original_docstring: Ensure a router interface on the local host.
  
          Creates a loopback interface and sets the bridge's BVI to the
          loopback interface to act as an L3 gateway for the network.
          For external networks, the BVI functions as an SNAT external
          interface. For updating an interface, the service plugin removes
          the old interface and then adds the new router interface. If an
          external gateway exists, ensures a local route in VPP.
  
          When Layer3 HA is enabled, the router interfaces are only enabled on
          the active VPP router. The standby router keeps the interface in
          an admin down state.
          
docstring: Ensure a router interface on the local host.
  Creates a loopback interface and sets the bridge's BVI to the
  loopback interface to act as an L3 gateway for the network.
  For external networks, the BVI functions as an SNAT external
  interface. For updating an interface, the service plugin removes
  the old interface and then adds the new router interface. If an
  external gateway exists, ensures a local route in VPP.
  
  When Layer3 HA is enabled, the router interfaces are only enabled on
  the active VPP router. The standby router keeps the interface in
  an admin down state.
docstring_tokens: Ensure a router interface on the local host . Creates a loopback interface and sets the bridge ' s BVI to the loopback interface to act as an L3 gateway for the network . For external networks the BVI functions as an SNAT external interface . For updating an interface the service plugin removes the old interface and then adds the new router interface . If an external gateway exists ensures a local route in VPP . When Layer3 HA is enabled the router interfaces are only enabled on the active VPP router . The standby router keeps the interface in an admin down state .
code: def ensure_router_interface_on_host(self, port_id, router_data):
          """Ensure a router interface on the local host.
  
          Creates a loopback interface and sets the bridge's BVI to the
          loopback interface to act as an L3 gateway for the network.
          For external networks, the BVI functions as an SNAT external
          interface. For updating an interface, the service plugin removes
          the old interface and then adds the new router interface. If an
          external gateway exists, ensures a local route in VPP.
  
          When Layer3 HA is enabled, the router interfaces are only enabled on
          the active VPP router. The standby router keeps the interface in
          an admin down state.
          """
          # The interface could be either an external_gw or an internal router
          # interface on a subnet
          # Enable SNAT by default unless it is set to False
          enable_snat = True
          # Multiple routers on a shared external subnet is supported
          # by adding local routes in VPP.
          is_local = 0  # True for local-only VPP routes.
          # Create an external interfce if the external_gateway_info key is
          # present, else create an internal interface
          if router_data.get('external_gateway_info', False):
              seg_id = router_data['external_segmentation_id']
              net_type = router_data['external_net_type']
              physnet = router_data['external_physnet']
              vrf = vpp.DEFAULT_VRF
              is_inside = False
              enable_snat = router_data['external_gateway_info']['enable_snat']
              external_gateway_ip = router_data['external_gateway_ip']
              # To support multiple IP addresses on a router port, add
              # the router to each of the subnets.
              gateway_ip = router_data['gateways'][0][0]
              prefixlen = router_data['gateways'][0][1]
              is_ipv6 = bool(router_data['gateways'][0][2])
          else:
              seg_id = router_data['segmentation_id']
              net_type = router_data['net_type']
              physnet = router_data['physnet']
              vrf = router_data['vrf_id']
              is_inside = True
              external_gateway_ip = None
              gateway_ip = router_data['gateway_ip']
              prefixlen = router_data['prefixlen']
              is_ipv6 = bool(router_data['is_ipv6'])
          # Ensure the network exists on host and get the network data
          net_data = self.net_driver.ensure_network(physnet, net_type, seg_id)
          # Get the bridge domain id and ensure a BVI interface for it
          bridge_idx = net_data['bridge_domain_id']
          # Ensure a BVI (i.e. A loopback) for the bridge domain
          loopback_idx = self.vpp.get_bridge_bvi(bridge_idx)
          # Create a loopback BVI interface
          loopback_mac = vpp.mac_str_t(router_data['loopback_mac'])
          if loopback_idx is None:
              # Create the loopback interface, but don't bring it UP yet
              loopback_idx = self.ensure_bridge_bvi(bridge_idx, loopback_mac)
          # Set the VRF for tenant BVI interfaces, if not already set
          if vrf and not self.vpp.get_interface_vrf(loopback_idx) == vrf:
              self.vpp.set_interface_vrf(loopback_idx, vrf, is_ipv6)
          # Make a best effort to set the MTU on the interface
          try:
              self.vpp.set_interface_mtu(loopback_idx, router_data['mtu'])
          except SystemExit:
              # Log error and continue, do not exit here
              LOG.error("Error setting MTU on router interface")
          ha_enabled = cfg.CONF.ml2_vpp.enable_l3_ha
          if ha_enabled:
              # Now bring up the loopback interface, if this router is the
              # ACTIVE router. Also populate the data structure
              # router_interface_states so the HA code can activate and
              # deactivate the interface
              if self.router_state:
                  LOG.debug("Router HA state is ACTIVE")
                  LOG.debug("Bringing UP the router intf idx: %s", loopback_idx)
                  self.vpp.ifup(loopback_idx)
                  self.router_interface_states[loopback_idx] = 1
              else:
                  LOG.debug("Router HA state is BACKUP")
                  LOG.debug("Bringing DOWN the router intf idx: %s",
                            loopback_idx)
                  self.vpp.ifdown(loopback_idx)
                  self.router_interface_states[loopback_idx] = 0
              LOG.debug("Current router interface states: %s",
                        self.router_interface_states)
          else:
              self.vpp.ifup(loopback_idx)
          # Set SNAT on the interface if SNAT is enabled
          # Get a list of all SNAT interfaces
          int_list = self.vpp.get_snat_interfaces()
          if loopback_idx not in int_list and enable_snat:
              self.vpp.set_snat_on_interface(loopback_idx, is_inside)
              # Set the SNAT 1:N overload on the external loopback interface
              if not is_inside:
                  self.vpp.snat_overload_on_interface_address(loopback_idx)
  
          # Add GPE mappings for GPE type networks only on the master
          # node, if ha_enabled
          if net_type == TYPE_GPE and self.gpe is not None:
              if (ha_enabled and self.router_state) or not ha_enabled:
                  self.gpe.add_local_gpe_mapping(seg_id, loopback_mac)
          # Set the gateway IP address on the BVI interface, if not already set
          addresses = self.vpp.get_interface_ip_addresses(loopback_idx)
          gw_ipif = ip_interface((gateway_ip, prefixlen,))
          # Is there another gateway ip_addr set on this external loopback?
          if not is_inside:
              # Any address other than the one we're thinking of?
              exists_gateway = any((addr for addr in addresses
                                    if addr != gw_ipif))
              if exists_gateway:
                  LOG.debug('A router gateway exists on the external network.'
                            'The current router gateway IP: %s will be added as '
                            'a local VPP route', str(gw_ipif))
          if gw_ipif not in addresses:
              # This address is not yet present?
  
              # Add a local VRF route if another external gateway exists
              if not is_inside and exists_gateway:
  
                  is_local = True
                  ip_prefix_length = 32 if gw_ipif.version == 4 else 128
                  # Add a local IP route if it doesn't exist
                  self.vpp.add_ip_route(vrf=vrf,
                                        ip_address=self._pack_address(
                                            gateway_ip),
                                        prefixlen=ip_prefix_length,
                                        next_hop_address=None,
                                        next_hop_sw_if_index=None,
                                        is_ipv6=is_ipv6,
                                        is_local=is_local)
              else:
                  self.vpp.set_interface_ip(loopback_idx, gw_ipif)
  
          router_dict = {
              'segmentation_id': seg_id,
              'physnet': physnet,
              'net_type': net_type,
              'bridge_domain_id': bridge_idx,
              'bvi_if_idx': loopback_idx,
              'gateway_ip': gateway_ip,
              'prefixlen': prefixlen,
              'is_ipv6': is_ipv6,
              'mac_address': loopback_mac,
              'is_inside': is_inside,
              'external_gateway_ip': external_gateway_ip,
              'vrf_id': vrf,
              'uplink_idx': net_data.get('if_uplink_idx'),
              'is_local': is_local
              }
          if is_inside:
              LOG.debug("Router: Created inside router port: %s",
                        router_dict)
              self.router_interfaces[port_id] = router_dict
              # Ensure that all gateway networks are exported into this
              # tenant VRF &
              # A default route exists in this VRF to the external gateway
              self.export_routes_from_tenant_vrfs(
                  source_vrf=router_dict['vrf_id'])
          else:
              LOG.debug("Router: Created outside router port: %s",
                        router_dict)
              self.router_external_interfaces[port_id] = router_dict
              # TODO(onong):
              # The current VPP NAT implementation supports only one outside
              # FIB table and by default it uses table 0, ie, the default vrf.
              # So, this is a temporary workaround to tide over the limitation.
              if not is_local:
                  self.default_route_in_default_vrf(router_dict)
              # Ensure that the gateway network is exported into all tenant
              # VRFs, with the correct default routes
                  self.export_routes_from_tenant_vrfs(
                      ext_gw_ip=router_dict['external_gateway_ip'])
          return loopback_idx
code_tokens: def ensure_router_interface_on_host ( self , port_id , router_data ) : enable_snat = True is_local = 0 if router_data . get ( 'external_gateway_info' , False ) : seg_id = router_data [ 'external_segmentation_id' ] net_type = router_data [ 'external_net_type' ] physnet = router_data [ 'external_physnet' ] vrf = vpp . DEFAULT_VRF is_inside = False enable_snat = router_data [ 'external_gateway_info' ] [ 'enable_snat' ] external_gateway_ip = router_data [ 'external_gateway_ip' ] gateway_ip = router_data [ 'gateways' ] [ 0 ] [ 0 ] prefixlen = router_data [ 'gateways' ] [ 0 ] [ 1 ] is_ipv6 = bool ( router_data [ 'gateways' ] [ 0 ] [ 2 ] ) else : seg_id = router_data [ 'segmentation_id' ] net_type = router_data [ 'net_type' ] physnet = router_data [ 'physnet' ] vrf = router_data [ 'vrf_id' ] is_inside = True external_gateway_ip = None gateway_ip = router_data [ 'gateway_ip' ] prefixlen = router_data [ 'prefixlen' ] is_ipv6 = bool ( router_data [ 'is_ipv6' ] ) net_data = self . net_driver . ensure_network ( physnet , net_type , seg_id ) bridge_idx = net_data [ 'bridge_domain_id' ] loopback_idx = self . vpp . get_bridge_bvi ( bridge_idx ) loopback_mac = vpp . mac_str_t ( router_data [ 'loopback_mac' ] ) if loopback_idx is None : loopback_idx = self . ensure_bridge_bvi ( bridge_idx , loopback_mac ) if vrf and not self . vpp . get_interface_vrf ( loopback_idx ) == vrf : self . vpp . set_interface_vrf ( loopback_idx , vrf , is_ipv6 ) try : self . vpp . set_interface_mtu ( loopback_idx , router_data [ 'mtu' ] ) except SystemExit : LOG . error ( "Error setting MTU on router interface" ) ha_enabled = cfg . CONF . ml2_vpp . enable_l3_ha if ha_enabled : if self . router_state : LOG . debug ( "Router HA state is ACTIVE" ) LOG . debug ( "Bringing UP the router intf idx: %s" , loopback_idx ) self . vpp . ifup ( loopback_idx ) self . router_interface_states [ loopback_idx ] = 1 else : LOG . debug ( "Router HA state is BACKUP" ) LOG . debug ( "Bringing DOWN the router intf idx: %s" , loopback_idx ) self . vpp . ifdown ( loopback_idx ) self . router_interface_states [ loopback_idx ] = 0 LOG . debug ( "Current router interface states: %s" , self . router_interface_states ) else : self . vpp . ifup ( loopback_idx ) int_list = self . vpp . get_snat_interfaces ( ) if loopback_idx not in int_list and enable_snat : self . vpp . set_snat_on_interface ( loopback_idx , is_inside ) if not is_inside : self . vpp . snat_overload_on_interface_address ( loopback_idx ) if net_type == TYPE_GPE and self . gpe is not None : if ( ha_enabled and self . router_state ) or not ha_enabled : self . gpe . add_local_gpe_mapping ( seg_id , loopback_mac ) addresses = self . vpp . get_interface_ip_addresses ( loopback_idx ) gw_ipif = ip_interface ( ( gateway_ip , prefixlen , ) ) if not is_inside : exists_gateway = any ( ( addr for addr in addresses if addr != gw_ipif ) ) if exists_gateway : LOG . debug ( 'A router gateway exists on the external network.' 'The current router gateway IP: %s will be added as ' 'a local VPP route' , str ( gw_ipif ) ) if gw_ipif not in addresses : if not is_inside and exists_gateway : is_local = True ip_prefix_length = 32 if gw_ipif . version == 4 else 128 self . vpp . add_ip_route ( vrf = vrf , ip_address = self . _pack_address ( gateway_ip ) , prefixlen = ip_prefix_length , next_hop_address = None , next_hop_sw_if_index = None , is_ipv6 = is_ipv6 , is_local = is_local ) else : self . vpp . set_interface_ip ( loopback_idx , gw_ipif ) router_dict = { 'segmentation_id' : seg_id , 'physnet' : physnet , 'net_type' : net_type , 'bridge_domain_id' : bridge_idx , 'bvi_if_idx' : loopback_idx , 'gateway_ip' : gateway_ip , 'prefixlen' : prefixlen , 'is_ipv6' : is_ipv6 , 'mac_address' : loopback_mac , 'is_inside' : is_inside , 'external_gateway_ip' : external_gateway_ip , 'vrf_id' : vrf , 'uplink_idx' : net_data . get ( 'if_uplink_idx' ) , 'is_local' : is_local } if is_inside : LOG . debug ( "Router: Created inside router port: %s" , router_dict ) self . router_interfaces [ port_id ] = router_dict self . export_routes_from_tenant_vrfs ( source_vrf = router_dict [ 'vrf_id' ] ) else : LOG . debug ( "Router: Created outside router port: %s" , router_dict ) self . router_external_interfaces [ port_id ] = router_dict if not is_local : self . default_route_in_default_vrf ( router_dict ) self . export_routes_from_tenant_vrfs ( ext_gw_ip = router_dict [ 'external_gateway_ip' ] ) return loopback_idx
short_docstring: Ensure a router interface on the local host.
short_docstring_tokens: Ensure a router interface on the local host .
comment: """Ensure a router interface on the local host.
  
          Creates a loopback interface and sets the bridge's BVI to the
          loopback interface to act as an L3 gateway for the network.
          For external networks, the BVI functions as an SNAT external
          interface. For updating an interface, the service plugin removes
          the old interface and then adds the new router interface. If an
          external gateway exists, ensures a local route in VPP.
  
          When Layer3 HA is enabled, the router interfaces are only enabled on
          the active VPP router. The standby router keeps the interface in
          an admin down state.
          """$SEP$# The interface could be either an external_gw or an internal router$SEP$# interface on a subnet$SEP$# Enable SNAT by default unless it is set to False$SEP$# Multiple routers on a shared external subnet is supported$SEP$# by adding local routes in VPP.$SEP$# True for local-only VPP routes.$SEP$# Create an external interfce if the external_gateway_info key is$SEP$# present, else create an internal interface$SEP$# To support multiple IP addresses on a router port, add$SEP$# the router to each of the subnets.$SEP$# Ensure the network exists on host and get the network data$SEP$# Get the bridge domain id and ensure a BVI interface for it$SEP$# Ensure a BVI (i.e. A loopback) for the bridge domain$SEP$# Create a loopback BVI interface$SEP$# Create the loopback interface, but don't bring it UP yet$SEP$# Set the VRF for tenant BVI interfaces, if not already set$SEP$# Make a best effort to set the MTU on the interface$SEP$# Log error and continue, do not exit here$SEP$# Now bring up the loopback interface, if this router is the$SEP$# ACTIVE router. Also populate the data structure$SEP$# router_interface_states so the HA code can activate and$SEP$# deactivate the interface$SEP$# Set SNAT on the interface if SNAT is enabled$SEP$# Get a list of all SNAT interfaces$SEP$# Set the SNAT 1:N overload on the external loopback interface$SEP$# Add GPE mappings for GPE type networks only on the master$SEP$# node, if ha_enabled$SEP$# Set the gateway IP address on the BVI interface, if not already set$SEP$# Is there another gateway ip_addr set on this external loopback?$SEP$# Any address other than the one we're thinking of?$SEP$# This address is not yet present?$SEP$# Add a local VRF route if another external gateway exists$SEP$# Add a local IP route if it doesn't exist$SEP$# Ensure that all gateway networks are exported into this$SEP$# tenant VRF &$SEP$# A default route exists in this VRF to the external gateway$SEP$# TODO(onong):$SEP$# The current VPP NAT implementation supports only one outside$SEP$# FIB table and by default it uses table 0, ie, the default vrf.$SEP$# So, this is a temporary workaround to tide over the limitation.$SEP$# Ensure that the gateway network is exported into all tenant$SEP$# VRFs, with the correct default routes