Migrate portsec app to new framework
Change-Id: I5c76eabb9e15c628a6ca800123a135b7e1347c3f Related-Bug: #1738986 Co-Authored-By: Lihi Wishnitzer <lihiwish@gmail.com>
This commit is contained in:
parent
b7eda732f5
commit
e32364e80d
|
@ -18,7 +18,7 @@ OVS_BRANCH=${OVS_BRANCH:-branch-2.6}
|
|||
EXTERNAL_HOST_IP=${EXTERNAL_HOST_IP:-}
|
||||
|
||||
DEFAULT_TUNNEL_TYPES="vxlan,geneve,gre"
|
||||
DEFAULT_APPS_LIST="portbinding,l2,l3_proactive,dhcp,dnat,sg,portsec,portqos,classifier,tunneling,provider"
|
||||
DEFAULT_APPS_LIST="portbinding,l2,l3_proactive,dhcp,dnat,sg,portqos,classifier,tunneling,provider"
|
||||
|
||||
if [[ $ENABLE_DF_SFC == "True" ]]; then
|
||||
DEFAULT_APPS_LIST="$DEFAULT_APPS_LIST,fc,sfc"
|
||||
|
|
|
@ -35,7 +35,7 @@ class ClassifierApp(df_base_app.DFlowApp):
|
|||
self.add_flow_go_to_table(
|
||||
table=const.INGRESS_CLASSIFICATION_DISPATCH_TABLE,
|
||||
priority=const.PRIORITY_DEFAULT,
|
||||
goto_table_id=const.EGRESS_PORT_SECURITY_TABLE,
|
||||
goto_table_id=self.dfdp.apps['portsec'].entrypoints.default,
|
||||
)
|
||||
|
||||
@df_base_app.register_event(ovs.OvsPort, model_constants.EVENT_CREATED)
|
||||
|
|
|
@ -73,11 +73,6 @@ class L2App(df_base_app.DFlowApp):
|
|||
const.PRIORITY_MEDIUM,
|
||||
const.IPV6_ND_TABLE, match=match)
|
||||
|
||||
# Default: traffic => send to connection track table
|
||||
self.add_flow_go_to_table(const.EGRESS_PORT_SECURITY_TABLE,
|
||||
const.PRIORITY_DEFAULT,
|
||||
const.EGRESS_CONNTRACK_TABLE)
|
||||
|
||||
# Default: traffic => send to service classification table
|
||||
self.add_flow_go_to_table(const.EGRESS_CONNTRACK_TABLE,
|
||||
const.PRIORITY_DEFAULT,
|
||||
|
|
|
@ -203,15 +203,17 @@ class MetadataServiceApp(df_base_app.DFlowApp):
|
|||
ip_proto=ipv4.inet.IPPROTO_TCP,
|
||||
tcp_dst=const.METADATA_HTTP_PORT,
|
||||
)
|
||||
inst = [parser.OFPInstructionGotoTable(
|
||||
const.SERVICES_CLASSIFICATION_TABLE)]
|
||||
actions = [
|
||||
parser.NXActionResubmitTable(
|
||||
table_id=self.dfdp.apps['portsec'].exitpoints.services),
|
||||
]
|
||||
# Bypass the security group check for metadata request.
|
||||
self.mod_flow(
|
||||
table_id=const.EGRESS_PORT_SECURITY_TABLE,
|
||||
table_id=self.dfdp.apps['portsec'].states.main,
|
||||
command=ofproto.OFPFC_ADD,
|
||||
priority=const.PRIORITY_VERY_HIGH,
|
||||
match=match,
|
||||
inst=inst)
|
||||
actions=actions)
|
||||
|
||||
inst = self._get_incoming_flow_instructions(ofproto, parser)
|
||||
self.mod_flow(
|
||||
|
|
|
@ -21,6 +21,7 @@ from ryu.lib.packet import arp
|
|||
from ryu.lib.packet import in_proto
|
||||
from ryu.ofproto import ether
|
||||
|
||||
from dragonflow.controller import app_base
|
||||
from dragonflow.controller.common import constants as const
|
||||
from dragonflow.controller.common import utils
|
||||
from dragonflow.controller import df_base_app
|
||||
|
@ -32,13 +33,42 @@ IPV4_SRC_MATCH_ITEM = 'ipv4_src'
|
|||
IPV6_SRC_MATCH_ITEM = 'ipv6_src'
|
||||
|
||||
|
||||
class PortSecApp(df_base_app.DFlowApp):
|
||||
@app_base.define_specification(
|
||||
states=('main',),
|
||||
public_mapping=app_base.VariableMapping(
|
||||
source_port_key='reg6',
|
||||
),
|
||||
entrypoints=(
|
||||
app_base.Entrypoint(
|
||||
name='default',
|
||||
target='main',
|
||||
consumes=(
|
||||
'source_port_key',
|
||||
),
|
||||
),
|
||||
),
|
||||
exitpoints=(
|
||||
app_base.Exitpoint(
|
||||
name='default',
|
||||
provides=(
|
||||
'source_port_key',
|
||||
),
|
||||
),
|
||||
app_base.Exitpoint(
|
||||
name='services',
|
||||
provides=(
|
||||
'source_port_key',
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
class PortSecApp(app_base.Base):
|
||||
|
||||
def _add_flow_drop(self, priority, match):
|
||||
drop_inst = None
|
||||
self.mod_flow(
|
||||
inst=drop_inst,
|
||||
table_id=const.EGRESS_PORT_SECURITY_TABLE,
|
||||
table_id=self.states.main,
|
||||
priority=priority,
|
||||
match=match)
|
||||
|
||||
|
@ -125,9 +155,9 @@ class PortSecApp(df_base_app.DFlowApp):
|
|||
|
||||
def _install_flows_check_valid_ip_and_mac(self, unique_key, ip, mac):
|
||||
match = self._get_ip_match_obj(unique_key, mac, ip)
|
||||
self.add_flow_go_to_table(const.EGRESS_PORT_SECURITY_TABLE,
|
||||
self.add_flow_go_to_table(self.states.main,
|
||||
const.PRIORITY_HIGH,
|
||||
const.EGRESS_CONNTRACK_TABLE,
|
||||
self.exitpoints.default,
|
||||
match=match)
|
||||
|
||||
ip_version = netaddr.IPAddress(ip).version
|
||||
|
@ -136,9 +166,9 @@ class PortSecApp(df_base_app.DFlowApp):
|
|||
match = self._get_arp_match_obj(unique_key, mac, ip)
|
||||
else:
|
||||
match = self._get_nd_match_object(unique_key, mac, ip)
|
||||
self.add_flow_go_to_table(const.EGRESS_PORT_SECURITY_TABLE,
|
||||
self.add_flow_go_to_table(self.states.main,
|
||||
const.PRIORITY_HIGH,
|
||||
const.SERVICES_CLASSIFICATION_TABLE,
|
||||
self.exitpoints.services,
|
||||
match=match)
|
||||
|
||||
def _uninstall_flows_check_valid_ip_and_mac(self, unique_key, ip, mac):
|
||||
|
@ -160,9 +190,9 @@ class PortSecApp(df_base_app.DFlowApp):
|
|||
# Other packets with valid source mac pass
|
||||
match = parser.OFPMatch(reg6=unique_key,
|
||||
eth_src=mac)
|
||||
self.add_flow_go_to_table(const.EGRESS_PORT_SECURITY_TABLE,
|
||||
self.add_flow_go_to_table(self.states.main,
|
||||
const.PRIORITY_LOW,
|
||||
const.SERVICES_CLASSIFICATION_TABLE,
|
||||
self.exitpoints.services,
|
||||
match=match)
|
||||
|
||||
def _uninstall_flows_check_valid_mac(self, unique_key, mac):
|
||||
|
@ -184,9 +214,9 @@ class PortSecApp(df_base_app.DFlowApp):
|
|||
udp_src=const.DHCP_CLIENT_PORT,
|
||||
udp_dst=const.DHCP_SERVER_PORT)
|
||||
|
||||
self.add_flow_go_to_table(const.EGRESS_PORT_SECURITY_TABLE,
|
||||
self.add_flow_go_to_table(self.states.main,
|
||||
const.PRIORITY_HIGH,
|
||||
const.EGRESS_CONNTRACK_TABLE,
|
||||
self.exitpoints.default,
|
||||
match=match)
|
||||
|
||||
# DHCPv6 packets with the vm mac pass
|
||||
|
@ -198,24 +228,24 @@ class PortSecApp(df_base_app.DFlowApp):
|
|||
udp_src=const.DHCPV6_CLIENT_PORT,
|
||||
udp_dst=const.DHCPV6_SERVER_PORT)
|
||||
|
||||
self.add_flow_go_to_table(const.EGRESS_PORT_SECURITY_TABLE,
|
||||
self.add_flow_go_to_table(self.states.main,
|
||||
const.PRIORITY_HIGH,
|
||||
const.EGRESS_CONNTRACK_TABLE,
|
||||
self.exitpoints.default,
|
||||
match=match)
|
||||
|
||||
# Arp probe packets with the vm mac pass
|
||||
match = self._get_arp_match_obj(unique_key=unique_key,
|
||||
mac=vm_mac,
|
||||
arp_op=arp.ARP_REQUEST)
|
||||
self.add_flow_go_to_table(const.EGRESS_PORT_SECURITY_TABLE,
|
||||
self.add_flow_go_to_table(self.states.main,
|
||||
const.PRIORITY_HIGH,
|
||||
const.SERVICES_CLASSIFICATION_TABLE,
|
||||
self.exitpoints.services,
|
||||
match=match)
|
||||
|
||||
match = self._get_nd_match_object(unique_key, vm_mac)
|
||||
self.add_flow_go_to_table(const.EGRESS_PORT_SECURITY_TABLE,
|
||||
self.add_flow_go_to_table(self.states.main,
|
||||
const.PRIORITY_HIGH,
|
||||
const.SERVICES_CLASSIFICATION_TABLE,
|
||||
self.exitpoints.services,
|
||||
match=match)
|
||||
|
||||
def _uninstall_flows_check_only_vm_mac(self, unique_key, vm_mac):
|
||||
|
@ -302,7 +332,7 @@ class PortSecApp(df_base_app.DFlowApp):
|
|||
|
||||
def _remove_one_port_security_flow(self, priority, match):
|
||||
ofproto = self.ofproto
|
||||
self.mod_flow(table_id=const.EGRESS_PORT_SECURITY_TABLE,
|
||||
self.mod_flow(table_id=self.states.main,
|
||||
priority=priority,
|
||||
match=match,
|
||||
command=ofproto.OFPFC_DELETE_STRICT)
|
||||
|
@ -335,9 +365,9 @@ class PortSecApp(df_base_app.DFlowApp):
|
|||
|
||||
# Send packets to next table directly
|
||||
match = parser.OFPMatch(reg6=unique_key)
|
||||
self.add_flow_go_to_table(const.EGRESS_PORT_SECURITY_TABLE,
|
||||
self.add_flow_go_to_table(self.states.main,
|
||||
const.PRIORITY_HIGH,
|
||||
const.EGRESS_CONNTRACK_TABLE,
|
||||
self.exitpoints.default,
|
||||
match=match)
|
||||
|
||||
def _uninstall_disable_flow(self, lport):
|
||||
|
@ -370,7 +400,8 @@ class PortSecApp(df_base_app.DFlowApp):
|
|||
self._subtract_lists(new_valid_macs, old_valid_macs)
|
||||
return added_valid_macs, removed_valid_macs
|
||||
|
||||
def switch_features_handler(self, ev):
|
||||
def initialize(self):
|
||||
super(PortSecApp, self).initialize()
|
||||
parser = self.parser
|
||||
|
||||
# Ip default drop
|
||||
|
|
|
@ -419,7 +419,7 @@ class MplsDriver(_SimpleMplsLabelAllocator, sfc_driver_base.SfcBaseDriver):
|
|||
port_pair):
|
||||
for flow_classifier in port_chain.flow_classifiers:
|
||||
self.app.mod_flow(
|
||||
table_id=constants.EGRESS_PORT_SECURITY_TABLE,
|
||||
table_id=self.app.dfdp.apps['portsec'].states.main,
|
||||
priority=constants.PRIORITY_VERY_HIGH,
|
||||
match=self.app.parser.OFPMatch(
|
||||
reg6=port_pair.egress_port.unique_key,
|
||||
|
@ -430,22 +430,16 @@ class MplsDriver(_SimpleMplsLabelAllocator, sfc_driver_base.SfcBaseDriver):
|
|||
port_pair_group,
|
||||
),
|
||||
),
|
||||
inst=[
|
||||
self.app.parser.OFPInstructionActions(
|
||||
self.app.ofproto.OFPIT_APPLY_ACTIONS,
|
||||
[
|
||||
self.app.parser.OFPActionSetField(
|
||||
mpls_label=self._get_egress_label(
|
||||
port_chain,
|
||||
flow_classifier,
|
||||
port_pair_group
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
self.app.parser.OFPInstructionGotoTable(
|
||||
constants.SFC_MPLS_DISPATCH_TABLE,
|
||||
actions=[
|
||||
self.app.parser.OFPActionSetField(
|
||||
mpls_label=self._get_egress_label(
|
||||
port_chain,
|
||||
flow_classifier,
|
||||
port_pair_group
|
||||
),
|
||||
),
|
||||
self.app.parser.NXActionResubmitTable(
|
||||
table_id=constants.SFC_MPLS_DISPATCH_TABLE),
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -460,7 +454,7 @@ class MplsDriver(_SimpleMplsLabelAllocator, sfc_driver_base.SfcBaseDriver):
|
|||
|
||||
for eth_type in self._ETH_TYPE_TO_TC:
|
||||
self.app.mod_flow(
|
||||
table_id=constants.EGRESS_PORT_SECURITY_TABLE,
|
||||
table_id=self.app.dfdp.apps['portsec'].states.main,
|
||||
priority=constants.PRIORITY_VERY_HIGH,
|
||||
match=self.app.parser.OFPMatch(
|
||||
reg6=port_pair.egress_port.unique_key,
|
||||
|
@ -501,7 +495,7 @@ class MplsDriver(_SimpleMplsLabelAllocator, sfc_driver_base.SfcBaseDriver):
|
|||
for flow_classifier in port_chain.flow_classifiers:
|
||||
self.app.mod_flow(
|
||||
command=self.app.ofproto.OFPFC_DELETE_STRICT,
|
||||
table_id=constants.EGRESS_PORT_SECURITY_TABLE,
|
||||
table_id=self.app.dfdp.apps['portsec'].states.main,
|
||||
priority=constants.PRIORITY_VERY_HIGH,
|
||||
match=self.app.parser.OFPMatch(
|
||||
reg6=port_pair.egress_port.unique_key,
|
||||
|
@ -519,7 +513,7 @@ class MplsDriver(_SimpleMplsLabelAllocator, sfc_driver_base.SfcBaseDriver):
|
|||
self.app.mod_flow(
|
||||
command=self.app.ofproto.OFPFC_DELETE_STRICT,
|
||||
priority=constants.PRIORITY_VERY_HIGH,
|
||||
table_id=constants.EGRESS_PORT_SECURITY_TABLE,
|
||||
table_id=self.app.dfdp.apps['portsec'].states.main,
|
||||
match=self.app.parser.OFPMatch(
|
||||
reg6=port_pair.egress_port.unique_key,
|
||||
eth_type=eth_type,
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
# First table in the pipeline. All packets are landed here.
|
||||
# In case packet is originated from local port, it is forwarded
|
||||
# to EGRESS_PORT_SECURITY_TABLE.
|
||||
# to the port sec application.
|
||||
# In case packet is coming from outside with a fip, it is
|
||||
# forwarded to table INGRESS_NAT_TABLE for translation.
|
||||
# In case the packet is coming with a tunnel id, it is
|
||||
|
@ -28,9 +28,6 @@
|
|||
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
|
||||
# Next 2 tables are related to connection tracking and packet filtering.
|
||||
# Used for SG.
|
||||
EGRESS_CONNTRACK_TABLE = 10
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# under the License.
|
||||
|
||||
import netaddr
|
||||
import six
|
||||
import time
|
||||
|
||||
from neutron_lib import constants as n_const
|
||||
|
@ -25,7 +26,8 @@ from dragonflow.tests.fullstack import test_objects as objects
|
|||
class TestOVSFlowsForPortSecurity(test_base.DFTestBase):
|
||||
|
||||
def _is_expected_flow(self, flow, expected_list):
|
||||
if flow['table'] != str(const.EGRESS_PORT_SECURITY_TABLE):
|
||||
table_id_u = six.text_type(self.dfdp.apps['portsec'].states.main)
|
||||
if flow['table'] != table_id_u:
|
||||
return False
|
||||
|
||||
priority = expected_list['priority']
|
||||
|
@ -63,10 +65,10 @@ class TestOVSFlowsForPortSecurity(test_base.DFTestBase):
|
|||
|
||||
unique_key_match = "reg6=" + hex(unique_key)
|
||||
dl_src_match = "dl_src=" + mac
|
||||
goto_conntrack_table_action = \
|
||||
"goto_table:" + str(const.EGRESS_CONNTRACK_TABLE)
|
||||
goto_classification_table_action = \
|
||||
"goto_table:" + str(const.SERVICES_CLASSIFICATION_TABLE)
|
||||
exitpoints = self.dfdp.apps['portsec'].exitpoints
|
||||
goto_conntrack_table_action = "goto_table:" + str(exitpoints.default)
|
||||
goto_classification_table_action = ("goto_table:" +
|
||||
str(exitpoints.services))
|
||||
|
||||
# priority: High, match: reg6=unique_key, dl_src=$vm_mac,
|
||||
# dl_dst=ff:ff:ff:ff:ff:ff, udp, tp_src=68, tp_dst=67,
|
||||
|
@ -205,13 +207,6 @@ class TestOVSFlowsForPortSecurity(test_base.DFTestBase):
|
|||
"actions": "drop"
|
||||
})
|
||||
|
||||
# priority: default, goto const.EGRESS_CONNTRACK_TABLE
|
||||
expected_flow_list.append({
|
||||
"priority": str(const.PRIORITY_DEFAULT),
|
||||
"match_list": [],
|
||||
"actions": "goto_table:" + str(const.EGRESS_CONNTRACK_TABLE)
|
||||
})
|
||||
|
||||
self._check_all_flows_existed(expected_flow_list)
|
||||
|
||||
def _test_anti_spoof_flows(self, subnet_info):
|
||||
|
|
|
@ -1,2 +1,8 @@
|
|||
vertices: {}
|
||||
edges: {}
|
||||
vertices:
|
||||
portsec:
|
||||
type: portsec
|
||||
|
||||
edges:
|
||||
dragonflow-legacy.out.5: portsec.in.default
|
||||
portsec.out.default: dragonflow-legacy.in.10
|
||||
portsec.out.services: dragonflow-legacy.in.20
|
||||
|
|
Loading…
Reference in New Issue