Skip to content

Commit

Permalink
northd: Add option to enable conntrack for router port
Browse files Browse the repository at this point in the history
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_router_port_acl',
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_router_port_acl=true

NOTE: this option only works for the LSP whose peer is l3dgw_port.

Submitted-at: #226
Signed-off-by: Xie Liu <liushyshy@gmail.com>
Acked-by: Dumitru Ceara <dceara@redhat.com>
Signed-off-by: Numan Siddique <numans@ovn.org>
  • Loading branch information
shylou authored and numansiddique committed Jan 10, 2024
1 parent 16d35a3 commit 9a0f307
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 2 deletions.
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Post v23.09.0
- Support CIDR based MAC binding aging threshold. See ovn-nb(5) for
'mac_binding_age_threshold' for more details.
- ovn-northd-ddlog has been removed.
- A new LSP option "enable_router_port_acl" 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
--------------------------
Expand Down
15 changes: 14 additions & 1 deletion northd/northd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,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_router_port_acl;
};

static bool lsp_can_be_inc_processed(const struct nbrec_logical_switch_port *);
Expand Down Expand Up @@ -2826,6 +2829,12 @@ 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 (op->peer && is_l3dgw_port(op->peer)) {
op->enable_router_port_acl = smap_get_bool(
&op->nbsp->options, "enable_router_port_acl", false);
}
} else if (op->nbrp && op->nbrp->peer && !op->l3dgw_port) {
struct ovn_port *peer = ovn_port_find(ports, op->nbrp->peer);
if (peer) {
Expand Down Expand Up @@ -7207,7 +7216,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_router_port_acl) {
continue;
}
skip_port_from_conntrack(od, op,
S_SWITCH_IN_PRE_ACL, S_SWITCH_OUT_PRE_ACL,
110, lflows);
}
Expand Down
7 changes: 6 additions & 1 deletion northd/ovn-northd.8.xml
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,12 @@
<code>Pre-stateful</code> to send IP packets to the connection tracker
before eventually advancing to ingress table <code>ACLs</code>. If
special ports such as route ports or localnet ports can't use ct(), a
priority-110 flow is added to skip over stateful ACLs. Multicast, IPv6
priority-110 flow is added to skip over stateful ACLs. This
priority-110 flow is not addd for router ports if the option
enable_router_port_acl is set to true in
<ref column="options:enable_router_port_acl"
table="Logical_Switch_Port" db="OVN_Northbound"/> column of
<ref table="Logical_Switch_Port" db="OVN_Northbound"/>. Multicast, IPv6
Neighbor Discovery and MLD traffic also skips stateful ACLs. For
"allow-stateless" ACLs, a flow is added to bypass setting the hint for
connection tracker processing when there are stateful ACLs or LB rules;
Expand Down
8 changes: 8 additions & 0 deletions ovn-nb.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,14 @@
should have a route to forward packets sent to configured proxy ARP
MAC/IPs to an appropriate destination.
</column>

<column name="options" key="enable_router_port_acl"
type='{"type": "boolean"}'>
Optional. Enable conntrack for the router port whose peer is
l3dgw_port if set to <code>true</code>. The default value is
<code>false</code>.
</column>

</group>

<group title="Options for localnet ports">
Expand Down
124 changes: 124 additions & 0 deletions tests/ovn-northd.at
Original file line number Diff line number Diff line change
Expand Up @@ -10970,5 +10970,129 @@ AT_CHECK([as northd ovn-appctl -t ovn-northd status], [0], [dnl
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_router_port_acl' 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_router_port_acl' and check the flows
check ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1 enable_router_port_acl=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_router_port_acl' and check the flows
check ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1 enable_router_port_acl=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;)
])

# Clear the option 'enable_router_port_acl' and check the flows. Before that enable the option.
check ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1 enable_router_port_acl=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;)
])

check ovn-nbctl --wait=sb lsp-set-options S1-R1 router-port=R1-S1
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
])

0 comments on commit 9a0f307

Please sign in to comment.