[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