[ovs-dev] [PATCH v2 ovn] Suppress LOCAL_ONLY traffic for localnet ports
Numan Siddique
numans at ovn.org
Tue Aug 31 15:35:07 UTC 2021
On Tue, Aug 24, 2021 at 7:27 PM Ihar Hrachyshka <ihrachys at redhat.com> wrote:
>
> When a router port is attached to a localnet switch, sending periodic
> RAs through localnet port will confuse upstream router by leaking
> conflicting router advertisements into datacenter network.
>
> This patch blocks all LOCAL_ONLY marked traffic leaving through localnet
> port. In addition to RAs, it also covers BFD periodic messages and IPv6
> prefix delegation.
>
> Signed-off-by: Ihar Hrachyshka <ihrachys at redhat.com>
Thanks. I applied your patch to the main branch.
Looks like ovn-architecture document is out of sync with actual table
numbers. I went ahead and
applied the patch since it should be a separate patch to correct those.
Numan
> ---
> v1: initial version
> v2: adjusted new flow priority (153 -> 150)
> v2: updated ovn-architecture.5
> ---
> controller/physical.c | 11 +++
> ovn-architecture.7.xml | 3 +-
> tests/ovn.at | 160 +++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 173 insertions(+), 1 deletion(-)
>
> diff --git a/controller/physical.c b/controller/physical.c
> index 2b8189246..6f2c1cea0 100644
> --- a/controller/physical.c
> +++ b/controller/physical.c
> @@ -1252,6 +1252,17 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_port_binding_by_name,
> binding->header_.uuid.parts[0], &match,
> ofpacts_p, &binding->header_.uuid);
>
> + /* Drop LOCAL_ONLY traffic leaking through localnet ports. */
> + match_init_catchall(&match);
> + ofpbuf_clear(ofpacts_p);
> + match_set_metadata(&match, htonll(dp_key));
> + match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key);
> + match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0,
> + MLF_LOCAL_ONLY, MLF_LOCAL_ONLY);
> + ofctrl_add_flow(flow_table, OFTABLE_CHECK_LOOPBACK, 160,
> + binding->header_.uuid.parts[0], &match,
> + ofpacts_p, &binding->header_.uuid);
> +
> /* localport traffic directed to external is *not* local */
> struct shash_node *node;
> SHASH_FOR_EACH (node, &ld->external_ports) {
> diff --git a/ovn-architecture.7.xml b/ovn-architecture.7.xml
> index 2d2d74b06..3d2910358 100644
> --- a/ovn-architecture.7.xml
> +++ b/ovn-architecture.7.xml
> @@ -1519,7 +1519,8 @@
> <p>
> Table 34 matches and drops packets for which the logical input and
> output ports are the same and the MLF_ALLOW_LOOPBACK flag is not
> - set. It resubmits other packets to table 40.
> + set. It also drops MLF_LOCAL_ONLY packets directed to a localnet port.
> + It resubmits other packets to table 40.
> </p>
> </li>
>
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 9329dd828..6c5e1dfff 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -13675,6 +13675,166 @@ OVN_CLEANUP([hv1],[hv2])
> AT_CLEANUP
> ])
>
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([IPv6 periodic RA disabled for localnet adjacent switch ports])
> +ovn_start
> +
> +net_add n1
> +sim_add hv1
> +sim_add hv2
> +as hv1
> +check ovs-vsctl add-br br-phys
> +check ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> +ovn_attach n1 br-phys 192.168.0.2
> +as hv2
> +check ovs-vsctl add-br br-phys
> +check ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
> +ovn_attach n1 br-phys 192.168.0.3
> +
> +check ovn-nbctl lr-add ro
> +check ovn-nbctl lrp-add ro ro-sw 00:00:00:00:00:01 aef0:0:0:0:0:0:0:1/64
> +
> +check ovn-nbctl ls-add sw
> +check ovn-nbctl lsp-add sw ln
> +check ovn-nbctl lsp-set-addresses ln unknown
> +check ovn-nbctl lsp-set-type ln localnet
> +check ovn-nbctl lsp-set-options ln network_name=phys
> +
> +check ovn-nbctl lsp-add sw sw-ro
> +check ovn-nbctl lsp-set-type sw-ro router
> +check ovn-nbctl lsp-set-options sw-ro router-port=ro-sw
> +check ovn-nbctl lsp-set-addresses sw-ro 00:00:00:00:00:01
> +check ovn-nbctl lsp-add sw sw-p1
> +check ovn-nbctl lsp-set-addresses sw-p1 "00:00:00:00:00:02 aef0::200:ff:fe00:2"
> +check ovn-nbctl lsp-add sw sw-p2
> +check ovn-nbctl lsp-set-addresses sw-p2 "00:00:00:00:00:03 aef0::200:ff:fe00:3"
> +
> +check ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:send_periodic=true
> +check ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:address_mode=slaac
> +check ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:max_interval=1
> +check ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:min_interval=1
> +
> +for i in 1 2 ; do
> + as hv$i
> + check ovs-vsctl -- add-port br-int hv$i-vif1 -- \
> + set interface hv$i-vif1 external-ids:iface-id=sw-p$i \
> + options:tx_pcap=hv$i/vif1-tx.pcap \
> + options:rxq_pcap=hv$i/vif1-rx.pcap \
> + ofport-request=1
> +done
> +
> +OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p1` = xup])
> +OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up sw-p2` = xup])
> +
> +reset_pcap_file() {
> + local iface=$1
> + local pcap_file=$2
> + ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \
> +options:rxq_pcap=dummy-rx.pcap
> + rm -f ${pcap_file}*.pcap
> + ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \
> +options:rxq_pcap=${pcap_file}-rx.pcap
> +
> +}
> +
> +construct_expected_ra() {
> + local src_mac=000000000001
> + local dst_mac=333300000001
> + local src_addr=fe80000000000000020000fffe000001
> + local dst_addr=ff020000000000000000000000000001
> +
> + local mtu=$1
> + local ra_mo=$2
> + local rdnss=$3
> + local dnssl=$4
> + local route_info=$5
> + local ra_prefix_la=$6
> +
> + local slla=0101${src_mac}
> + local mtu_opt=""
> + if test $mtu != 0; then
> + mtu_opt=05010000${mtu}
> + fi
> + shift 6
> +
> + local prefix=""
> + while [[ $# -gt 0 ]] ; do
> + local size=$1
> + local net=$2
> + prefix=${prefix}0304${size}${ra_prefix_la}ffffffffffffffff00000000${net}
> + shift 2
> + done
> +
> + local rdnss_opt=""
> + if test $rdnss != 0; then
> + rdnss_opt=19030000ffffffff${rdnss}
> + fi
> + local dnssl_opt=""
> + if test $dnssl != 0; then
> + dnssl_opt=1f030000ffffffff${dnssl}
> + fi
> + local route_info_opt=""
> + if test $route_info != 0; then
> + route_info_opt=${route_info}
> + fi
> +
> + local ra=ff${ra_mo}ffff0000000000000000${slla}${mtu_opt}${prefix}${rdnss_opt}${dnssl_opt}${route_info_opt}
> + local icmp=8600XXXX${ra}
> +
> + local ip_len=$(expr ${#icmp} / 2)
> + ip_len=$(echo "$ip_len" | awk '{printf "%0.4x\n", $0}')
> +
> + local ip=60000000${ip_len}3aff${src_addr}${dst_addr}${icmp}
> + local eth=${dst_mac}${src_mac}86dd${ip}
> + local packet=${eth}
> + echo $packet >> expected
> +}
> +
> +ra_received() {
> + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $1 | sed '/^ffffffffffff/d' | wc -l
> +}
> +
> +ra_test() {
> + construct_expected_ra $@
> +
> + for i in hv1 hv2 ; do
> + as $i reset_pcap_file $i-vif1 $i/vif1
> +
> + OVS_WAIT_WHILE([test 0 = $(ra_received $i/vif1-tx.pcap)])
> +
> + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $i/vif1-tx.pcap > packets
> + sed -i '/^ffffffffffff/d' packets
> +
> + cat expected | cut -c -112 > expout
> + AT_CHECK([head -1 packets | cut -c -112], [0], [expout])
> +
> + # Skip ICMPv6 checksum.
> + cat expected | cut -c 117- > expout
> + AT_CHECK([head -1 packets | cut -c 117-], [0], [expout])
> +
> + rm -f packets
> + as $i reset_pcap_file $i-vif1 $i/vif1
> + done
> +
> + rm -f expected
> +}
> +
> +# check that RAs are sent to vifs
> +ra_test 0 00 0 0 0 c0 40 aef00000000000000000000000000000
> +
> +# check that RAs don't leak into provider networks
> +for i in hv1 hv2 ; do
> + $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $i/br-phys-tx.pcap > packets
> + sed -i '/^ffffffffffff/d' packets
> +
> + > expout
> + AT_CHECK([head -1 packets], [0], [expout])
> +done
> +
> +OVN_CLEANUP([hv1],[hv2])
> +AT_CLEANUP
> +])
> +
> OVN_FOR_EACH_NORTHD([
> AT_SETUP([ACL reject rule test])
> AT_KEYWORDS([acl-reject])
> --
> 2.31.1
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
More information about the dev
mailing list