diff --git a/dragonflow/controller/apps/dhcp.py b/dragonflow/controller/apps/dhcp.py index 6d71e2d5d..758e55664 100644 --- a/dragonflow/controller/apps/dhcp.py +++ b/dragonflow/controller/apps/dhcp.py @@ -31,7 +31,9 @@ from ryu.ofproto import ether from dragonflow.common import utils as df_utils from dragonflow import conf as cfg +from dragonflow.controller.common import arp_responder from dragonflow.controller.common import constants as const +from dragonflow.controller.common import icmp_responder from dragonflow.controller import df_base_app from dragonflow.db.models import constants as model_constants from dragonflow.db.models import host_route @@ -552,3 +554,46 @@ class DHCPApp(df_base_app.DFlowApp): hard_timeout=hard_timeout, table_id=const.DHCP_TABLE, match=match) + + @df_base_app.register_event(l2.LogicalPort, model_constants.EVENT_CREATED) + def _lport_created(self, lport): + if lport.device_owner == n_const.DEVICE_OWNER_DHCP: + self._install_dhcp_port_responders(lport) + + @df_base_app.register_event(l2.LogicalPort, model_constants.EVENT_UPDATED) + def _lport_updated(self, lport, orig_lport): + if lport.device_owner != n_const.DEVICE_OWNER_DHCP: + return + + if (lport.ip, lport.mac) != (orig_lport.id, orig_lport.mac): + self._uninstall_dhcp_port_responders(orig_lport) + self._install_dhcp_port_responders(lport) + + @df_base_app.register_event(l2.LogicalPort, model_constants.EVENT_DELETED) + def _lport_deleted(self, lport): + if lport.device_owner == n_const.DEVICE_OWNER_DHCP: + self._uninstall_dhcp_port_responders(lport) + + def _get_dhcp_port_arp_responder(self, lport): + return arp_responder.ArpResponder( + app=self, + network_id=lport.lswitch.unique_key, + interface_ip=lport.ip, + interface_mac=lport.mac, + ) + + def _get_dhcp_port_icmp_responder(self, lport): + return icmp_responder.ICMPResponder( + app=self, + network_id=lport.lswitch.unique_key, + interface_ip=lport.ip, + table_id=const.L2_LOOKUP_TABLE, + ) + + def _install_dhcp_port_responders(self, lport): + self._get_dhcp_port_arp_responder(lport).add() + self._get_dhcp_port_icmp_responder(lport).add() + + def _uninstall_dhcp_port_responders(self, lport): + self._get_dhcp_port_arp_responder(lport).remove() + self._get_dhcp_port_icmp_responder(lport).remove() diff --git a/dragonflow/controller/common/icmp_responder.py b/dragonflow/controller/common/icmp_responder.py index ac2498326..cd509f646 100644 --- a/dragonflow/controller/common/icmp_responder.py +++ b/dragonflow/controller/common/icmp_responder.py @@ -34,13 +34,14 @@ class ICMPResponder(object): @param table_id Where the respondor will be installed. """ def __init__(self, app, interface_ip, router_key=None, dst_mac=None, - table_id=const.L3_LOOKUP_TABLE): + table_id=const.L3_LOOKUP_TABLE, network_id=None): self.app = app self.datapath = app.datapath self.interface_ip = interface_ip self.router_key = router_key self.dst_mac = dst_mac self.table_id = table_id + self.network_id = network_id def _get_match(self): parser = self.datapath.ofproto_parser @@ -52,6 +53,8 @@ class ICMPResponder(object): match_fields.update({'eth_dst': self.dst_mac}) elif self.router_key: match_fields.update({'reg5': self.router_key}) + if self.network_id is not None: + match_fields['metadata'] = self.network_id match = parser.OFPMatch(**match_fields) return match