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 |