components/openstack/neutron/files/agent/evs_l3_agent.py
changeset 2083 87196737f09f
parent 1987 6fa18b7a0af6
child 2174 2856bd2e4b18
equal deleted inserted replaced
2082:45b7dae3df63 2083:87196737f09f
   258         if gw_ip:
   258         if gw_ip:
   259             cmd = ['/usr/bin/pfexec', '/usr/sbin/route', 'add', 'default',
   259             cmd = ['/usr/bin/pfexec', '/usr/sbin/route', 'add', 'default',
   260                    gw_ip]
   260                    gw_ip]
   261             utils.execute(cmd, check_exit_code=False)
   261             utils.execute(cmd, check_exit_code=False)
   262 
   262 
       
   263             # for each of the internal ports, add Policy Based
       
   264             # Routing (PBR) rule
       
   265             for port in ri.internal_ports:
       
   266                 internal_dlname = self.get_internal_device_name(port['id'])
       
   267                 rules = ['pass in on %s to %s:%s from any to any' %
       
   268                          (internal_dlname, external_dlname, gw_ip)]
       
   269                 ipversion = netaddr.IPNetwork(port['subnet']['cidr']).version
       
   270                 ri.ipfilters_manager.add_ipf_rules(rules, ipversion)
       
   271 
   263     def external_gateway_removed(self, ri, ex_gw_port,
   272     def external_gateway_removed(self, ri, ex_gw_port,
   264                                  external_dlname, internal_cidrs):
   273                                  external_dlname, internal_cidrs):
       
   274 
       
   275         gw_ip = ex_gw_port['subnet']['gateway_ip']
       
   276         if gw_ip:
       
   277             # remove PBR rules
       
   278             for port in ri.internal_ports:
       
   279                 internal_dlname = self.get_internal_device_name(port['id'])
       
   280                 rules = ['pass in on %s to %s:%s from any to any' %
       
   281                          (internal_dlname, external_dlname, gw_ip)]
       
   282                 ipversion = netaddr.IPNetwork(port['subnet']['cidr']).version
       
   283                 ri.ipfilters_manager.remove_ipf_rules(rules, ipversion)
       
   284 
       
   285             cmd = ['/usr/bin/pfexec', '/usr/sbin/route', 'delete', 'default',
       
   286                    gw_ip]
       
   287             utils.execute(cmd, check_exit_code=False)
   265 
   288 
   266         if net_lib.Datalink.datalink_exists(external_dlname):
   289         if net_lib.Datalink.datalink_exists(external_dlname):
   267             self.driver.fini_l3(external_dlname)
   290             self.driver.fini_l3(external_dlname)
   268             self.driver.unplug(external_dlname)
   291             self.driver.unplug(external_dlname)
   269         gw_ip = ex_gw_port['subnet']['gateway_ip']
   292 
   270         if gw_ip:
   293     def _get_ippool_name(self, mac_address, suffix=None):
   271             cmd = ['/usr/bin/pfexec', '/usr/sbin/route', 'delete', 'default',
   294         # Generate a unique-name for ippool(1m) from that last 3
   272                    gw_ip]
   295         # bytes of mac-address. It is called pool name, but it is
   273             utils.execute(cmd, check_exit_code=False)
   296         # actually a 32 bit integer
   274 
   297         name = mac_address.split(':')[3:]
   275     def _get_ippool_name(self, mac_address):
   298         if suffix:
   276         # generate a unique-name for ippool(1m) from that last 3
   299             name.append(suffix)
   277         # bytes of mac-address
   300         return int("".join(name), 16)
   278         mac_suffix = mac_address.split(':')[3:]
       
   279         return int("".join(mac_suffix), 16)
       
   280 
   301 
   281     def internal_network_added(self, ri, port):
   302     def internal_network_added(self, ri, port):
   282 
       
   283         internal_dlname = self.get_internal_device_name(port['id'])
   303         internal_dlname = self.get_internal_device_name(port['id'])
   284         if not net_lib.Datalink.datalink_exists(internal_dlname):
   304         # driver just returns if datalink and IP interface already exists
   285             self.driver.plug(port['tenant_id'], port['network_id'], port['id'],
   305         self.driver.plug(port['tenant_id'], port['network_id'], port['id'],
   286                              internal_dlname)
   306                          internal_dlname)
   287         self.driver.init_l3(internal_dlname, [port['ip_cidr']])
   307         self.driver.init_l3(internal_dlname, [port['ip_cidr']])
   288 
   308 
   289         # add ippool(1m) for the new internal port
   309         # Since we support shared router model, we need to block the new
   290         new_ippool_name = self._get_ippool_name(port['mac_address'])
   310         # internal port from reaching other tenant's ports
   291         ri.ipfilters_manager.add_ippool(new_ippool_name, None)
   311         block_pname = self._get_ippool_name(port['mac_address'])
       
   312         ri.ipfilters_manager.add_ippool(block_pname, None)
       
   313         if self.conf.allow_forwarding_between_networks:
       
   314             # If allow_forwarding_between_networks is set, then we need to
       
   315             # allow forwarding of packets between same tenant's ports.
       
   316             allow_pname = self._get_ippool_name(port['mac_address'], '0')
       
   317             ri.ipfilters_manager.add_ippool(allow_pname, None)
   292 
   318 
   293         # walk through the other internal ports and retrieve their
   319         # walk through the other internal ports and retrieve their
   294         # cidrs and at the same time add the new internal port's
   320         # cidrs and at the same time add the new internal port's
   295         # cidr to them
   321         # cidr to them
   296         subnet_cidr = port['subnet']['cidr']
   322         port_subnet = port['subnet']['cidr']
   297         other_subnet_cidrs = []
   323         block_subnets = []
   298         for oip in ri.internal_ports:
   324         allow_subnets = []
   299             if oip['mac_address'] != port['mac_address']:
   325         for internal_port in ri.internal_ports:
   300                 if (self.conf.allow_forwarding_between_networks and
   326             if internal_port['mac_address'] == port['mac_address']:
   301                         oip['tenant_id'] == port['tenant_id']):
   327                 continue
   302                     continue
   328             if (self.conf.allow_forwarding_between_networks and
   303                 other_subnet_cidrs.append(oip['subnet']['cidr'])
   329                     internal_port['tenant_id'] == port['tenant_id']):
   304                 ippool_name = self._get_ippool_name(oip['mac_address'])
   330                 allow_subnets.append(internal_port['subnet']['cidr'])
   305                 ri.ipfilters_manager.add_ippool(ippool_name, [subnet_cidr])
   331                 # we need to add the port's subnet to this internal_port's
   306         # update the new port's pool with other port's cidrs
   332                 # allowed_subnet_pool
   307         ri.ipfilters_manager.add_ippool(new_ippool_name, other_subnet_cidrs)
   333                 iport_allow_pname = \
   308 
   334                     self._get_ippool_name(internal_port['mac_address'], '0')
   309         # now setup the IPF rule
   335                 ri.ipfilters_manager.add_ippool(iport_allow_pname,
       
   336                                                 [port_subnet])
       
   337             else:
       
   338                 block_subnets.append(internal_port['subnet']['cidr'])
       
   339                 iport_block_pname = \
       
   340                     self._get_ippool_name(internal_port['mac_address'])
       
   341                 ri.ipfilters_manager.add_ippool(iport_block_pname,
       
   342                                                 [port_subnet])
       
   343         # update the new port's pool with other ports' subnet
       
   344         ri.ipfilters_manager.add_ippool(block_pname, block_subnets)
       
   345         if self.conf.allow_forwarding_between_networks:
       
   346             ri.ipfilters_manager.add_ippool(allow_pname, allow_subnets)
       
   347 
       
   348         # now setup the IPF rules
   310         rules = ['block in quick on %s from %s to pool/%d' %
   349         rules = ['block in quick on %s from %s to pool/%d' %
   311                  (internal_dlname, subnet_cidr, new_ippool_name)]
   350                  (internal_dlname, port_subnet, block_pname)]
   312         ipversion = netaddr.IPNetwork(subnet_cidr).version
   351         # pass in packets between networks that belong to same tenant
       
   352         if self.conf.allow_forwarding_between_networks:
       
   353             rules.append('pass in quick on %s from %s to pool/%d' %
       
   354                          (internal_dlname, port_subnet, allow_pname))
       
   355         # if the external gateway is already setup for the shared router,
       
   356         # then we need to add Policy Based Routing (PBR) for this internal
       
   357         # network
       
   358         ex_gw_port = ri.ex_gw_port
       
   359         ex_gw_ip = (ex_gw_port['subnet']['gateway_ip'] if ex_gw_port else None)
       
   360         if ex_gw_ip:
       
   361             external_dlname = self.get_external_device_name(ex_gw_port['id'])
       
   362             rules.append('pass in on %s to %s:%s from any to any' %
       
   363                          (internal_dlname, external_dlname, ex_gw_ip))
       
   364 
       
   365         ipversion = netaddr.IPNetwork(port_subnet).version
   313         ri.ipfilters_manager.add_ipf_rules(rules, ipversion)
   366         ri.ipfilters_manager.add_ipf_rules(rules, ipversion)
   314 
   367 
   315     def internal_network_removed(self, ri, port):
   368     def internal_network_removed(self, ri, port):
   316         internal_dlname = self.get_internal_device_name(port['id'])
   369         internal_dlname = self.get_internal_device_name(port['id'])
       
   370         port_subnet = port['subnet']['cidr']
       
   371         # remove all the IP filter rules that we added during
       
   372         # internal network addition
       
   373         block_pname = self._get_ippool_name(port['mac_address'])
       
   374         rules = ['block in quick on %s from %s to pool/%d' %
       
   375                  (internal_dlname, port_subnet, block_pname)]
       
   376         if self.conf.allow_forwarding_between_networks:
       
   377             allow_pname = self._get_ippool_name(port['mac_address'], '0')
       
   378             rules.append('pass in quick on %s from %s to pool/%d' %
       
   379                          (internal_dlname, port_subnet, allow_pname))
       
   380 
       
   381         # remove all the IP filter rules that we added during
       
   382         # external network addition
       
   383         ex_gw_port = ri.ex_gw_port
       
   384         ex_gw_ip = (ex_gw_port['subnet']['gateway_ip'] if ex_gw_port else None)
       
   385         if ex_gw_ip:
       
   386             external_dlname = self.get_external_device_name(ex_gw_port['id'])
       
   387             rules.append('pass in on %s to %s:%s from any to any' %
       
   388                          (internal_dlname, external_dlname, ex_gw_ip))
       
   389         ipversion = netaddr.IPNetwork(port['subnet']['cidr']).version
       
   390         ri.ipfilters_manager.remove_ipf_rules(rules, ipversion)
       
   391 
       
   392         # remove the ippool
       
   393         ri.ipfilters_manager.remove_ippool(block_pname, None)
       
   394         if self.conf.allow_forwarding_between_networks:
       
   395             ri.ipfilters_manager.remove_ippool(allow_pname, None)
       
   396 
       
   397         for internal_port in ri.internal_ports:
       
   398             if (self.conf.allow_forwarding_between_networks and
       
   399                     internal_port['tenant_id'] == port['tenant_id']):
       
   400                 iport_allow_pname = \
       
   401                     self._get_ippool_name(internal_port['mac_address'], '0')
       
   402                 ri.ipfilters_manager.remove_ippool(iport_allow_pname,
       
   403                                                    [port_subnet])
       
   404             else:
       
   405                 iport_block_pname = \
       
   406                     self._get_ippool_name(internal_port['mac_address'])
       
   407                 ri.ipfilters_manager.remove_ippool(iport_block_pname,
       
   408                                                    [port_subnet])
       
   409 
   317         if net_lib.Datalink.datalink_exists(internal_dlname):
   410         if net_lib.Datalink.datalink_exists(internal_dlname):
   318             self.driver.fini_l3(internal_dlname)
   411             self.driver.fini_l3(internal_dlname)
   319             self.driver.unplug(internal_dlname)
   412             self.driver.unplug(internal_dlname)
   320 
       
   321         # remove all the IP filter rules that we added during addition.
       
   322         ippool_name = self._get_ippool_name(port['mac_address'])
       
   323         rules = ['block in quick on %s from %s to pool/%d' %
       
   324                  (internal_dlname, port['subnet']['cidr'], ippool_name)]
       
   325         ipversion = netaddr.IPNetwork(port['subnet']['cidr']).version
       
   326         ri.ipfilters_manager.remove_ipf_rules(rules, ipversion)
       
   327         # remove the ippool
       
   328         ri.ipfilters_manager.remove_ippool(ippool_name, None)
       
   329         for internal_port in ri.internal_ports:
       
   330             if (self.conf.allow_forwarding_between_networks and
       
   331                     internal_port['tenant_id'] == port['tenant_id']):
       
   332                 continue
       
   333             ippool_name = \
       
   334                 self._get_ippool_name(internal_port['mac_address'])
       
   335             subnet_cidr = internal_port['subnet']['cidr']
       
   336             ri.ipfilters_manager.remove_ippool(ippool_name, [subnet_cidr])
       
   337 
   413 
   338     def routers_updated(self, context, routers):
   414     def routers_updated(self, context, routers):
   339         super(EVSL3NATAgent, self).routers_updated(context, routers)
   415         super(EVSL3NATAgent, self).routers_updated(context, routers)
   340         if routers:
   416         if routers:
   341             # If router's interface was removed, then the VNIC associated
   417             # If router's interface was removed, then the VNIC associated