[ovs-dev] [PATCH ovn] Suppress periodic RAs for switches attached to localnet

Ihar Hrachyshka ihrachys at redhat.com
Tue Aug 24 23:23:26 UTC 2021


On Tue, Aug 17, 2021 at 2:20 PM Numan Siddique <numans at ovn.org> wrote:
>
> On Fri, Aug 13, 2021 at 10:33 AM Frode Nordahl
> <frode.nordahl at canonical.com> wrote:
> >
> > On Sat, Aug 7, 2021 at 12:20 AM 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.
> >
> > Do I understand you correctly that you want to suppress RA's on an
> > entire LS if it has one localnet port? If so, I'm a bit concerned
> > about this approach as it is a perfectly valid configuration to attach
> > an instance directly to a LS with a localnet port.
> >
> > In such a scenario the instance would no longer receive periodic RAs.
> > While the instance would still be able to solicit its IPv6 prefix,
> > router and DNS servers on startup, it would not receive any
> > information should the router address, prefix or DNS server
> > information change somewhere down the line.
> >
> > Could we filter this in some other way that does not affect the entire
> > switch? Or could it be managing and suppressing the RAs is the
> > responsibility of the physical DC switch/router administrator?
>
>
> Agree with Frode.  VIFs associated with logical switches with localnet port
> should be served periodic RAs if configured.
>
> I think the right fix would be to make sure that ovn-controller doesn't inject
> the periodic RAs to the patch ports connecting to the provider bridges.
>
> If I recall, ovn-controller would inject the periodic RAs only to the local VIFs
> which need the periodic RAs.  So ideally it should not leak out of the br-int.
>

You are right we shouldn't suppress other RAs. I am sending a new
patch in a sec.

To the point of the mechanism to suppress RAs on localnets, AFAIU the
packet is injected into LS peer port that is plugged into router. From
the controller() action perspective, we don't know where RA will
propagate.

There are two options here:
a) block specifically RAs using corresponding drop rule (dst=ff02:1,
icmp6, code=134...)
b) block all LOCAL_ONLY marked traffic on leaving through localnet port

The latter will also block prefix delegation and BFD messages, which I
believe we should block any way.

I will send (b) in a second but let me know if a more fine grained (a)
option is preferable (perhaps we should have both?)

Cheers,
Ihar


> Thanks
> Numan
>
>
> >
> > --
> > Frode Nordahl
> >
> > > Signed-off-by: Ihar Hrachyshka <ihrachys at redhat.com>
> > > ---
> > >  northd/ovn-northd.c |   5 +-
> > >  tests/ovn.at        | 156 ++++++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 160 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> > > index a0eaa1247..6cd686d12 100644
> > > --- a/northd/ovn-northd.c
> > > +++ b/northd/ovn-northd.c
> > > @@ -10207,7 +10207,10 @@ build_ND_RA_flows_for_lrouter_port(
> > >
> > >      if (smap_get_bool(&op->nbrp->ipv6_ra_configs, "send_periodic",
> > >                        false)) {
> > > -        copy_ra_to_sb(op, address_mode);
> > > +        /* Don't leak RAs into datacenter networks. */
> > > +        if (!op->peer->od->n_localnet_ports) {
> > > +            copy_ra_to_sb(op, address_mode);
> > > +        }
> > >      }
> > >
> > >      ds_clear(match);
> > > diff --git a/tests/ovn.at b/tests/ovn.at
> > > index 7ae136ad9..22c5ed07c 100644
> > > --- a/tests/ovn.at
> > > +++ b/tests/ovn.at
> > > @@ -13674,6 +13674,162 @@ 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=4
> > > +check ovn-nbctl set Logical_Router_Port ro-sw ipv6_ra_configs:min_interval=3
> > > +
> > > +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_test() {
> > > +    if [[ $1 = 1 ]]; then
> > > +        shift; construct_expected_ra $@
> > > +    else
> > > +        shift; > expected
> > > +    fi
> > > +
> > > +    for i in hv1 hv2 ; do
> > > +        as $i reset_pcap_file $i-vif1 $i/vif1
> > > +
> > > +        OVS_WAIT_WHILE([test 24 = $(wc -c $i/vif1-tx.pcap | cut -d " " -f1)])
> > > +
> > > +        $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([cat packets | cut -c -112], [0], [expout])
> > > +
> > > +        # Skip ICMPv6 checksum.
> > > +        cat expected | cut -c 117- > expout
> > > +        AT_CHECK([cat packets | cut -c 117-], [0], [expout])
> > > +
> > > +        rm -f packets
> > > +        as $i reset_pcap_file $i-vif1 $i/vif1
> > > +    done
> > > +
> > > +    rm -f expected
> > > +}
> > > +
> > > +# first check that localnet port blocks RAs
> > > +ra_test 0 0 00 0 0 0 c0 40 aef00000000000000000000000000000
> > > +
> > > +# now remove localnet port and check periodic RAs
> > > +check ovn-nbctl lsp-del ln
> > > +check ovn-nbctl --wait=hv sync
> > > +ra_test 1 0 00 0 0 0 c0 40 aef00000000000000000000000000000
> > > +
> > > +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
> > _______________________________________________
> > dev mailing list
> > dev at openvswitch.org
> > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> >
>



More information about the dev mailing list