From 518ec54b6dfa699c547cc89807773ae90229ef8f Mon Sep 17 00:00:00 2001 From: shylou Date: Tue, 28 Nov 2023 17:52:48 +0800 Subject: [PATCH] northd: Add option to enable conntrack for router port By default, OVN skips the conntrack process for router type LSP within a LS. It seems unnecessary for the LSP whose peer is l3dgw_port. Therefore, we introduce an option named 'enable_conntrack', which defaults to false and can be set to true to enable conntrack for the LSP whose peer is l3dgw_port. And then we can implement a gateway stateful firewall by dgw with stateful ACL. For example: prelude: R1-S1 is a l3dgw_port ovn-nbctl pg-add pg_dgw ovn-nbctl pg-set-ports pg_dgw S1-R1 ovn-nbctl acl-add pg_dgw from-lport 1002 "inport == @pg_dgw && ip4" allow-related ovn-nbctl acl-add pg_dgw to-lport 1003 "outport == @pg_dgw && ip4" allow-related ovn-nbctl lsp-set-options S1-R1 router-port=R1-S1 enable_conntrack=true NOTE: this option only works for the LSP whose peer is l3dgw_port. Signed-off-by: Xie Liu --- NEWS | 2 + northd/northd.c | 30 ++++++++++++++- ovn-nb.xml | 8 ++++ tests/ovn-northd.at | 92 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index acb3b854fb..54382eb291 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ Post v23.09.0 external_ids:ovn-openflow-probe-interval configuration option for ovn-controller no longer matters and is ignored. - Enable PMTU discovery on geneve tunnels for E/W traffic. + - A new LSP option "enable_conntrack" has been added to enable conntrack + for the router port whose peer is l3dgw_port if set it true. OVN v23.09.0 - 15 Sep 2023 -------------------------- diff --git a/northd/northd.c b/northd/northd.c index 07dffb15a7..7ce3525f6d 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -1605,6 +1605,9 @@ struct ovn_port { * access it from any other nodes. */ struct ovs_list lflows; + + /* Only used for the router type LSP whose peer is l3dgw_port */ + bool enable_conntrack; }; static bool lsp_can_be_inc_processed(const struct nbrec_logical_switch_port *); @@ -2657,6 +2660,13 @@ join_logical_ports(const struct sbrec_port_binding_table *sbrec_pb_table, od->has_vtep_lports = true; } + if (smap_get( ->options, "enable_conntrack") && + !lsp_is_router(nbsp)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "enable_conntrack option is not supported " + "on logical port %s", nbsp->name); + } + parse_lsp_addrs(op); op->od = od; @@ -2819,6 +2829,20 @@ join_logical_ports(const struct sbrec_port_binding_table *sbrec_pb_table, arp_proxy, op->nbsp->name); } } + + /* Only used for the router type LSP whose peer is l3dgw_port */ + if (smap_get(&op->nbsp->options, "enable_conntrack")) { + if (op->peer && is_l3dgw_port(op->peer)) { + op->enable_conntrack = smap_get_bool(&op->nbsp->options, + "enable_conntrack", false); + } else { + static struct vlog_rate_limit rl = + VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "enable_conntrack option is not " + "supported on logical port %s", + op->nbsp->name); + } + } } else if (op->nbrp && op->nbrp->peer && !op->l3dgw_port) { struct ovn_port *peer = ovn_port_find(ports, op->nbrp->peer); if (peer) { @@ -7202,7 +7226,11 @@ build_pre_acls(struct ovn_datapath *od, * which handles defragmentation, in order to match L4 headers. */ if (od->has_stateful_acl) { for (size_t i = 0; i < od->n_router_ports; i++) { - skip_port_from_conntrack(od, od->router_ports[i], + struct ovn_port *op = od->router_ports[i]; + if (op->enable_conntrack) { + continue; + } + skip_port_from_conntrack(od, op, S_SWITCH_IN_PRE_ACL, S_SWITCH_OUT_PRE_ACL, 110, lflows); } diff --git a/ovn-nb.xml b/ovn-nb.xml index fcb1c6ecc5..b74798e924 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -1107,6 +1107,14 @@ should have a route to forward packets sent to configured proxy ARP MAC/IPs to an appropriate destination. + + + Optional. Enable conntrack for the router port whose peer is + l3dgw_port if set to true. The default value is + false. + + diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 19e4f1263e..a686c3f727 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -10966,3 +10966,95 @@ Status: active AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD_NO_HV([ +AT_SETUP([Distributed gw port enable conntrack option]) +ovn_start + +check ovn-sbctl chassis-add gw1 geneve 127.0.0.1 + +# Add a distributed router +check ovn-nbctl lr-add R1 +check ovn-nbctl lrp-add R1 R1-S1 02:ac:10:01:00:01 172.16.1.1/24 +check ovn-nbctl lrp-set-gateway-chassis R1-S1 gw1 + +# Add a external network connected to R1 +check ovn-nbctl ls-add S1 +check ovn-nbctl lsp-add S1 S1-R1 +check ovn-nbctl lsp-set-type S1-R1 router +check ovn-nbctl lsp-set-addresses S1-R1 router +check ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1 +AT_CHECK([test x`ovn-nbctl lsp-get-up S1-R1` = xup]) + +# Add a external network vif +check ovn-nbctl lsp-add S1 S1-VIF +check ovn-nbctl lsp-set-addresses S1-VIF "02:ac:10:01:00:02 172.16.1.11" + +# Add the router gw port and vif to one port_group which has stateful acls +check ovn-nbctl --wait=sb pg-add pg_dgw S1-R1 S1-VIF +check ovn-nbctl acl-add pg_dgw from-lport 1002 "inport == @pg_dgw && ip4" allow-related +check ovn-nbctl acl-add pg_dgw to-lport 1003 "outport == @pg_dgw && ip4" allow-related + +# Check skip conntrack option with 'enable_conntrack' default (false) +AT_CHECK([ovn-sbctl dump-flows S1 | grep pre_acl | sed 's/table=./table=?/'], [0], [dnl + table=? (ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) + table=? (ls_in_pre_acl ), priority=110 , match=(eth.mcast), action=(next;) + table=? (ls_in_pre_acl ), priority=110 , match=(ip && inport == "S1-R1"), action=(next;) + table=? (ls_in_pre_acl ), priority=110 , match=(nd || nd_rs || nd_ra || mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;) + table=? (ls_in_pre_acl ), priority=100 , match=(ip), action=(reg0[[0]] = 1; next;) + table=? (ls_in_pre_acl ), priority=0 , match=(1), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(eth.mcast), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(ip && outport == "S1-R1"), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(nd || nd_rs || nd_ra || mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;) + table=? (ls_out_pre_acl ), priority=100 , match=(ip), action=(reg0[[0]] = 1; next;) + table=? (ls_out_pre_acl ), priority=0 , match=(1), action=(next;) +]) + +# Enable 'enable_conntrack' and check the flows +AT_CHECK([ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1 enable_conntrack=true]) +AT_CHECK([ovn-sbctl dump-flows S1 | grep pre_acl | sed 's/table=./table=?/'], [0], [dnl + table=? (ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) + table=? (ls_in_pre_acl ), priority=110 , match=(eth.mcast), action=(next;) + table=? (ls_in_pre_acl ), priority=110 , match=(nd || nd_rs || nd_ra || mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;) + table=? (ls_in_pre_acl ), priority=100 , match=(ip), action=(reg0[[0]] = 1; next;) + table=? (ls_in_pre_acl ), priority=0 , match=(1), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(eth.mcast), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(nd || nd_rs || nd_ra || mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;) + table=? (ls_out_pre_acl ), priority=100 , match=(ip), action=(reg0[[0]] = 1; next;) + table=? (ls_out_pre_acl ), priority=0 , match=(1), action=(next;) +]) + +# ICMP packets from router port to external network should go to conntrack +flow_eth_in='eth.src == 02:ac:10:01:00:01 && eth.dst == 02:ac:10:01:00:02' +flow_ip_in='ip.ttl==64 && ip4.src == 172.16.10.1 && ip4.dst == 172.16.10.11' +flow_icmp='icmp4.type == 8' +flow_in="inport == \"S1-R1\" && ${flow_eth_in} && ${flow_ip_in} && ${flow_icmp}" +AT_CHECK_UNQUOTED([ovn_trace --ct est --ct est --minimal S1 "${flow_in}"], [0], [dnl +ct_next(ct_state=est|trk) { + ct_next(ct_state=est|trk) { + output("S1-VIF"); + }; +}; +]) + +# Disable 'enable_conntrack' and check the flows +AT_CHECK([ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1 enable_conntrack=false]) +AT_CHECK([ovn-sbctl dump-flows S1 | grep pre_acl | sed 's/table=./table=?/'], [0], [dnl + table=? (ls_in_pre_acl ), priority=110 , match=(eth.dst == $svc_monitor_mac), action=(next;) + table=? (ls_in_pre_acl ), priority=110 , match=(eth.mcast), action=(next;) + table=? (ls_in_pre_acl ), priority=110 , match=(ip && inport == "S1-R1"), action=(next;) + table=? (ls_in_pre_acl ), priority=110 , match=(nd || nd_rs || nd_ra || mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;) + table=? (ls_in_pre_acl ), priority=100 , match=(ip), action=(reg0[[0]] = 1; next;) + table=? (ls_in_pre_acl ), priority=0 , match=(1), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(eth.mcast), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(eth.src == $svc_monitor_mac), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(ip && outport == "S1-R1"), action=(next;) + table=? (ls_out_pre_acl ), priority=110 , match=(nd || nd_rs || nd_ra || mldv1 || mldv2 || (udp && udp.src == 546 && udp.dst == 547)), action=(next;) + table=? (ls_out_pre_acl ), priority=100 , match=(ip), action=(reg0[[0]] = 1; next;) + table=? (ls_out_pre_acl ), priority=0 , match=(1), action=(next;) +]) + +AT_CLEANUP +])