OpenStack Networking (Neutron)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

2165 lines
98 KiB

  1. # Copyright 2011 VMware, Inc.
  2. # All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  5. # not use this file except in compliance with the License. You may obtain
  6. # a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. # License for the specific language governing permissions and limitations
  14. # under the License.
  15. import base64
  16. import collections
  17. import functools
  18. import hashlib
  19. import signal
  20. import sys
  21. import time
  22. import netaddr
  23. from neutron_lib import constants as n_const
  24. from oslo_config import cfg
  25. from oslo_log import log as logging
  26. import oslo_messaging
  27. from oslo_service import loopingcall
  28. from oslo_service import systemd
  29. from osprofiler import profiler
  30. import six
  31. from six import moves
  32. from neutron._i18n import _, _LE, _LI, _LW
  33. from neutron.agent.common import ip_lib
  34. from neutron.agent.common import ovs_lib
  35. from neutron.agent.common import polling
  36. from neutron.agent.common import utils
  37. from neutron.agent.l2.extensions import manager as ext_manager
  38. from neutron.agent import rpc as agent_rpc
  39. from neutron.agent import securitygroups_rpc as sg_rpc
  40. from neutron.api.rpc.callbacks import resources
  41. from neutron.api.rpc.handlers import dvr_rpc
  42. from neutron.common import config
  43. from neutron.common import constants as c_const
  44. from neutron.common import ipv6_utils as ipv6
  45. from neutron.common import topics
  46. from neutron.common import utils as n_utils
  47. from neutron import context
  48. from neutron.extensions import portbindings
  49. from neutron.plugins.common import constants as p_const
  50. from neutron.plugins.common import utils as p_utils
  51. from neutron.plugins.ml2.drivers.l2pop.rpc_manager import l2population_rpc
  52. from neutron.plugins.ml2.drivers.openvswitch.agent.common \
  53. import constants
  54. from neutron.plugins.ml2.drivers.openvswitch.agent \
  55. import ovs_agent_extension_api as ovs_ext_api
  56. from neutron.plugins.ml2.drivers.openvswitch.agent \
  57. import ovs_dvr_neutron_agent
  58. LOG = logging.getLogger(__name__)
  59. cfg.CONF.import_group('AGENT', 'neutron.plugins.ml2.drivers.openvswitch.'
  60. 'agent.common.config')
  61. cfg.CONF.import_group('OVS', 'neutron.plugins.ml2.drivers.openvswitch.agent.'
  62. 'common.config')
  63. class _mac_mydialect(netaddr.mac_unix):
  64. word_fmt = '%.2x'
  65. class LocalVLANMapping(object):
  66. def __init__(self, vlan, network_type, physical_network, segmentation_id,
  67. vif_ports=None):
  68. if vif_ports is None:
  69. vif_ports = {}
  70. self.vlan = vlan
  71. self.network_type = network_type
  72. self.physical_network = physical_network
  73. self.segmentation_id = segmentation_id
  74. self.vif_ports = vif_ports
  75. # set of tunnel ports on which packets should be flooded
  76. self.tun_ofports = set()
  77. def __str__(self):
  78. return ("lv-id = %s type = %s phys-net = %s phys-id = %s" %
  79. (self.vlan, self.network_type, self.physical_network,
  80. self.segmentation_id))
  81. class OVSPluginApi(agent_rpc.PluginApi):
  82. pass
  83. def has_zero_prefixlen_address(ip_addresses):
  84. return any(netaddr.IPNetwork(ip).prefixlen == 0 for ip in ip_addresses)
  85. @profiler.trace_cls("rpc")
  86. class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
  87. l2population_rpc.L2populationRpcCallBackTunnelMixin,
  88. dvr_rpc.DVRAgentRpcCallbackMixin):
  89. '''Implements OVS-based tunneling, VLANs and flat networks.
  90. Two local bridges are created: an integration bridge (defaults to
  91. 'br-int') and a tunneling bridge (defaults to 'br-tun'). An
  92. additional bridge is created for each physical network interface
  93. used for VLANs and/or flat networks.
  94. All VM VIFs are plugged into the integration bridge. VM VIFs on a
  95. given virtual network share a common "local" VLAN (i.e. not
  96. propagated externally). The VLAN id of this local VLAN is mapped
  97. to the physical networking details realizing that virtual network.
  98. For virtual networks realized as GRE tunnels, a Logical Switch
  99. (LS) identifier is used to differentiate tenant traffic on
  100. inter-HV tunnels. A mesh of tunnels is created to other
  101. Hypervisors in the cloud. These tunnels originate and terminate on
  102. the tunneling bridge of each hypervisor. Port patching is done to
  103. connect local VLANs on the integration bridge to inter-hypervisor
  104. tunnels on the tunnel bridge.
  105. For each virtual network realized as a VLAN or flat network, a
  106. veth or a pair of patch ports is used to connect the local VLAN on
  107. the integration bridge with the physical network bridge, with flow
  108. rules adding, modifying, or stripping VLAN tags as necessary.
  109. '''
  110. # history
  111. # 1.0 Initial version
  112. # 1.1 Support Security Group RPC
  113. # 1.2 Support DVR (Distributed Virtual Router) RPC
  114. # 1.3 Added param devices_to_update to security_groups_provider_updated
  115. # 1.4 Added support for network_update
  116. target = oslo_messaging.Target(version='1.4')
  117. def __init__(self, bridge_classes, conf=None):
  118. '''Constructor.
  119. :param bridge_classes: a dict for bridge classes.
  120. :param conf: an instance of ConfigOpts
  121. '''
  122. super(OVSNeutronAgent, self).__init__()
  123. self.conf = conf or cfg.CONF
  124. self.ovs = ovs_lib.BaseOVS()
  125. agent_conf = self.conf.AGENT
  126. ovs_conf = self.conf.OVS
  127. self.fullsync = False
  128. # init bridge classes with configured datapath type.
  129. self.br_int_cls, self.br_phys_cls, self.br_tun_cls = (
  130. functools.partial(bridge_classes[b],
  131. datapath_type=ovs_conf.datapath_type)
  132. for b in ('br_int', 'br_phys', 'br_tun'))
  133. self.use_veth_interconnection = ovs_conf.use_veth_interconnection
  134. self.veth_mtu = agent_conf.veth_mtu
  135. self.available_local_vlans = set(moves.range(p_const.MIN_VLAN_TAG,
  136. p_const.MAX_VLAN_TAG))
  137. self.tunnel_types = agent_conf.tunnel_types or []
  138. self.l2_pop = agent_conf.l2_population
  139. # TODO(ethuleau): Change ARP responder so it's not dependent on the
  140. # ML2 l2 population mechanism driver.
  141. self.enable_distributed_routing = agent_conf.enable_distributed_routing
  142. self.arp_responder_enabled = agent_conf.arp_responder and self.l2_pop
  143. host = self.conf.host
  144. self.agent_id = 'ovs-agent-%s' % host
  145. if self.tunnel_types:
  146. self.enable_tunneling = True
  147. else:
  148. self.enable_tunneling = False
  149. # Validate agent configurations
  150. self._check_agent_configurations()
  151. # Keep track of int_br's device count for use by _report_state()
  152. self.int_br_device_count = 0
  153. self.int_br = self.br_int_cls(ovs_conf.integration_bridge)
  154. self.setup_integration_br()
  155. # Stores port update notifications for processing in main rpc loop
  156. self.updated_ports = set()
  157. # Stores port delete notifications
  158. self.deleted_ports = set()
  159. self.network_ports = collections.defaultdict(set)
  160. # keeps association between ports and ofports to detect ofport change
  161. self.vifname_to_ofport_map = {}
  162. self.setup_rpc()
  163. self.bridge_mappings = self._parse_bridge_mappings(
  164. ovs_conf.bridge_mappings)
  165. self.setup_physical_bridges(self.bridge_mappings)
  166. self.local_vlan_map = {}
  167. self._reset_tunnel_ofports()
  168. self.polling_interval = agent_conf.polling_interval
  169. self.minimize_polling = agent_conf.minimize_polling
  170. self.ovsdb_monitor_respawn_interval = (
  171. agent_conf.ovsdb_monitor_respawn_interval or
  172. constants.DEFAULT_OVSDBMON_RESPAWN)
  173. self.local_ip = ovs_conf.local_ip
  174. self.tunnel_count = 0
  175. self.vxlan_udp_port = agent_conf.vxlan_udp_port
  176. self.dont_fragment = agent_conf.dont_fragment
  177. self.tunnel_csum = agent_conf.tunnel_csum
  178. self.tun_br = None
  179. self.patch_int_ofport = constants.OFPORT_INVALID
  180. self.patch_tun_ofport = constants.OFPORT_INVALID
  181. if self.enable_tunneling:
  182. # The patch_int_ofport and patch_tun_ofport are updated
  183. # here inside the call to setup_tunnel_br()
  184. self.setup_tunnel_br(ovs_conf.tunnel_bridge)
  185. self.init_extension_manager(self.connection)
  186. self.dvr_agent = ovs_dvr_neutron_agent.OVSDVRNeutronAgent(
  187. self.context,
  188. self.dvr_plugin_rpc,
  189. self.int_br,
  190. self.tun_br,
  191. self.bridge_mappings,
  192. self.phys_brs,
  193. self.int_ofports,
  194. self.phys_ofports,
  195. self.patch_int_ofport,
  196. self.patch_tun_ofport,
  197. host,
  198. self.enable_tunneling,
  199. self.enable_distributed_routing)
  200. if self.enable_tunneling:
  201. self.setup_tunnel_br_flows()
  202. self.dvr_agent.setup_dvr_flows()
  203. # Collect additional bridges to monitor
  204. self.ancillary_brs = self.setup_ancillary_bridges(
  205. ovs_conf.integration_bridge, ovs_conf.tunnel_bridge)
  206. # In order to keep existed device's local vlan unchanged,
  207. # restore local vlan mapping at start
  208. self._restore_local_vlan_map()
  209. # Security group agent support
  210. self.sg_agent = sg_rpc.SecurityGroupAgentRpc(self.context,
  211. self.sg_plugin_rpc, self.local_vlan_map,
  212. defer_refresh_firewall=True, integration_bridge=self.int_br)
  213. # we default to False to provide backward compat with out of tree
  214. # firewall drivers that expect the logic that existed on the Neutron
  215. # server which only enabled hybrid plugging based on the use of the
  216. # hybrid driver.
  217. hybrid_plug = getattr(self.sg_agent.firewall,
  218. 'OVS_HYBRID_PLUG_REQUIRED', False)
  219. self.prevent_arp_spoofing = (
  220. agent_conf.prevent_arp_spoofing and
  221. not self.sg_agent.firewall.provides_arp_spoofing_protection)
  222. #TODO(mangelajo): optimize resource_versions to only report
  223. # versions about resources which are common,
  224. # or which are used by specific extensions.
  225. self.agent_state = {
  226. 'binary': 'neutron-openvswitch-agent',
  227. 'host': host,
  228. 'topic': n_const.L2_AGENT_TOPIC,
  229. 'configurations': {'bridge_mappings': self.bridge_mappings,
  230. 'tunnel_types': self.tunnel_types,
  231. 'tunneling_ip': self.local_ip,
  232. 'l2_population': self.l2_pop,
  233. 'arp_responder_enabled':
  234. self.arp_responder_enabled,
  235. 'enable_distributed_routing':
  236. self.enable_distributed_routing,
  237. 'log_agent_heartbeats':
  238. agent_conf.log_agent_heartbeats,
  239. 'extensions': self.ext_manager.names(),
  240. 'datapath_type': ovs_conf.datapath_type,
  241. 'ovs_capabilities': self.ovs.capabilities,
  242. 'vhostuser_socket_dir':
  243. ovs_conf.vhostuser_socket_dir,
  244. portbindings.OVS_HYBRID_PLUG: hybrid_plug},
  245. 'resource_versions': resources.LOCAL_RESOURCE_VERSIONS,
  246. 'agent_type': agent_conf.agent_type,
  247. 'start_flag': True}
  248. report_interval = agent_conf.report_interval
  249. if report_interval:
  250. heartbeat = loopingcall.FixedIntervalLoopingCall(
  251. self._report_state)
  252. heartbeat.start(interval=report_interval)
  253. # Initialize iteration counter
  254. self.iter_num = 0
  255. self.run_daemon_loop = True
  256. self.catch_sigterm = False
  257. self.catch_sighup = False
  258. # The initialization is complete; we can start receiving messages
  259. self.connection.consume_in_threads()
  260. self.quitting_rpc_timeout = agent_conf.quitting_rpc_timeout
  261. def _parse_bridge_mappings(self, bridge_mappings):
  262. try:
  263. return n_utils.parse_mappings(bridge_mappings)
  264. except ValueError as e:
  265. raise ValueError(_("Parsing bridge_mappings failed: %s.") % e)
  266. def _report_state(self):
  267. # How many devices are likely used by a VM
  268. self.agent_state.get('configurations')['devices'] = (
  269. self.int_br_device_count)
  270. self.agent_state.get('configurations')['in_distributed_mode'] = (
  271. self.dvr_agent.in_distributed_mode())
  272. try:
  273. agent_status = self.state_rpc.report_state(self.context,
  274. self.agent_state,
  275. True)
  276. if agent_status == c_const.AGENT_REVIVED:
  277. LOG.info(_LI('Agent has just been revived. '
  278. 'Doing a full sync.'))
  279. self.fullsync = True
  280. # we only want to update resource versions on startup
  281. self.agent_state.pop('resource_versions', None)
  282. if self.agent_state.pop('start_flag', None):
  283. # On initial start, we notify systemd after initialization
  284. # is complete.
  285. systemd.notify_once()
  286. except Exception:
  287. LOG.exception(_LE("Failed reporting state!"))
  288. def _restore_local_vlan_map(self):
  289. self._local_vlan_hints = {}
  290. cur_ports = self.int_br.get_vif_ports()
  291. port_names = [p.port_name for p in cur_ports]
  292. port_info = self.int_br.get_ports_attributes(
  293. "Port", columns=["name", "other_config", "tag"], ports=port_names)
  294. by_name = {x['name']: x for x in port_info}
  295. for port in cur_ports:
  296. # if a port was deleted between get_vif_ports and
  297. # get_ports_attributes, we
  298. # will get a KeyError
  299. try:
  300. local_vlan_map = by_name[port.port_name]['other_config']
  301. local_vlan = by_name[port.port_name]['tag']
  302. except KeyError:
  303. continue
  304. if not local_vlan:
  305. continue
  306. net_uuid = local_vlan_map.get('net_uuid')
  307. if (net_uuid and net_uuid not in self._local_vlan_hints
  308. and local_vlan != constants.DEAD_VLAN_TAG):
  309. self.available_local_vlans.discard(local_vlan)
  310. self._local_vlan_hints[local_vlan_map['net_uuid']] = \
  311. local_vlan
  312. def _dispose_local_vlan_hints(self):
  313. self.available_local_vlans.update(self._local_vlan_hints.values())
  314. self._local_vlan_hints = {}
  315. def _reset_tunnel_ofports(self):
  316. self.tun_br_ofports = {p_const.TYPE_GENEVE: {},
  317. p_const.TYPE_GRE: {},
  318. p_const.TYPE_VXLAN: {}}
  319. def setup_rpc(self):
  320. self.plugin_rpc = OVSPluginApi(topics.PLUGIN)
  321. self.sg_plugin_rpc = sg_rpc.SecurityGroupServerRpcApi(topics.PLUGIN)
  322. self.dvr_plugin_rpc = dvr_rpc.DVRServerRpcApi(topics.PLUGIN)
  323. self.state_rpc = agent_rpc.PluginReportStateAPI(topics.REPORTS)
  324. # RPC network init
  325. self.context = context.get_admin_context_without_session()
  326. # Define the listening consumers for the agent
  327. consumers = [[topics.PORT, topics.UPDATE],
  328. [topics.PORT, topics.DELETE],
  329. [constants.TUNNEL, topics.UPDATE],
  330. [constants.TUNNEL, topics.DELETE],
  331. [topics.SECURITY_GROUP, topics.UPDATE],
  332. [topics.DVR, topics.UPDATE],
  333. [topics.NETWORK, topics.UPDATE]]
  334. if self.l2_pop:
  335. consumers.append([topics.L2POPULATION, topics.UPDATE])
  336. self.connection = agent_rpc.create_consumers([self],
  337. topics.AGENT,
  338. consumers,
  339. start_listening=False)
  340. def init_extension_manager(self, connection):
  341. ext_manager.register_opts(self.conf)
  342. self.ext_manager = (
  343. ext_manager.AgentExtensionsManager(self.conf))
  344. self.agent_api = ovs_ext_api.OVSAgentExtensionAPI(self.int_br,
  345. self.tun_br)
  346. self.ext_manager.initialize(
  347. connection, constants.EXTENSION_DRIVER_TYPE,
  348. self.agent_api)
  349. def get_net_uuid(self, vif_id):
  350. for network_id, vlan_mapping in six.iteritems(self.local_vlan_map):
  351. if vif_id in vlan_mapping.vif_ports:
  352. return network_id
  353. def port_update(self, context, **kwargs):
  354. port = kwargs.get('port')
  355. # Put the port identifier in the updated_ports set.
  356. # Even if full port details might be provided to this call,
  357. # they are not used since there is no guarantee the notifications
  358. # are processed in the same order as the relevant API requests
  359. self.updated_ports.add(port['id'])
  360. LOG.debug("port_update message processed for port %s", port['id'])
  361. def port_delete(self, context, **kwargs):
  362. port_id = kwargs.get('port_id')
  363. self.deleted_ports.add(port_id)
  364. self.updated_ports.discard(port_id)
  365. LOG.debug("port_delete message processed for port %s", port_id)
  366. def network_update(self, context, **kwargs):
  367. network_id = kwargs['network']['id']
  368. for port_id in self.network_ports[network_id]:
  369. # notifications could arrive out of order, if the port is deleted
  370. # we don't want to update it anymore
  371. if port_id not in self.deleted_ports:
  372. self.updated_ports.add(port_id)
  373. LOG.debug("network_update message processed for network "
  374. "%(network_id)s, with ports: %(ports)s",
  375. {'network_id': network_id,
  376. 'ports': self.network_ports[network_id]})
  377. def _clean_network_ports(self, port_id):
  378. for port_set in self.network_ports.values():
  379. if port_id in port_set:
  380. port_set.remove(port_id)
  381. break
  382. def process_deleted_ports(self, port_info):
  383. # don't try to process removed ports as deleted ports since
  384. # they are already gone
  385. if 'removed' in port_info:
  386. self.deleted_ports -= port_info['removed']
  387. deleted_ports = list(self.deleted_ports)
  388. while self.deleted_ports:
  389. port_id = self.deleted_ports.pop()
  390. port = self.int_br.get_vif_port_by_id(port_id)
  391. self._clean_network_ports(port_id)
  392. self.ext_manager.delete_port(self.context,
  393. {"vif_port": port,
  394. "port_id": port_id})
  395. # move to dead VLAN so deleted ports no
  396. # longer have access to the network
  397. if port:
  398. # don't log errors since there is a chance someone will be
  399. # removing the port from the bridge at the same time
  400. self.port_dead(port, log_errors=False)
  401. self.port_unbound(port_id)
  402. # Flush firewall rules after ports are put on dead VLAN to be
  403. # more secure
  404. self.sg_agent.remove_devices_filter(deleted_ports)
  405. def tunnel_update(self, context, **kwargs):
  406. LOG.debug("tunnel_update received")
  407. if not self.enable_tunneling:
  408. return
  409. tunnel_ip = kwargs.get('tunnel_ip')
  410. tunnel_type = kwargs.get('tunnel_type')
  411. if not tunnel_type:
  412. LOG.error(_LE("No tunnel_type specified, cannot create tunnels"))
  413. return
  414. if tunnel_type not in self.tunnel_types:
  415. LOG.error(_LE("tunnel_type %s not supported by agent"),
  416. tunnel_type)
  417. return
  418. if tunnel_ip == self.local_ip:
  419. return
  420. tun_name = self.get_tunnel_name(tunnel_type, self.local_ip, tunnel_ip)
  421. if tun_name is None:
  422. return
  423. if not self.l2_pop:
  424. self._setup_tunnel_port(self.tun_br, tun_name, tunnel_ip,
  425. tunnel_type)
  426. def tunnel_delete(self, context, **kwargs):
  427. LOG.debug("tunnel_delete received")
  428. if not self.enable_tunneling:
  429. return
  430. tunnel_ip = kwargs.get('tunnel_ip')
  431. if not tunnel_ip:
  432. LOG.error(_LE("No tunnel_ip specified, cannot delete tunnels"))
  433. return
  434. tunnel_type = kwargs.get('tunnel_type')
  435. if not tunnel_type:
  436. LOG.error(_LE("No tunnel_type specified, cannot delete tunnels"))
  437. return
  438. if tunnel_type not in self.tunnel_types:
  439. LOG.error(_LE("tunnel_type %s not supported by agent"),
  440. tunnel_type)
  441. return
  442. ofport = self.tun_br_ofports[tunnel_type].get(tunnel_ip)
  443. self.cleanup_tunnel_port(self.tun_br, ofport, tunnel_type)
  444. def _tunnel_port_lookup(self, network_type, remote_ip):
  445. return self.tun_br_ofports[network_type].get(remote_ip)
  446. def fdb_add(self, context, fdb_entries):
  447. LOG.debug("fdb_add received")
  448. for lvm, agent_ports in self.get_agent_ports(fdb_entries,
  449. self.local_vlan_map):
  450. agent_ports.pop(self.local_ip, None)
  451. if len(agent_ports):
  452. if not self.enable_distributed_routing:
  453. with self.tun_br.deferred() as deferred_br:
  454. self.fdb_add_tun(context, deferred_br, lvm,
  455. agent_ports, self._tunnel_port_lookup)
  456. else:
  457. self.fdb_add_tun(context, self.tun_br, lvm,
  458. agent_ports, self._tunnel_port_lookup)
  459. def fdb_remove(self, context, fdb_entries):
  460. LOG.debug("fdb_remove received")
  461. for lvm, agent_ports in self.get_agent_ports(fdb_entries,
  462. self.local_vlan_map):
  463. agent_ports.pop(self.local_ip, None)
  464. if len(agent_ports):
  465. if not self.enable_distributed_routing:
  466. with self.tun_br.deferred() as deferred_br:
  467. self.fdb_remove_tun(context, deferred_br, lvm,
  468. agent_ports,
  469. self._tunnel_port_lookup)
  470. else:
  471. self.fdb_remove_tun(context, self.tun_br, lvm,
  472. agent_ports, self._tunnel_port_lookup)
  473. def add_fdb_flow(self, br, port_info, remote_ip, lvm, ofport):
  474. if port_info == n_const.FLOODING_ENTRY:
  475. lvm.tun_ofports.add(ofport)
  476. br.install_flood_to_tun(lvm.vlan, lvm.segmentation_id,
  477. lvm.tun_ofports)
  478. else:
  479. self.setup_entry_for_arp_reply(br, 'add', lvm.vlan,
  480. port_info.mac_address,
  481. port_info.ip_address)
  482. br.install_unicast_to_tun(lvm.vlan,
  483. lvm.segmentation_id,
  484. ofport,
  485. port_info.mac_address)
  486. def del_fdb_flow(self, br, port_info, remote_ip, lvm, ofport):
  487. if port_info == n_const.FLOODING_ENTRY:
  488. if ofport not in lvm.tun_ofports:
  489. LOG.debug("attempt to remove a non-existent port %s", ofport)
  490. return
  491. lvm.tun_ofports.remove(ofport)
  492. if len(lvm.tun_ofports) > 0:
  493. br.install_flood_to_tun(lvm.vlan, lvm.segmentation_id,
  494. lvm.tun_ofports)
  495. else:
  496. # This local vlan doesn't require any more tunneling
  497. br.delete_flood_to_tun(lvm.vlan)
  498. else:
  499. self.setup_entry_for_arp_reply(br, 'remove', lvm.vlan,
  500. port_info.mac_address,
  501. port_info.ip_address)
  502. br.delete_unicast_to_tun(lvm.vlan, port_info.mac_address)
  503. def _fdb_chg_ip(self, context, fdb_entries):
  504. LOG.debug("update chg_ip received")
  505. with self.tun_br.deferred() as deferred_br:
  506. self.fdb_chg_ip_tun(context, deferred_br, fdb_entries,
  507. self.local_ip, self.local_vlan_map)
  508. def setup_entry_for_arp_reply(self, br, action, local_vid, mac_address,
  509. ip_address):
  510. '''Set the ARP respond entry.
  511. When the l2 population mechanism driver and OVS supports to edit ARP
  512. fields, a table (ARP_RESPONDER) to resolve ARP locally is added to the
  513. tunnel bridge.
  514. '''
  515. if not self.arp_responder_enabled:
  516. return
  517. ip = netaddr.IPAddress(ip_address)
  518. if ip.version == 6:
  519. return
  520. ip = str(ip)
  521. mac = str(netaddr.EUI(mac_address, dialect=_mac_mydialect))
  522. if action == 'add':
  523. br.install_arp_responder(local_vid, ip, mac)
  524. elif action == 'remove':
  525. br.delete_arp_responder(local_vid, ip)
  526. else:
  527. LOG.warning(_LW('Action %s not supported'), action)
  528. def _local_vlan_for_flat(self, lvid, physical_network):
  529. phys_br = self.phys_brs[physical_network]
  530. phys_port = self.phys_ofports[physical_network]
  531. int_br = self.int_br
  532. int_port = self.int_ofports[physical_network]
  533. phys_br.provision_local_vlan(port=phys_port, lvid=lvid,
  534. segmentation_id=None,
  535. distributed=False)
  536. int_br.provision_local_vlan(port=int_port, lvid=lvid,
  537. segmentation_id=None)
  538. def _local_vlan_for_vlan(self, lvid, physical_network, segmentation_id):
  539. distributed = self.enable_distributed_routing
  540. phys_br = self.phys_brs[physical_network]
  541. phys_port = self.phys_ofports[physical_network]
  542. int_br = self.int_br
  543. int_port = self.int_ofports[physical_network]
  544. phys_br.provision_local_vlan(port=phys_port, lvid=lvid,
  545. segmentation_id=segmentation_id,
  546. distributed=distributed)
  547. int_br.provision_local_vlan(port=int_port, lvid=lvid,
  548. segmentation_id=segmentation_id)
  549. def provision_local_vlan(self, net_uuid, network_type, physical_network,
  550. segmentation_id):
  551. '''Provisions a local VLAN.
  552. :param net_uuid: the uuid of the network associated with this vlan.
  553. :param network_type: the network type ('gre', 'vxlan', 'vlan', 'flat',
  554. 'local', 'geneve')
  555. :param physical_network: the physical network for 'vlan' or 'flat'
  556. :param segmentation_id: the VID for 'vlan' or tunnel ID for 'tunnel'
  557. '''
  558. # On a restart or crash of OVS, the network associated with this VLAN
  559. # will already be assigned, so check for that here before assigning a
  560. # new one.
  561. lvm = self.local_vlan_map.get(net_uuid)
  562. if lvm:
  563. lvid = lvm.vlan
  564. else:
  565. lvid = self._local_vlan_hints.pop(net_uuid, None)
  566. if lvid is None:
  567. if not self.available_local_vlans:
  568. LOG.error(_LE("No local VLAN available for net-id=%s"),
  569. net_uuid)
  570. return
  571. lvid = self.available_local_vlans.pop()
  572. self.local_vlan_map[net_uuid] = LocalVLANMapping(lvid,
  573. network_type,
  574. physical_network,
  575. segmentation_id)
  576. LOG.info(_LI("Assigning %(vlan_id)s as local vlan for "
  577. "net-id=%(net_uuid)s"),
  578. {'vlan_id': lvid, 'net_uuid': net_uuid})
  579. if network_type in constants.TUNNEL_NETWORK_TYPES:
  580. if self.enable_tunneling:
  581. # outbound broadcast/multicast
  582. ofports = list(self.tun_br_ofports[network_type].values())
  583. if ofports:
  584. self.tun_br.install_flood_to_tun(lvid,
  585. segmentation_id,
  586. ofports)
  587. # inbound from tunnels: set lvid in the right table
  588. # and resubmit to Table LEARN_FROM_TUN for mac learning
  589. if self.enable_distributed_routing:
  590. self.dvr_agent.process_tunneled_network(
  591. network_type, lvid, segmentation_id)
  592. else:
  593. self.tun_br.provision_local_vlan(
  594. network_type=network_type, lvid=lvid,
  595. segmentation_id=segmentation_id)
  596. else:
  597. LOG.error(_LE("Cannot provision %(network_type)s network for "
  598. "net-id=%(net_uuid)s - tunneling disabled"),
  599. {'network_type': network_type,
  600. 'net_uuid': net_uuid})
  601. elif network_type == p_const.TYPE_FLAT:
  602. if physical_network in self.phys_brs:
  603. self._local_vlan_for_flat(lvid, physical_network)
  604. else:
  605. LOG.error(_LE("Cannot provision flat network for "
  606. "net-id=%(net_uuid)s - no bridge for "
  607. "physical_network %(physical_network)s"),
  608. {'net_uuid': net_uuid,
  609. 'physical_network': physical_network})
  610. elif network_type == p_const.TYPE_VLAN:
  611. if physical_network in self.phys_brs:
  612. self._local_vlan_for_vlan(lvid, physical_network,
  613. segmentation_id)
  614. else:
  615. LOG.error(_LE("Cannot provision VLAN network for "
  616. "net-id=%(net_uuid)s - no bridge for "
  617. "physical_network %(physical_network)s"),
  618. {'net_uuid': net_uuid,
  619. 'physical_network': physical_network})
  620. elif network_type == p_const.TYPE_LOCAL:
  621. # no flows needed for local networks
  622. pass
  623. else:
  624. LOG.error(_LE("Cannot provision unknown network type "
  625. "%(network_type)s for net-id=%(net_uuid)s"),
  626. {'network_type': network_type,
  627. 'net_uuid': net_uuid})
  628. def reclaim_local_vlan(self, net_uuid):
  629. '''Reclaim a local VLAN.
  630. :param net_uuid: the network uuid associated with this vlan.
  631. '''
  632. lvm = self.local_vlan_map.pop(net_uuid, None)
  633. if lvm is None:
  634. LOG.debug("Network %s not used on agent.", net_uuid)
  635. return
  636. LOG.info(_LI("Reclaiming vlan = %(vlan_id)s from "
  637. "net-id = %(net_uuid)s"),
  638. {'vlan_id': lvm.vlan, 'net_uuid': net_uuid})
  639. if lvm.network_type in constants.TUNNEL_NETWORK_TYPES:
  640. if self.enable_tunneling:
  641. self.tun_br.reclaim_local_vlan(
  642. network_type=lvm.network_type,
  643. segmentation_id=lvm.segmentation_id)
  644. self.tun_br.delete_flood_to_tun(lvm.vlan)
  645. self.tun_br.delete_unicast_to_tun(lvm.vlan, None)
  646. self.tun_br.delete_arp_responder(lvm.vlan, None)
  647. if self.l2_pop:
  648. # Try to remove tunnel ports if not used by other networks
  649. for ofport in lvm.tun_ofports:
  650. self.cleanup_tunnel_port(self.tun_br, ofport,
  651. lvm.network_type)
  652. elif lvm.network_type == p_const.TYPE_FLAT:
  653. if lvm.physical_network in self.phys_brs:
  654. # outbound
  655. br = self.phys_brs[lvm.physical_network]
  656. br.reclaim_local_vlan(
  657. port=self.phys_ofports[lvm.physical_network],
  658. lvid=lvm.vlan)
  659. # inbound
  660. br = self.int_br
  661. br.reclaim_local_vlan(
  662. port=self.int_ofports[lvm.physical_network],
  663. segmentation_id=None)
  664. elif lvm.network_type == p_const.TYPE_VLAN:
  665. if lvm.physical_network in self.phys_brs:
  666. # outbound
  667. br = self.phys_brs[lvm.physical_network]
  668. br.reclaim_local_vlan(
  669. port=self.phys_ofports[lvm.physical_network],
  670. lvid=lvm.vlan)
  671. # inbound
  672. br = self.int_br
  673. br.reclaim_local_vlan(
  674. port=self.int_ofports[lvm.physical_network],
  675. segmentation_id=lvm.segmentation_id)
  676. elif lvm.network_type == p_const.TYPE_LOCAL:
  677. # no flows needed for local networks
  678. pass
  679. else:
  680. LOG.error(_LE("Cannot reclaim unknown network type "
  681. "%(network_type)s for net-id=%(net_uuid)s"),
  682. {'network_type': lvm.network_type,
  683. 'net_uuid': net_uuid})
  684. self.available_local_vlans.add(lvm.vlan)
  685. def port_bound(self, port, net_uuid,
  686. network_type, physical_network,
  687. segmentation_id, fixed_ips, device_owner,
  688. ovs_restarted):
  689. '''Bind port to net_uuid/lsw_id and install flow for inbound traffic
  690. to vm.
  691. :param port: an ovs_lib.VifPort object.
  692. :param net_uuid: the net_uuid this port is to be associated with.
  693. :param network_type: the network type ('gre', 'vlan', 'flat', 'local')
  694. :param physical_network: the physical network for 'vlan' or 'flat'
  695. :param segmentation_id: the VID for 'vlan' or tunnel ID for 'tunnel'
  696. :param fixed_ips: the ip addresses assigned to this port
  697. :param device_owner: the string indicative of owner of this port
  698. :param ovs_restarted: indicates if this is called for an OVS restart.
  699. '''
  700. if net_uuid not in self.local_vlan_map or ovs_restarted:
  701. self.provision_local_vlan(net_uuid, network_type,
  702. physical_network, segmentation_id)
  703. lvm = self.local_vlan_map[net_uuid]
  704. lvm.vif_ports[port.vif_id] = port
  705. self.dvr_agent.bind_port_to_dvr(port, lvm,
  706. fixed_ips,
  707. device_owner)
  708. port_other_config = self.int_br.db_get_val("Port", port.port_name,
  709. "other_config")
  710. if port_other_config is None:
  711. if port.vif_id in self.deleted_ports:
  712. LOG.debug("Port %s deleted concurrently", port.vif_id)
  713. elif port.vif_id in self.updated_ports:
  714. LOG.error(_LE("Expected port %s not found"), port.vif_id)
  715. else:
  716. LOG.debug("Unable to get config for port %s", port.vif_id)
  717. return False
  718. vlan_mapping = {'net_uuid': net_uuid,
  719. 'network_type': network_type,
  720. 'physical_network': physical_network}
  721. if segmentation_id is not None:
  722. vlan_mapping['segmentation_id'] = segmentation_id
  723. port_other_config.update(vlan_mapping)
  724. self.int_br.set_db_attribute("Port", port.port_name, "other_config",
  725. port_other_config)
  726. return True
  727. def _add_port_tag_info(self, need_binding_ports):
  728. port_names = [p['vif_port'].port_name for p in need_binding_ports]
  729. port_info = self.int_br.get_ports_attributes(
  730. "Port", columns=["name", "tag", "other_config"],
  731. ports=port_names, if_exists=True)
  732. info_by_port = {x['name']: [x['tag'], x['other_config']]
  733. for x in port_info}
  734. for port_detail in need_binding_ports:
  735. lvm = self.local_vlan_map.get(port_detail['network_id'])
  736. if not lvm:
  737. continue
  738. port = port_detail['vif_port']
  739. cur_info = info_by_port.get(port.port_name)
  740. if cur_info is not None and cur_info[0] != lvm.vlan:
  741. other_config = cur_info[1] or {}
  742. other_config['tag'] = lvm.vlan
  743. self.int_br.set_db_attribute(
  744. "Port", port.port_name, "other_config", other_config)
  745. def _bind_devices(self, need_binding_ports):
  746. devices_up = []
  747. devices_down = []
  748. failed_devices = []
  749. port_names = [p['vif_port'].port_name for p in need_binding_ports]
  750. port_info = self.int_br.get_ports_attributes(
  751. "Port", columns=["name", "tag"], ports=port_names, if_exists=True)
  752. tags_by_name = {x['name']: x['tag'] for x in port_info}
  753. for port_detail in need_binding_ports:
  754. lvm = self.local_vlan_map.get(port_detail['network_id'])
  755. if not lvm:
  756. # network for port was deleted. skip this port since it
  757. # will need to be handled as a DEAD port in the next scan
  758. continue
  759. port = port_detail['vif_port']
  760. device = port_detail['device']
  761. # Do not bind a port if it's already bound
  762. cur_tag = tags_by_name.get(port.port_name)
  763. if cur_tag is None:
  764. LOG.debug("Port %s was deleted concurrently, skipping it",
  765. port.port_name)
  766. continue
  767. # Uninitialized port has tag set to []
  768. if cur_tag and cur_tag != lvm.vlan:
  769. self.int_br.delete_flows(in_port=port.ofport)
  770. if self.prevent_arp_spoofing:
  771. self.setup_arp_spoofing_protection(self.int_br,
  772. port, port_detail)
  773. if cur_tag != lvm.vlan:
  774. self.int_br.set_db_attribute(
  775. "Port", port.port_name, "tag", lvm.vlan)
  776. # update plugin about port status
  777. # FIXME(salv-orlando): Failures while updating device status
  778. # must be handled appropriately. Otherwise this might prevent
  779. # neutron server from sending network-vif-* events to the nova
  780. # API server, thus possibly preventing instance spawn.
  781. if port_detail.get('admin_state_up'):
  782. LOG.debug("Setting status for %s to UP", device)
  783. devices_up.append(device)
  784. else:
  785. LOG.debug("Setting status for %s to DOWN", device)
  786. devices_down.append(device)
  787. if devices_up or devices_down:
  788. devices_set = self.plugin_rpc.update_device_list(
  789. self.context, devices_up, devices_down, self.agent_id,
  790. self.conf.host)
  791. failed_devices = (devices_set.get('failed_devices_up') +
  792. devices_set.get('failed_devices_down'))
  793. if failed_devices:
  794. LOG.error(_LE("Configuration for devices %s failed!"),
  795. failed_devices)
  796. LOG.info(_LI("Configuration for devices up %(up)s and devices "
  797. "down %(down)s completed."),
  798. {'up': devices_up, 'down': devices_down})
  799. return set(failed_devices)
  800. @staticmethod
  801. def setup_arp_spoofing_protection(bridge, vif, port_details):
  802. if not port_details.get('port_security_enabled', True):
  803. LOG.info(_LI("Skipping ARP spoofing rules for port '%s' because "
  804. "it has port security disabled"), vif.port_name)
  805. bridge.delete_arp_spoofing_protection(port=vif.ofport)
  806. bridge.set_allowed_macs_for_port(port=vif.ofport, allow_all=True)
  807. return
  808. if port_details['device_owner'].startswith(
  809. n_const.DEVICE_OWNER_NETWORK_PREFIX):
  810. LOG.debug("Skipping ARP spoofing rules for network owned port "
  811. "'%s'.", vif.port_name)
  812. bridge.delete_arp_spoofing_protection(port=vif.ofport)
  813. bridge.set_allowed_macs_for_port(port=vif.ofport, allow_all=True)
  814. return
  815. # clear any previous flows related to this port in our ARP table
  816. bridge.delete_arp_spoofing_allow_rules(port=vif.ofport)
  817. # collect all of the addresses and cidrs that belong to the port
  818. addresses = {f['ip_address'] for f in port_details['fixed_ips']}
  819. mac_addresses = {vif.vif_mac}
  820. if port_details.get('allowed_address_pairs'):
  821. addresses |= {p['ip_address']
  822. for p in port_details['allowed_address_pairs']}
  823. mac_addresses |= {p['mac_address']
  824. for p in port_details['allowed_address_pairs']
  825. if p.get('mac_address')}
  826. bridge.set_allowed_macs_for_port(vif.ofport, mac_addresses)
  827. ipv6_addresses = {ip for ip in addresses
  828. if netaddr.IPNetwork(ip).version == 6}
  829. # Allow neighbor advertisements for LLA address.
  830. ipv6_addresses |= {str(ipv6.get_ipv6_addr_by_EUI64(
  831. n_const.IPv6_LLA_PREFIX, mac))
  832. for mac in mac_addresses}
  833. if not has_zero_prefixlen_address(ipv6_addresses):
  834. # Install protection only when prefix is not zero because a /0
  835. # prefix allows any address anyway and the nd_target can only
  836. # match on /1 or more.
  837. bridge.install_icmpv6_na_spoofing_protection(port=vif.ofport,
  838. ip_addresses=ipv6_addresses)
  839. ipv4_addresses = {ip for ip in addresses
  840. if netaddr.IPNetwork(ip).version == 4}
  841. if not has_zero_prefixlen_address(ipv4_addresses):
  842. # Install protection only when prefix is not zero because a /0
  843. # prefix allows any address anyway and the ARP_SPA can only
  844. # match on /1 or more.
  845. bridge.install_arp_spoofing_protection(port=vif.ofport,
  846. ip_addresses=ipv4_addresses)
  847. else:
  848. bridge.delete_arp_spoofing_protection(port=vif.ofport)
  849. def port_unbound(self, vif_id, net_uuid=None):
  850. '''Unbind port.
  851. Removes corresponding local vlan mapping object if this is its last
  852. VIF.
  853. :param vif_id: the id of the vif
  854. :param net_uuid: the net_uuid this port is associated with.
  855. '''
  856. if net_uuid is None:
  857. net_uuid = self.get_net_uuid(vif_id)
  858. if not self.local_vlan_map.get(net_uuid):
  859. LOG.info(_LI('port_unbound(): net_uuid %s not in local_vlan_map'),
  860. net_uuid)
  861. return
  862. lvm = self.local_vlan_map[net_uuid]
  863. if vif_id in lvm.vif_ports:
  864. vif_port = lvm.vif_ports[vif_id]
  865. self.dvr_agent.unbind_port_from_dvr(vif_port, lvm)
  866. lvm.vif_ports.pop(vif_id, None)
  867. if not lvm.vif_ports:
  868. self.reclaim_local_vlan(net_uuid)
  869. def port_dead(self, port, log_errors=True):
  870. '''Once a port has no binding, put it on the "dead vlan".
  871. :param port: an ovs_lib.VifPort object.
  872. '''
  873. # Don't kill a port if it's already dead
  874. cur_tag = self.int_br.db_get_val("Port", port.port_name, "tag",
  875. log_errors=log_errors)
  876. if cur_tag and cur_tag != constants.DEAD_VLAN_TAG:
  877. self.int_br.set_db_attribute("Port", port.port_name, "tag",
  878. constants.DEAD_VLAN_TAG,
  879. log_errors=log_errors)
  880. self.int_br.drop_port(in_port=port.ofport)
  881. def setup_integration_br(self):
  882. '''Setup the integration bridge.
  883. '''
  884. # Ensure the integration bridge is created.
  885. # ovs_lib.OVSBridge.create() will run
  886. # ovs-vsctl -- --may-exist add-br BRIDGE_NAME
  887. # which does nothing if bridge already exists.
  888. self.int_br.create()
  889. self.int_br.set_secure_mode()
  890. self.int_br.setup_controllers(self.conf)
  891. if self.conf.AGENT.drop_flows_on_start:
  892. # Delete the patch port between br-int and br-tun if we're deleting
  893. # the flows on br-int, so that traffic doesn't get flooded over
  894. # while flows are missing.
  895. self.int_br.delete_port(self.conf.OVS.int_peer_patch_port)
  896. self.int_br.delete_flows()
  897. self.int_br.setup_default_table()
  898. def setup_ancillary_bridges(self, integ_br, tun_br):
  899. '''Setup ancillary bridges - for example br-ex.'''
  900. ovs = ovs_lib.BaseOVS()
  901. ovs_bridges = set(ovs.get_bridges())
  902. # Remove all known bridges
  903. ovs_bridges.remove(integ_br)
  904. if self.enable_tunneling:
  905. ovs_bridges.remove(tun_br)
  906. br_names = [self.phys_brs[physical_network].br_name for
  907. physical_network in self.phys_brs]
  908. ovs_bridges.difference_update(br_names)
  909. # Filter list of bridges to those that have external
  910. # bridge-id's configured
  911. br_names = []
  912. for bridge in ovs_bridges:
  913. bridge_id = ovs.get_bridge_external_bridge_id(bridge)
  914. if bridge_id != bridge:
  915. br_names.append(bridge)
  916. ovs_bridges.difference_update(br_names)
  917. ancillary_bridges = []
  918. for bridge in ovs_bridges:
  919. br = ovs_lib.OVSBridge(bridge)
  920. LOG.info(_LI('Adding %s to list of bridges.'), bridge)
  921. ancillary_bridges.append(br)
  922. return ancillary_bridges
  923. def setup_tunnel_br(self, tun_br_name=None):
  924. '''(re)initialize the tunnel bridge.
  925. Creates tunnel bridge, and links it to the integration bridge
  926. using a patch port.
  927. :param tun_br_name: the name of the tunnel bridge.
  928. '''
  929. if not self.tun_br:
  930. self.tun_br = self.br_tun_cls(tun_br_name)
  931. # tun_br.create() won't recreate bridge if it exists, but will handle
  932. # cases where something like datapath_type has changed
  933. self.tun_br.create(secure_mode=True)
  934. self.tun_br.setup_controllers(self.conf)
  935. if (not self.int_br.port_exists(self.conf.OVS.int_peer_patch_port) or
  936. self.patch_tun_ofport == ovs_lib.INVALID_OFPORT):
  937. self.patch_tun_ofport = self.int_br.add_patch_port(
  938. self.conf.OVS.int_peer_patch_port,
  939. self.conf.OVS.tun_peer_patch_port)
  940. if (not self.tun_br.port_exists(self.conf.OVS.tun_peer_patch_port) or
  941. self.patch_int_ofport == ovs_lib.INVALID_OFPORT):
  942. self.patch_int_ofport = self.tun_br.add_patch_port(
  943. self.conf.OVS.tun_peer_patch_port,
  944. self.conf.OVS.int_peer_patch_port)
  945. if ovs_lib.INVALID_OFPORT in (self.patch_tun_ofport,
  946. self.patch_int_ofport):
  947. LOG.error(_LE("Failed to create OVS patch port. Cannot have "
  948. "tunneling enabled on this agent, since this "
  949. "version of OVS does not support tunnels or patch "
  950. "ports. Agent terminated!"))
  951. sys.exit(1)
  952. if self.conf.AGENT.drop_flows_on_start:
  953. self.tun_br.delete_flows()
  954. def setup_tunnel_br_flows(self):
  955. '''Setup the tunnel bridge.
  956. Add all flows to the tunnel bridge.
  957. '''
  958. self.tun_br.setup_default_table(self.patch_int_ofport,
  959. self.arp_responder_enabled)
  960. def setup_physical_bridges(self, bridge_mappings):
  961. '''Setup the physical network bridges.
  962. Creates physical network bridges and links them to the
  963. integration bridge using veths or patch ports.
  964. :param bridge_mappings: map physical network names to bridge names.
  965. '''
  966. self.phys_brs = {}
  967. self.int_ofports = {}
  968. self.phys_ofports = {}
  969. ip_wrapper = ip_lib.IPWrapper()
  970. ovs = ovs_lib.BaseOVS()
  971. ovs_bridges = ovs.get_bridges()
  972. for physical_network, bridge in six.iteritems(bridge_mappings):
  973. LOG.info(_LI("Mapping physical network %(physical_network)s to "
  974. "bridge %(bridge)s"),
  975. {'physical_network': physical_network,
  976. 'bridge': bridge})
  977. # setup physical bridge
  978. if bridge not in ovs_bridges:
  979. LOG.error(_LE("Bridge %(bridge)s for physical network "
  980. "%(physical_network)s does not exist. Agent "
  981. "terminated!"),
  982. {'physical_network': physical_network,
  983. 'bridge': bridge})
  984. sys.exit(1)
  985. br = self.br_phys_cls(bridge)
  986. # The bridge already exists, so create won't recreate it, but will
  987. # handle things like changing the datapath_type
  988. br.create()
  989. br.setup_controllers(self.conf)
  990. if cfg.CONF.AGENT.drop_flows_on_start:
  991. br.delete_flows()
  992. br.setup_default_table()
  993. self.phys_brs[physical_network] = br
  994. # interconnect physical and integration bridges using veth/patches
  995. int_if_name = p_utils.get_interface_name(
  996. bridge, prefix=constants.PEER_INTEGRATION_PREFIX)
  997. phys_if_name = p_utils.get_interface_name(
  998. bridge, prefix=constants.PEER_PHYSICAL_PREFIX)
  999. # Interface type of port for physical and integration bridges must
  1000. # be same, so check only one of them.
  1001. # Not logging error here, as the interface may not exist yet.
  1002. # Type check is done to cleanup wrong interface if any.
  1003. int_type = self.int_br.db_get_val("Interface",
  1004. int_if_name, "type", log_errors=False)
  1005. if self.use_veth_interconnection:
  1006. # Drop ports if the interface types doesn't match the
  1007. # configuration value.
  1008. if int_type == 'patch':
  1009. self.int_br.delete_port(int_if_name)
  1010. br.delete_port(phys_if_name)
  1011. device = ip_lib.IPDevice(int_if_name)
  1012. if device.exists():
  1013. device.link.delete()
  1014. # Give udev a chance to process its rules here, to avoid
  1015. # race conditions between commands launched by udev rules
  1016. # and the subsequent call to ip_wrapper.add_veth
  1017. utils.execute(['udevadm', 'settle', '--timeout=10'])
  1018. int_veth, phys_veth = ip_wrapper.add_veth(int_if_name,
  1019. phys_if_name)
  1020. int_ofport = self.int_br.add_port(int_veth)
  1021. phys_ofport = br.add_port(phys_veth)
  1022. else:
  1023. # Drop ports if the interface type doesn't match the
  1024. # configuration value
  1025. if int_type == 'veth':
  1026. self.int_br.delete_port(int_if_name)
  1027. br.delete_port(phys_if_name)
  1028. # Setup int_br to physical bridge patches. If they already
  1029. # exist we leave them alone, otherwise we create them but don't
  1030. # connect them until after the drop rules are in place.
  1031. if self.int_br.port_exists(int_if_name):
  1032. int_ofport = self.int_br.get_port_ofport(int_if_name)
  1033. else:
  1034. int_ofport = self.int_br.add_patch_port(
  1035. int_if_name, constants.NONEXISTENT_PEER)
  1036. if br.port_exists(phys_if_name):
  1037. phys_ofport = br.get_port_ofport(phys_if_name)
  1038. else:
  1039. phys_ofport = br.add_patch_port(
  1040. phys_if_name, constants.NONEXISTENT_PEER)
  1041. self.int_ofports[physical_network] = int_ofport
  1042. self.phys_ofports[physical_network] = phys_ofport
  1043. # block all untranslated traffic between bridges
  1044. self.int_br.drop_port(in_port=int_ofport)
  1045. br.drop_port(in_port=phys_ofport)
  1046. if self.use_veth_interconnection:
  1047. # enable veth to pass traffic
  1048. int_veth.link.set_up()
  1049. phys_veth.link.set_up()
  1050. if self.veth_mtu:
  1051. # set up mtu size for veth interfaces
  1052. int_veth.link.set_mtu(self.veth_mtu)
  1053. phys_veth.link.set_mtu(self.veth_mtu)
  1054. else:
  1055. # associate patch ports to pass traffic
  1056. self.int_br.set_db_attribute('Interface', int_if_name,
  1057. 'options', {'peer': phys_if_name})
  1058. br.set_db_attribute('Interface', phys_if_name,
  1059. 'options', {'peer': int_if_name})
  1060. def update_stale_ofport_rules(self):
  1061. # ARP spoofing rules and drop-flow upon port-delete
  1062. # use ofport-based rules
  1063. previous = self.vifname_to_ofport_map
  1064. current = self.int_br.get_vif_port_to_ofport_map()
  1065. # if any ofport numbers have changed, re-process the devices as
  1066. # added ports so any rules based on ofport numbers are updated.
  1067. moved_ports = self._get_ofport_moves(current, previous)
  1068. # delete any stale rules based on removed ofports
  1069. ofports_deleted = set(previous.values()) - set(current.values())
  1070. for ofport in ofports_deleted:
  1071. if self.prevent_arp_spoofing:
  1072. self.int_br.delete_arp_spoofing_protection(port=ofport)
  1073. self.int_br.delete_flows(in_port=ofport)
  1074. # store map for next iteration
  1075. self.vifname_to_ofport_map = current
  1076. return moved_ports
  1077. @staticmethod
  1078. def _get_ofport_moves(current, previous):
  1079. """Returns a list of moved ports.
  1080. Takes two port->ofport maps and returns a list ports that moved to a
  1081. different ofport. Deleted ports are not included.
  1082. """
  1083. port_moves = []
  1084. for name, ofport in previous.items():
  1085. if name not in current:
  1086. continue
  1087. current_ofport = current[name]
  1088. if ofport != current_ofport:
  1089. port_moves.append(name)
  1090. return port_moves
  1091. def _get_port_info(self, registered_ports, cur_ports,
  1092. readd_registered_ports):
  1093. port_info = {'current': cur_ports}
  1094. # FIXME(salv-orlando): It's not really necessary to return early
  1095. # if nothing has changed.
  1096. if not readd_registered_ports and cur_ports == registered_ports:
  1097. return port_info
  1098. if readd_registered_ports:
  1099. port_info['added'] = cur_ports
  1100. else:
  1101. port_info['added'] = cur_ports - registered_ports
  1102. # Update port_info with ports not found on the integration bridge
  1103. port_info['removed'] = registered_ports - cur_ports
  1104. return port_info
  1105. def _update_port_info_failed_devices_stats(self, port_info,
  1106. failed_devices):
  1107. # remove failed devices that don't need to be retried
  1108. failed_devices['added'] -= port_info['removed']
  1109. failed_devices['removed'] -= port_info['added']
  1110. # Disregard devices that were never noticed by the agent
  1111. port_info['removed'] &= port_info['current']
  1112. # retry failed devices
  1113. port_info['added'] |= failed_devices['added']
  1114. LOG.debug("retrying failed devices %s", failed_devices['added'])
  1115. port_info['removed'] |= failed_devices['removed']
  1116. # Update current ports
  1117. port_info['current'] |= port_info['added']
  1118. port_info['current'] -= port_info['removed']
  1119. def process_ports_events(self, events, registered_ports, ancillary_ports,
  1120. old_ports_not_ready, failed_devices,
  1121. failed_ancillary_devices, updated_ports=None):
  1122. port_info = {}
  1123. port_info['added'] = set()
  1124. port_info['removed'] = set()
  1125. port_info['current'] = registered_ports
  1126. ancillary_port_info = {}
  1127. ancillary_port_info['added'] = set()
  1128. ancillary_port_info['removed'] = set()
  1129. ancillary_port_info['current'] = ancillary_ports
  1130. ports_not_ready_yet = set()
  1131. # if a port was added and then removed or viceversa since the agent
  1132. # can't know the order of the operations, check the status of the port
  1133. # to determine if the port was added or deleted
  1134. added_ports = {p['name'] for p in events['added']}
  1135. removed_ports = {p['name'] for p in events['removed']}
  1136. ports_removed_and_added = added_ports & removed_ports
  1137. for p in ports_removed_and_added:
  1138. if ovs_lib.BaseOVS().port_exists(p):
  1139. events['removed'] = [e for e in events['removed']
  1140. if e['name'] != p]
  1141. else:
  1142. events['added'] = [e for e in events['added']
  1143. if e['name'] != p]
  1144. #TODO(rossella_s): scanning the ancillary bridge won't be needed
  1145. # anymore when https://review.openstack.org/#/c/203381 since the bridge
  1146. # id stored in external_ids will be used to identify the bridge the
  1147. # port belongs to
  1148. cur_ancillary_ports = set()
  1149. for bridge in self.ancillary_brs:
  1150. cur_ancillary_ports |= bridge.get_vif_port_set()
  1151. cur_ancillary_ports |= ancillary_port_info['current']
  1152. def _process_port(port, ports, ancillary_ports):
  1153. # check 'iface-id' is set otherwise is not a port
  1154. # the agent should care about
  1155. if 'attached-mac' in port.get('external_ids', []):
  1156. iface_id = self.int_br.portid_from_external_ids(
  1157. port['external_ids'])
  1158. if iface_id:
  1159. if port['ofport'] == ovs_lib.UNASSIGNED_OFPORT:
  1160. LOG.debug("Port %s not ready yet on the bridge",
  1161. iface_id)
  1162. ports_not_ready_yet.add(port['name'])
  1163. return
  1164. # check if port belongs to ancillary bridge
  1165. if iface_id in cur_ancillary_ports:
  1166. ancillary_ports.add(iface_id)
  1167. else:
  1168. ports.add(iface_id)
  1169. if old_ports_not_ready:
  1170. old_ports_not_ready_attrs = self.int_br.get_ports_attributes(
  1171. 'Interface', columns=['name', 'external_ids', 'ofport'],
  1172. ports=old_ports_not_ready, if_exists=True)
  1173. now_ready_ports = set(
  1174. [p['name'] for p in old_ports_not_ready_attrs])
  1175. LOG.debug("Ports %s are now ready", now_ready_ports)
  1176. old_ports_not_ready_yet = old_ports_not_ready - now_ready_ports
  1177. removed_ports = set([p['name'] for p in events['removed']])
  1178. old_ports_not_ready_yet -= removed_ports
  1179. LOG.debug("Ports %s were not ready at last iteration and are not "
  1180. "ready yet", old_ports_not_ready_yet)
  1181. ports_not_ready_yet |= old_ports_not_ready_yet
  1182. events['added'].extend(old_ports_not_ready_attrs)
  1183. for port in events['added']:
  1184. _process_port(port, port_info['added'],
  1185. ancillary_port_info['added'])
  1186. for port in events['removed']:
  1187. _process_port(port, port_info['removed'],
  1188. ancillary_port_info['removed'])
  1189. self._update_port_info_failed_devices_stats(port_info, failed_devices)
  1190. self._update_port_info_failed_devices_stats(ancillary_port_info,
  1191. failed_ancillary_devices)
  1192. if updated_ports is None:
  1193. updated_ports = set()
  1194. updated_ports.update(self.check_changed_vlans())
  1195. if updated_ports:
  1196. # Some updated ports might have been removed in the
  1197. # meanwhile, and therefore should not be processed.
  1198. # In this case the updated port won't be found among
  1199. # current ports.
  1200. updated_ports &= port_info['current']
  1201. port_info['updated'] = updated_ports
  1202. return port_info, ancillary_port_info, ports_not_ready_yet
  1203. def scan_ports(self, registered_ports, sync, updated_ports=None):
  1204. cur_ports = self.int_br.get_vif_port_set()
  1205. self.int_br_device_count = len(cur_ports)
  1206. port_info = self._get_port_info(registered_ports, cur_ports, sync)
  1207. if updated_ports is None:
  1208. updated_ports = set()
  1209. updated_ports.update(self.check_changed_vlans())
  1210. if updated_ports:
  1211. # Some updated ports might have been removed in the
  1212. # meanwhile, and therefore should not be processed.
  1213. # In this case the updated port won't be found among
  1214. # current ports.
  1215. updated_ports &= cur_ports
  1216. if updated_ports:
  1217. port_info['updated'] = updated_ports
  1218. return port_info
  1219. def scan_ancillary_ports(self, registered_ports, sync):
  1220. cur_ports = set()
  1221. for bridge in self.ancillary_brs:
  1222. cur_ports |= bridge.get_vif_port_set()
  1223. return self._get_port_info(registered_ports, cur_ports, sync)
  1224. def check_changed_vlans(self):
  1225. """Return ports which have lost their vlan tag.
  1226. The returned value is a set of port ids of the ports concerned by a
  1227. vlan tag loss.
  1228. """
  1229. port_tags = self.int_br.get_port_tag_dict()
  1230. changed_ports = set()
  1231. for lvm in self.local_vlan_map.values():
  1232. for port in lvm.vif_ports.values():
  1233. if (
  1234. port.port_name in port_tags
  1235. and port_tags[port.port_name] != lvm.vlan
  1236. ):
  1237. LOG.info(
  1238. _LI("Port '%(port_name)s' has lost "
  1239. "its vlan tag '%(vlan_tag)d'!"),
  1240. {'port_name': port.port_name,
  1241. 'vlan_tag': lvm.vlan}
  1242. )
  1243. changed_ports.add(port.vif_id)
  1244. return changed_ports
  1245. def treat_vif_port(self, vif_port, port_id, network_id, network_type,
  1246. physical_network, segmentation_id, admin_state_up,
  1247. fixed_ips, device_owner, ovs_restarted):
  1248. # When this function is called for a port, the port should have
  1249. # an OVS ofport configured, as only these ports were considered
  1250. # for being treated. If that does not happen, it is a potential
  1251. # error condition of which operators should be aware
  1252. port_needs_binding = True
  1253. if not vif_port.ofport:
  1254. LOG.warning(_LW("VIF port: %s has no ofport configured, "
  1255. "and might not be able to transmit"),
  1256. vif_port.vif_id)
  1257. if vif_port:
  1258. if admin_state_up:
  1259. port_needs_binding = self.port_bound(
  1260. vif_port, network_id, network_type,
  1261. physical_network, segmentation_id,
  1262. fixed_ips, device_owner, ovs_restarted)
  1263. else:
  1264. LOG.info(_LI("VIF port: %s admin state up disabled, "
  1265. "putting on the dead VLAN"), vif_port.vif_id)
  1266. self.port_dead(vif_port)
  1267. port_needs_binding = False
  1268. else:
  1269. LOG.debug("No VIF port for port %s defined on agent.", port_id)
  1270. return port_needs_binding
  1271. def _setup_tunnel_port(self, br, port_name, remote_ip, tunnel_type):
  1272. try:
  1273. if (netaddr.IPAddress(self.local_ip).version !=
  1274. netaddr.IPAddress(remote_ip).version):
  1275. LOG.error(_LE("IP version mismatch, cannot create tunnel: "
  1276. "local_ip=%(lip)s remote_ip=%(rip)s"),
  1277. {'lip': self.local_ip, 'rip': remote_ip})
  1278. return 0
  1279. except Exception:
  1280. LOG.error(_LE("Invalid local or remote IP, cannot create tunnel: "
  1281. "local_ip=%(lip)s remote_ip=%(rip)s"),
  1282. {'lip': self.local_ip, 'rip': remote_ip})
  1283. return 0
  1284. ofport = br.add_tunnel_port(port_name,
  1285. remote_ip,
  1286. self.local_ip,
  1287. tunnel_type,
  1288. self.vxlan_udp_port,
  1289. self.dont_fragment,
  1290. self.tunnel_csum)
  1291. if ofport == ovs_lib.INVALID_OFPORT:
  1292. LOG.error(_LE("Failed to set-up %(type)s tunnel port to %(ip)s"),
  1293. {'type': tunnel_type, 'ip': remote_ip})
  1294. return 0
  1295. self.tun_br_ofports[tunnel_type][remote_ip] = ofport
  1296. # Add flow in default table to resubmit to the right
  1297. # tunneling table (lvid will be set in the latter)
  1298. br.setup_tunnel_port(tunnel_type, ofport)
  1299. ofports = self.tun_br_ofports[tunnel_type].values()
  1300. if ofports and not self.l2_pop:
  1301. # Update flooding flows to include the new tunnel
  1302. for vlan_mapping in list(self.local_vlan_map.values()):
  1303. if vlan_mapping.network_type == tunnel_type:
  1304. br.install_flood_to_tun(vlan_mapping.vlan,
  1305. vlan_mapping.segmentation_id,
  1306. ofports)
  1307. return ofport
  1308. def setup_tunnel_port(self, br, remote_ip, network_type):
  1309. port_name = self.get_tunnel_name(
  1310. network_type, self.local_ip, remote_ip)
  1311. if port_name is None:
  1312. return 0
  1313. ofport = self._setup_tunnel_port(br,
  1314. port_name,
  1315. remote_ip,
  1316. network_type)
  1317. return ofport
  1318. def cleanup_tunnel_port(self, br, tun_ofport, tunnel_type):
  1319. # Check if this tunnel port is still used
  1320. for lvm in self.local_vlan_map.values():
  1321. if tun_ofport in lvm.tun_ofports:
  1322. break
  1323. # If not, remove it
  1324. else:
  1325. items = list(self.tun_br_ofports[tunnel_type].items())
  1326. for remote_ip, ofport in items:
  1327. if ofport == tun_ofport:
  1328. port_name = self.get_tunnel_name(
  1329. tunnel_type, self.local_ip, remote_ip)
  1330. br.delete_port(port_name)
  1331. br.cleanup_tunnel_port(ofport)
  1332. self.tun_br_ofports[tunnel_type].pop(remote_ip, None)
  1333. def treat_devices_added_or_updated(self, devices, ovs_restarted):
  1334. skipped_devices = []
  1335. need_binding_devices = []
  1336. security_disabled_devices = []
  1337. devices_details_list = (
  1338. self.plugin_rpc.get_devices_details_list_and_failed_devices(
  1339. self.context,
  1340. devices,
  1341. self.agent_id,
  1342. self.conf.host))
  1343. failed_devices = set(devices_details_list.get('failed_devices'))
  1344. devices = devices_details_list.get('devices')
  1345. vif_by_id = self.int_br.get_vifs_by_ids(
  1346. [vif['device'] for vif in devices])
  1347. for details in devices:
  1348. device = details['device']
  1349. LOG.debug("Processing port: %s", device)
  1350. port = vif_by_id.get(device)
  1351. if not port:
  1352. # The port disappeared and cannot be processed
  1353. LOG.info(_LI("Port %s was not found on the integration bridge "
  1354. "and will therefore not be processed"), device)
  1355. skipped_devices.append(device)
  1356. continue
  1357. if 'port_id' in details:
  1358. LOG.info(_LI("Port %(device)s updated. Details: %(details)s"),
  1359. {'device': device, 'details': details})
  1360. details['vif_port'] = port
  1361. need_binding = self.treat_vif_port(port, details['port_id'],
  1362. details['network_id'],
  1363. details['network_type'],
  1364. details['physical_network'],
  1365. details['segmentation_id'],
  1366. details['admin_state_up'],
  1367. details['fixed_ips'],
  1368. details['device_owner'],
  1369. ovs_restarted)
  1370. if need_binding:
  1371. need_binding_devices.append(details)
  1372. port_security = details['port_security_enabled']
  1373. has_sgs = 'security_groups' in details
  1374. if not port_security or not has_sgs:
  1375. security_disabled_devices.append(device)
  1376. self._update_port_network(details['port_id'],
  1377. details['network_id'])
  1378. self.ext_manager.handle_port(self.context, details)
  1379. else:
  1380. LOG.warning(
  1381. _LW("Device %s not defined on plugin or binding failed"),
  1382. device)
  1383. if (port and port.ofport != -1):
  1384. self.port_dead(port)
  1385. return (skipped_devices, need_binding_devices,
  1386. security_disabled_devices, failed_devices)
  1387. def _update_port_network(self, port_id, network_id):
  1388. self._clean_network_ports(port_id)
  1389. self.network_ports[network_id].add(port_id)
  1390. def treat_ancillary_devices_added(self, devices):
  1391. devices_details_list = (
  1392. self.plugin_rpc.get_devices_details_list_and_failed_devices(
  1393. self.context,
  1394. devices,
  1395. self.agent_id,
  1396. self.conf.host))
  1397. failed_devices = set(devices_details_list.get('failed_devices'))
  1398. devices_added = [
  1399. d['device'] for d in devices_details_list.get('devices')]
  1400. # update plugin about port status
  1401. devices_set_up = (
  1402. self.plugin_rpc.update_device_list(self.context,
  1403. devices_added,
  1404. [],
  1405. self.agent_id,
  1406. self.conf.host))
  1407. failed_devices |= set(devices_set_up.get('failed_devices_up'))
  1408. LOG.info(_LI("Ancillary Ports %(added)s added, failed devices "
  1409. "%(failed)s"), {'added': devices,
  1410. 'failed': failed_devices})
  1411. return failed_devices
  1412. def treat_devices_removed(self, devices):
  1413. self.sg_agent.remove_devices_filter(devices)
  1414. LOG.info(_LI("Ports %s removed"), devices)
  1415. devices_down = self.plugin_rpc.update_device_list(self.context,
  1416. [],
  1417. devices,
  1418. self.agent_id,
  1419. self.conf.host)
  1420. failed_devices = set(devices_down.get('failed_devices_down'))
  1421. LOG.debug("Port removal failed for %s", failed_devices)
  1422. for device in devices:
  1423. self.ext_manager.delete_port(self.context, {'port_id': device})
  1424. self.port_unbound(device)
  1425. return failed_devices
  1426. def treat_ancillary_devices_removed(self, devices):
  1427. LOG.info(_LI("Ancillary ports %s removed"), devices)
  1428. devices_down = self.plugin_rpc.update_device_list(self.context,
  1429. [],
  1430. devices,
  1431. self.agent_id,
  1432. self.conf.host)
  1433. LOG.info(_LI("Devices down %s "), devices_down)
  1434. failed_devices = set(devices_down.get('failed_devices_down'))
  1435. if failed_devices:
  1436. LOG.debug("Port removal failed for %s", failed_devices)
  1437. for detail in devices_down.get('devices_down'):
  1438. if detail['exists']:
  1439. LOG.info(_LI("Port %s updated."), detail['device'])
  1440. # Nothing to do regarding local networking
  1441. else:
  1442. LOG.debug("Device %s not defined on plugin", detail['device'])
  1443. return failed_devices
  1444. def process_network_ports(self, port_info, ovs_restarted):
  1445. failed_devices = {'added': set(), 'removed': set()}
  1446. # TODO(salv-orlando): consider a solution for ensuring notifications
  1447. # are processed exactly in the same order in which they were
  1448. # received. This is tricky because there are two notification
  1449. # sources: the neutron server, and the ovs db monitor process
  1450. # If there is an exception while processing security groups ports
  1451. # will not be wired anyway, and a resync will be triggered
  1452. # VIF wiring needs to be performed always for 'new' devices.
  1453. # For updated ports, re-wiring is not needed in most cases, but needs
  1454. # to be performed anyway when the admin state of a device is changed.
  1455. # A device might be both in the 'added' and 'updated'
  1456. # list at the same time; avoid processing it twice.
  1457. devices_added_updated = (port_info.get('added', set()) |
  1458. port_info.get('updated', set()))
  1459. need_binding_devices = []
  1460. security_disabled_ports = []
  1461. if devices_added_updated:
  1462. start = time.time()
  1463. (skipped_devices, need_binding_devices,
  1464. security_disabled_ports, failed_devices['added']) = (
  1465. self.treat_devices_added_or_updated(
  1466. devices_added_updated, ovs_restarted))
  1467. LOG.debug("process_network_ports - iteration:%(iter_num)d - "
  1468. "treat_devices_added_or_updated completed. "
  1469. "Skipped %(num_skipped)d devices of "
  1470. "%(num_current)d devices currently available. "
  1471. "Time elapsed: %(elapsed).3f",
  1472. {'iter_num': self.iter_num,
  1473. 'num_skipped': len(skipped_devices),
  1474. 'num_current': len(port_info['current']),
  1475. 'elapsed': time.time() - start})
  1476. # Update the list of current ports storing only those which
  1477. # have been actually processed.
  1478. port_info['current'] = (port_info['current'] -
  1479. set(skipped_devices))
  1480. # TODO(salv-orlando): Optimize avoiding applying filters
  1481. # unnecessarily, (eg: when there are no IP address changes)
  1482. added_ports = port_info.get('added', set())
  1483. self._add_port_tag_info(need_binding_devices)
  1484. if security_disabled_ports:
  1485. added_ports -= set(security_disabled_ports)
  1486. self.sg_agent.setup_port_filters(added_ports,
  1487. port_info.get('updated', set()))
  1488. failed_devices['added'] |= self._bind_devices(need_binding_devices)
  1489. if 'removed' in port_info and port_info['removed']:
  1490. start = time.time()
  1491. failed_devices['removed'] |= self.treat_devices_removed(
  1492. port_info['removed'])
  1493. LOG.debug("process_network_ports - iteration:%(iter_num)d - "
  1494. "treat_devices_removed completed in %(elapsed).3f",
  1495. {'iter_num': self.iter_num,
  1496. 'elapsed': time.time() - start})
  1497. return failed_devices
  1498. def process_ancillary_network_ports(self, port_info):
  1499. failed_devices = {'added': set(), 'removed': set()}
  1500. if 'added' in port_info and port_info['added']:
  1501. start = time.time()
  1502. failed_added = self.treat_ancillary_devices_added(
  1503. port_info['added'])
  1504. LOG.debug("process_ancillary_network_ports - iteration: "
  1505. "%(iter_num)d - treat_ancillary_devices_added "
  1506. "completed in %(elapsed).3f",
  1507. {'iter_num': self.iter_num,
  1508. 'elapsed': time.time() - start})
  1509. failed_devices['added'] = failed_added
  1510. if 'removed' in port_info and port_info['removed']:
  1511. start = time.time()
  1512. failed_removed = self.treat_ancillary_devices_removed(
  1513. port_info['removed'])
  1514. failed_devices['removed'] = failed_removed
  1515. LOG.debug("process_ancillary_network_ports - iteration: "
  1516. "%(iter_num)d - treat_ancillary_devices_removed "
  1517. "completed in %(elapsed).3f",
  1518. {'iter_num': self.iter_num,
  1519. 'elapsed': time.time() - start})
  1520. return failed_devices
  1521. @classmethod
  1522. def get_tunnel_hash(cls, ip_address, hashlen):
  1523. try:
  1524. addr = netaddr.IPAddress(ip_address)
  1525. if addr.version == n_const.IP_VERSION_4:
  1526. # We cannot change this from 8, since it could break
  1527. # backwards-compatibility
  1528. return '%08x' % addr
  1529. else:
  1530. # Create 32-bit Base32 encoded hash
  1531. sha1 = hashlib.sha1(ip_address.encode())
  1532. iphash = base64.b32encode(sha1.digest())
  1533. return iphash[:hashlen].decode().lower()
  1534. except Exception:
  1535. LOG.warning(_LW("Invalid remote IP: %s"), ip_address)
  1536. return
  1537. def tunnel_sync(self):
  1538. LOG.debug("Configuring tunnel endpoints to other OVS agents")
  1539. try:
  1540. for tunnel_type in self.tunnel_types:
  1541. details = self.plugin_rpc.tunnel_sync(self.context,
  1542. self.local_ip,
  1543. tunnel_type,
  1544. self.conf.host)
  1545. if not self.l2_pop:
  1546. tunnels = details['tunnels']
  1547. for tunnel in tunnels:
  1548. if self.local_ip != tunnel['ip_address']:
  1549. remote_ip = tunnel['ip_address']
  1550. tun_name = self.get_tunnel_name(
  1551. tunnel_type, self.local_ip, remote_ip)
  1552. if tun_name is None:
  1553. continue
  1554. self._setup_tunnel_port(self.tun_br,
  1555. tun_name,
  1556. tunnel['ip_address'],
  1557. tunnel_type)
  1558. except Exception as e:
  1559. LOG.debug("Unable to sync tunnel IP %(local_ip)s: %(e)s",
  1560. {'local_ip': self.local_ip, 'e': e})
  1561. return True
  1562. return False
  1563. @classmethod
  1564. def get_tunnel_name(cls, network_type, local_ip, remote_ip):
  1565. # This string is used to build port and interface names in OVS.
  1566. # Port and interface names can be max 16 characters long,
  1567. # including NULL, and must be unique per table per host.
  1568. # We make the name as long as possible given the network_type,
  1569. # for example, 'vxlan-012345678' or 'geneve-01234567'.
  1570. # Remove length of network type and dash
  1571. hashlen = n_const.DEVICE_NAME_MAX_LEN - len(network_type) - 1
  1572. remote_tunnel_hash = cls.get_tunnel_hash(remote_ip, hashlen)
  1573. if not remote_tunnel_hash:
  1574. return None
  1575. return '%s-%s' % (network_type, remote_tunnel_hash)
  1576. def _agent_has_updates(self, polling_manager):
  1577. return (polling_manager.is_polling_required or
  1578. self.updated_ports or
  1579. self.deleted_ports or
  1580. self.sg_agent.firewall_refresh_needed())
  1581. def _port_info_has_changes(self, port_info):
  1582. return (port_info.get('added') or
  1583. port_info.get('removed') or
  1584. port_info.get('updated'))
  1585. def check_ovs_status(self):
  1586. # Check for the canary flow
  1587. status = self.int_br.check_canary_table()
  1588. if status == constants.OVS_RESTARTED:
  1589. LOG.warning(_LW("OVS is restarted. OVSNeutronAgent will reset "
  1590. "bridges and recover ports."))
  1591. elif status == constants.OVS_DEAD:
  1592. LOG.warning(_LW("OVS is dead. OVSNeutronAgent will keep running "
  1593. "and checking OVS status periodically."))
  1594. return status
  1595. def loop_count_and_wait(self, start_time, port_stats):
  1596. # sleep till end of polling interval
  1597. elapsed = time.time() - start_time
  1598. LOG.debug("Agent rpc_loop - iteration:%(iter_num)d "
  1599. "completed. Processed ports statistics: "
  1600. "%(port_stats)s. Elapsed:%(elapsed).3f",
  1601. {'iter_num': self.iter_num,
  1602. 'port_stats': port_stats,
  1603. 'elapsed': elapsed})
  1604. if elapsed < self.polling_interval:
  1605. time.sleep(self.polling_interval - elapsed)
  1606. else:
  1607. LOG.debug("Loop iteration exceeded interval "
  1608. "(%(polling_interval)s vs. %(elapsed)s)!",
  1609. {'polling_interval': self.polling_interval,
  1610. 'elapsed': elapsed})
  1611. self.iter_num = self.iter_num + 1
  1612. def get_port_stats(self, port_info, ancillary_port_info):
  1613. port_stats = {
  1614. 'regular': {
  1615. 'added': len(port_info.get('added', [])),
  1616. 'updated': len(port_info.get('updated', [])),
  1617. 'removed': len(port_info.get('removed', []))}}
  1618. if self.ancillary_brs:
  1619. port_stats['ancillary'] = {
  1620. 'added': len(ancillary_port_info.get('added', [])),
  1621. 'removed': len(ancillary_port_info.get('removed', []))}
  1622. return port_stats
  1623. def cleanup_stale_flows(self):
  1624. bridges = [self.int_br]
  1625. bridges.extend(self.phys_brs.values())
  1626. if self.enable_tunneling:
  1627. bridges.append(self.tun_br)
  1628. for bridge in bridges:
  1629. LOG.info(_LI("Cleaning stale %s flows"), bridge.br_name)
  1630. bridge.cleanup_flows()
  1631. def process_port_info(self, start, polling_manager, sync, ovs_restarted,
  1632. ports, ancillary_ports, updated_ports_copy,
  1633. consecutive_resyncs, ports_not_ready_yet,
  1634. failed_devices, failed_ancillary_devices):
  1635. # There are polling managers that don't have get_events, e.g.
  1636. # AlwaysPoll used by windows implementations
  1637. # REVISIT (rossella_s) This needs to be reworked to hide implementation
  1638. # details regarding polling in BasePollingManager subclasses
  1639. if sync or not (hasattr(polling_manager, 'get_events')):
  1640. if sync:
  1641. LOG.info(_LI("Agent out of sync with plugin!"))
  1642. consecutive_resyncs = consecutive_resyncs + 1
  1643. if (consecutive_resyncs >=
  1644. constants.MAX_DEVICE_RETRIES):
  1645. LOG.warning(_LW(
  1646. "Clearing cache of registered ports,"
  1647. " retries to resync were > %s"),
  1648. constants.MAX_DEVICE_RETRIES)
  1649. ports.clear()
  1650. ancillary_ports.clear()
  1651. consecutive_resyncs = 0
  1652. else:
  1653. consecutive_resyncs = 0
  1654. # TODO(rossella_s): For implementations that use AlwaysPoll
  1655. # resync if a device failed. This can be improved in future
  1656. sync = (any(failed_devices.values()) or
  1657. any(failed_ancillary_devices.values()))
  1658. # NOTE(rossella_s) don't empty the queue of events
  1659. # calling polling_manager.get_events() since
  1660. # the agent might miss some event (for example a port
  1661. # deletion)
  1662. reg_ports = (set() if ovs_restarted else ports)
  1663. port_info = self.scan_ports(reg_ports, sync,
  1664. updated_ports_copy)
  1665. # Treat ancillary devices if they exist
  1666. if self.ancillary_brs:
  1667. ancillary_port_info = self.scan_ancillary_ports(
  1668. ancillary_ports, sync)
  1669. LOG.debug("Agent rpc_loop - iteration:%(iter_num)d"
  1670. " - ancillary port info retrieved. "
  1671. "Elapsed:%(elapsed).3f",
  1672. {'iter_num': self.iter_num,
  1673. 'elapsed': time.time() - start})
  1674. else:
  1675. ancillary_port_info = {}
  1676. else:
  1677. consecutive_resyncs = 0
  1678. events = polling_manager.get_events()
  1679. port_info, ancillary_port_info, ports_not_ready_yet = (
  1680. self.process_ports_events(events, ports, ancillary_ports,
  1681. ports_not_ready_yet,
  1682. failed_devices,
  1683. failed_ancillary_devices,
  1684. updated_ports_copy))
  1685. return (port_info, ancillary_port_info, consecutive_resyncs,
  1686. ports_not_ready_yet)
  1687. def _remove_devices_not_to_retry(self, failed_devices,
  1688. failed_ancillary_devices,
  1689. devices_not_to_retry,
  1690. ancillary_devices_not_to_retry):
  1691. """This method removes the devices that exceeded the number of retries
  1692. from failed_devices and failed_ancillary_devices
  1693. """
  1694. for event in ['added', 'removed']:
  1695. failed_devices[event] = (
  1696. failed_devices[event] - devices_not_to_retry[event])
  1697. failed_ancillary_devices[event] = (
  1698. failed_ancillary_devices[event] -
  1699. ancillary_devices_not_to_retry[event])
  1700. def _get_devices_not_to_retry(self, failed_devices,
  1701. failed_ancillary_devices,
  1702. failed_devices_retries_map):
  1703. """Return the devices not to retry and update the retries map"""
  1704. new_failed_devices_retries_map = {}
  1705. devices_not_to_retry = {}
  1706. ancillary_devices_not_to_retry = {}
  1707. def _increase_retries(devices_set):
  1708. devices_not_to_retry = set()
  1709. for dev in devices_set:
  1710. retries = failed_devices_retries_map.get(dev, 0)
  1711. if retries >= constants.MAX_DEVICE_RETRIES:
  1712. devices_not_to_retry.add(dev)
  1713. LOG.warning(_LW(
  1714. "Device %(dev)s failed for %(times)s times and won't "
  1715. "be retried anymore"), {
  1716. 'dev': dev, 'times': constants.MAX_DEVICE_RETRIES})
  1717. else:
  1718. new_failed_devices_retries_map[dev] = retries + 1
  1719. return devices_not_to_retry
  1720. for event in ['added', 'removed']:
  1721. devices_not_to_retry[event] = _increase_retries(
  1722. failed_devices[event])
  1723. ancillary_devices_not_to_retry[event] = _increase_retries(
  1724. failed_ancillary_devices[event])
  1725. return (new_failed_devices_retries_map, devices_not_to_retry,
  1726. ancillary_devices_not_to_retry)
  1727. def update_retries_map_and_remove_devs_not_to_retry(
  1728. self, failed_devices, failed_ancillary_devices,
  1729. failed_devices_retries_map):
  1730. (new_failed_devices_retries_map, devices_not_to_retry,
  1731. ancillary_devices_not_to_retry) = self._get_devices_not_to_retry(
  1732. failed_devices, failed_ancillary_devices,
  1733. failed_devices_retries_map)
  1734. self._remove_devices_not_to_retry(
  1735. failed_devices, failed_ancillary_devices, devices_not_to_retry,
  1736. ancillary_devices_not_to_retry)
  1737. return new_failed_devices_retries_map
  1738. def rpc_loop(self, polling_manager=None):
  1739. if not polling_manager:
  1740. polling_manager = polling.get_polling_manager(
  1741. minimize_polling=False)
  1742. sync = False
  1743. ports = set()
  1744. updated_ports_copy = set()
  1745. ancillary_ports = set()
  1746. tunnel_sync = True
  1747. ovs_restarted = False
  1748. consecutive_resyncs = 0
  1749. need_clean_stale_flow = True
  1750. ports_not_ready_yet = set()
  1751. failed_devices = {'added': set(), 'removed': set()}
  1752. failed_ancillary_devices = {'added': set(), 'removed': set()}
  1753. failed_devices_retries_map = {}
  1754. while self._check_and_handle_signal():
  1755. if self.fullsync:
  1756. LOG.info(_LI("rpc_loop doing a full sync."))
  1757. sync = True
  1758. self.fullsync = False
  1759. port_info = {}
  1760. ancillary_port_info = {}
  1761. start = time.time()
  1762. LOG.debug("Agent rpc_loop - iteration:%d started",
  1763. self.iter_num)
  1764. ovs_status = self.check_ovs_status()
  1765. if ovs_status == constants.OVS_RESTARTED:
  1766. self.setup_integration_br()
  1767. self.setup_physical_bridges(self.bridge_mappings)
  1768. if self.enable_tunneling:
  1769. self._reset_tunnel_ofports()
  1770. self.setup_tunnel_br()
  1771. self.setup_tunnel_br_flows()
  1772. tunnel_sync = True
  1773. if self.enable_distributed_routing:
  1774. self.dvr_agent.reset_ovs_parameters(self.int_br,
  1775. self.tun_br,
  1776. self.patch_int_ofport,
  1777. self.patch_tun_ofport)
  1778. self.dvr_agent.reset_dvr_parameters()
  1779. self.dvr_agent.setup_dvr_flows()
  1780. # restart the polling manager so that it will signal as added
  1781. # all the current ports
  1782. # REVISIT (rossella_s) Define a method "reset" in
  1783. # BasePollingManager that will be implemented by AlwaysPoll as
  1784. # no action and by InterfacePollingMinimizer as start/stop
  1785. if isinstance(
  1786. polling_manager, polling.InterfacePollingMinimizer):
  1787. polling_manager.stop()
  1788. polling_manager.start()
  1789. elif ovs_status == constants.OVS_DEAD:
  1790. # Agent doesn't apply any operations when ovs is dead, to
  1791. # prevent unexpected failure or crash. Sleep and continue
  1792. # loop in which ovs status will be checked periodically.
  1793. port_stats = self.get_port_stats({}, {})
  1794. self.loop_count_and_wait(start, port_stats)
  1795. continue
  1796. # Notify the plugin of tunnel IP
  1797. if self.enable_tunneling and tunnel_sync:
  1798. try:
  1799. tunnel_sync = self.tunnel_sync()
  1800. except Exception:
  1801. LOG.exception(
  1802. _LE("Error while configuring tunnel endpoints"))
  1803. tunnel_sync = True
  1804. ovs_restarted |= (ovs_status == constants.OVS_RESTARTED)
  1805. devices_need_retry = (any(failed_devices.values()) or
  1806. any(failed_ancillary_devices.values()) or
  1807. ports_not_ready_yet)
  1808. if (self._agent_has_updates(polling_manager) or sync
  1809. or devices_need_retry):
  1810. try:
  1811. LOG.debug("Agent rpc_loop - iteration:%(iter_num)d - "
  1812. "starting polling. Elapsed:%(elapsed).3f",
  1813. {'iter_num': self.iter_num,
  1814. 'elapsed': time.time() - start})
  1815. # Save updated ports dict to perform rollback in
  1816. # case resync would be needed, and then clear
  1817. # self.updated_ports. As the greenthread should not yield
  1818. # between these two statements, this will be thread-safe
  1819. updated_ports_copy = self.updated_ports
  1820. self.updated_ports = set()
  1821. (port_info, ancillary_port_info, consecutive_resyncs,
  1822. ports_not_ready_yet) = (self.process_port_info(
  1823. start, polling_manager, sync, ovs_restarted,
  1824. ports, ancillary_ports, updated_ports_copy,
  1825. consecutive_resyncs, ports_not_ready_yet,
  1826. failed_devices, failed_ancillary_devices))
  1827. sync = False
  1828. self.process_deleted_ports(port_info)
  1829. ofport_changed_ports = self.update_stale_ofport_rules()
  1830. if ofport_changed_ports:
  1831. port_info.setdefault('updated', set()).update(
  1832. ofport_changed_ports)
  1833. LOG.debug("Agent rpc_loop - iteration:%(iter_num)d - "
  1834. "port information retrieved. "
  1835. "Elapsed:%(elapsed).3f",
  1836. {'iter_num': self.iter_num,
  1837. 'elapsed': time.time() - start})
  1838. # Secure and wire/unwire VIFs and update their status
  1839. # on Neutron server
  1840. if (self._port_info_has_changes(port_info) or
  1841. self.sg_agent.firewall_refresh_needed() or
  1842. ovs_restarted):
  1843. LOG.debug("Starting to process devices in:%s",
  1844. port_info)
  1845. failed_devices = self.process_network_ports(
  1846. port_info, ovs_restarted)
  1847. if need_clean_stale_flow:
  1848. self.cleanup_stale_flows()
  1849. need_clean_stale_flow = False
  1850. LOG.debug("Agent rpc_loop - iteration:%(iter_num)d - "
  1851. "ports processed. Elapsed:%(elapsed).3f",
  1852. {'iter_num': self.iter_num,
  1853. 'elapsed': time.time() - start})
  1854. ports = port_info['current']
  1855. if self.ancillary_brs:
  1856. failed_ancillary_devices = (
  1857. self.process_ancillary_network_ports(
  1858. ancillary_port_info))
  1859. LOG.debug("Agent rpc_loop - iteration: "
  1860. "%(iter_num)d - ancillary ports "
  1861. "processed. Elapsed:%(elapsed).3f",
  1862. {'iter_num': self.iter_num,
  1863. 'elapsed': time.time() - start})
  1864. ancillary_ports = ancillary_port_info['current']
  1865. polling_manager.polling_completed()
  1866. failed_devices_retries_map = (
  1867. self.update_retries_map_and_remove_devs_not_to_retry(
  1868. failed_devices, failed_ancillary_devices,
  1869. failed_devices_retries_map))
  1870. # Keep this flag in the last line of "try" block,
  1871. # so we can sure that no other Exception occurred.
  1872. ovs_restarted = False
  1873. self._dispose_local_vlan_hints()
  1874. except Exception:
  1875. LOG.exception(_LE("Error while processing VIF ports"))
  1876. # Put the ports back in self.updated_port
  1877. self.updated_ports |= updated_ports_copy
  1878. sync = True
  1879. port_stats = self.get_port_stats(port_info, ancillary_port_info)
  1880. self.loop_count_and_wait(start, port_stats)
  1881. def daemon_loop(self):
  1882. # Start everything.
  1883. LOG.info(_LI("Agent initialized successfully, now running... "))
  1884. signal.signal(signal.SIGTERM, self._handle_sigterm)
  1885. if hasattr(signal, 'SIGHUP'):
  1886. signal.signal(signal.SIGHUP, self._handle_sighup)
  1887. with polling.get_polling_manager(
  1888. self.minimize_polling,
  1889. self.ovsdb_monitor_respawn_interval) as pm:
  1890. self.rpc_loop(polling_manager=pm)
  1891. def _handle_sigterm(self, signum, frame):
  1892. self.catch_sigterm = True
  1893. if self.quitting_rpc_timeout:
  1894. self.set_rpc_timeout(self.quitting_rpc_timeout)
  1895. def _handle_sighup(self, signum, frame):
  1896. self.catch_sighup = True
  1897. def _check_and_handle_signal(self):
  1898. if self.catch_sigterm:
  1899. LOG.info(_LI("Agent caught SIGTERM, quitting daemon loop."))
  1900. self.run_daemon_loop = False
  1901. self.catch_sigterm = False
  1902. if self.catch_sighup:
  1903. LOG.info(_LI("Agent caught SIGHUP, resetting."))
  1904. self.conf.reload_config_files()
  1905. config.setup_logging()
  1906. LOG.debug('Full set of CONF:')
  1907. self.conf.log_opt_values(LOG, logging.DEBUG)
  1908. self.catch_sighup = False
  1909. return self.run_daemon_loop
  1910. def set_rpc_timeout(self, timeout):
  1911. for rpc_api in (self.plugin_rpc, self.sg_plugin_rpc,
  1912. self.dvr_plugin_rpc, self.state_rpc):
  1913. rpc_api.client.timeout = timeout
  1914. def _check_agent_configurations(self):
  1915. if (self.enable_distributed_routing and self.enable_tunneling
  1916. and not self.l2_pop):
  1917. raise ValueError(_("DVR deployments for VXLAN/GRE/Geneve "
  1918. "underlays require L2-pop to be enabled, "
  1919. "in both the Agent and Server side."))
  1920. def validate_local_ip(local_ip):
  1921. """Verify if the ip exists on the agent's host."""
  1922. if not ip_lib.IPWrapper().get_device_by_ip(local_ip):
  1923. LOG.error(_LE("Tunneling can't be enabled with invalid local_ip '%s'."
  1924. " IP couldn't be found on this host's interfaces."),
  1925. local_ip)
  1926. raise SystemExit(1)
  1927. def validate_tunnel_config(tunnel_types, local_ip):
  1928. """Verify local ip and tunnel config if tunneling is enabled."""
  1929. if not tunnel_types:
  1930. return
  1931. validate_local_ip(local_ip)
  1932. for tun in tunnel_types:
  1933. if tun not in constants.TUNNEL_NETWORK_TYPES:
  1934. LOG.error(_LE('Invalid tunnel type specified: %s'), tun)
  1935. raise SystemExit(1)
  1936. def prepare_xen_compute():
  1937. is_xen_compute_host = 'rootwrap-xen-dom0' in cfg.CONF.AGENT.root_helper
  1938. if is_xen_compute_host:
  1939. # Force ip_lib to always use the root helper to ensure that ip
  1940. # commands target xen dom0 rather than domU.
  1941. cfg.CONF.register_opts(ip_lib.OPTS)
  1942. cfg.CONF.set_default('ip_lib_force_root', True)
  1943. def main(bridge_classes):
  1944. prepare_xen_compute()
  1945. validate_tunnel_config(cfg.CONF.AGENT.tunnel_types, cfg.CONF.OVS.local_ip)
  1946. try:
  1947. agent = OVSNeutronAgent(bridge_classes, cfg.CONF)
  1948. except (RuntimeError, ValueError) as e:
  1949. LOG.error(_LE("%s Agent terminated!"), e)
  1950. sys.exit(1)
  1951. agent.daemon_loop()