diff --git a/dragonflow/controller/apps/dnat.py b/dragonflow/controller/apps/dnat.py index 6a16fc8b3..2b32cad0d 100644 --- a/dragonflow/controller/apps/dnat.py +++ b/dragonflow/controller/apps/dnat.py @@ -314,8 +314,45 @@ class DNATApp(df_base_app.DFlowApp): match=self._get_ingress_icmp_flow_match(floatingip, icmp_type), ) + def _get_source_port_detector_match(self, floatingip): + match = self.parser.OFPMatch( + eth_type=ether.ETH_TYPE_IP, + ipv4_src=floatingip.floating_ip_address, + reg6=0, + ) + return match + + def _install_source_port_detector(self, floatingip): + parser = self.parser + match = self._get_source_port_detector_match(floatingip) + actions = [ + parser.OFPActionSetField(reg6=floatingip.lport.unique_key), + ] + + inst_type = self.datapath.ofproto.OFPIT_APPLY_ACTIONS + inst = [ + parser.OFPInstructionActions(inst_type, actions), + parser.OFPInstructionGotoTable(const.L2_LOOKUP_TABLE), + ] + self.mod_flow( + table_id=const.EXTERNAL_INGRESS_DETECT_SOURCE_TABLE, + priority=const.PRIORITY_HIGH, + match=match, + inst=inst, + ) + + def _uninstall_source_port_detector(self, floatingip): + match = self._get_source_port_detector_match(floatingip) + self.mod_flow( + command=self.ofproto.OFPFC_DELETE_STRICT, + table_id=const.EXTERNAL_INGRESS_DETECT_SOURCE_TABLE, + priority=const.PRIORITY_HIGH, + match=match, + ) + def _install_ingress_nat_flows(self, floatingip): self._get_arp_responder(floatingip).add() + self._install_source_port_detector(floatingip) self._install_ingress_capture_flow(floatingip) self._install_ingress_translate_flow(floatingip) self._install_ingress_icmp_flows(floatingip) @@ -325,6 +362,7 @@ class DNATApp(df_base_app.DFlowApp): self._uninstall_ingress_capture_flow(floatingip) self._uninstall_ingress_translate_flow(floatingip) self._uninstall_ingress_icmp_flows(floatingip) + self._uninstall_source_port_detector(floatingip) def _get_dnat_egress_match(self, floatingip, **kwargs): return self.parser.OFPMatch( diff --git a/dragonflow/controller/apps/provider.py b/dragonflow/controller/apps/provider.py index 07002e702..fd3d01633 100644 --- a/dragonflow/controller/apps/provider.py +++ b/dragonflow/controller/apps/provider.py @@ -112,6 +112,11 @@ class ProviderApp(df_base_app.DFlowApp): def switch_features_handler(self, ev): self._setup_physical_bridges(self.bridge_mappings) + self.add_flow_go_to_table( + const.EXTERNAL_INGRESS_DETECT_SOURCE_TABLE, + const.PRIORITY_DEFAULT, + const.L2_LOOKUP_TABLE + ) @df_base_app.register_event(l2.LogicalPort, l2.EVENT_BIND_LOCAL) def _add_local_port(self, lport): @@ -286,7 +291,8 @@ class ProviderApp(df_base_app.DFlowApp): action_inst = self.parser.OFPInstructionActions( self.ofproto.OFPIT_APPLY_ACTIONS, actions) - goto_inst = self.parser.OFPInstructionGotoTable(const.L2_LOOKUP_TABLE) + goto_inst = self.parser.OFPInstructionGotoTable( + const.EXTERNAL_INGRESS_DETECT_SOURCE_TABLE) inst = [action_inst, goto_inst] self.mod_flow( diff --git a/dragonflow/controller/common/constants.py b/dragonflow/controller/common/constants.py index d0cb1bb67..3b081ad0f 100644 --- a/dragonflow/controller/common/constants.py +++ b/dragonflow/controller/common/constants.py @@ -26,6 +26,8 @@ # translated to network id and the packet is forwarded to # INGRESS_DESTINATION_PORT_LOOKUP_TABLE. INGRESS_CLASSIFICATION_DISPATCH_TABLE = 0 +# Detect reg6 (provider network and dNAT) +EXTERNAL_INGRESS_DETECT_SOURCE_TABLE = 2 # All packets from unknown ovs ports are dropped here. Other packets # are forwarded to table EGRESS_CONNTRACK_TABLE. EGRESS_PORT_SECURITY_TABLE = 5