From patchwork Tue Jan 9 18:54:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zoltan Balogh X-Patchwork-Id: 857673 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zGLtj6wt9z9sPk for ; Wed, 10 Jan 2018 05:55:25 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 3D1D9F73; Tue, 9 Jan 2018 18:54:48 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 32499EF8 for ; Tue, 9 Jan 2018 18:54:46 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from sessmg22.ericsson.net (sessmg22.ericsson.net [193.180.251.58]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 534C958A for ; Tue, 9 Jan 2018 18:54:44 +0000 (UTC) X-AuditID: c1b4fb3a-335ff700000037f2-43-5a550ff202ad Received: from ESESSHC017.ericsson.se (Unknown_Domain [153.88.183.69]) by sessmg22.ericsson.net (Symantec Mail Security) with SMTP id 1E.B8.14322.2FF055A5; Tue, 9 Jan 2018 19:54:42 +0100 (CET) Received: from labserv2.eth.ericsson.se (153.88.183.153) by smtp.internal.ericsson.com (153.88.183.71) with Microsoft SMTP Server id 14.3.352.0; Tue, 9 Jan 2018 19:54:42 +0100 Received: from dell11.sdn.hu.eld.ericsson.se (unknown [10.58.48.15]) by labserv2.eth.ericsson.se (Postfix) with ESMTP id 8E27F29C746; Tue, 9 Jan 2018 19:47:46 +0100 (CET) From: Zoltan Balogh To: , Date: Tue, 9 Jan 2018 19:54:33 +0100 Message-ID: <20180109185433.23945-4-zoltan.balogh@ericsson.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180109185433.23945-1-zoltan.balogh@ericsson.com> References: <20180109185433.23945-1-zoltan.balogh@ericsson.com> MIME-Version: 1.0 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprPLMWRmVeSWpSXmKPExsUyM2K7q+4n/tAogxuTlC2Ont7D7MDo8ezm f8YAxigum5TUnMyy1CJ9uwSujKdfNjEV3F3NWLGg27yB8Wc7YxcjJ4eEgInE1p+72UBsIYHD jBJ31wd1MXIB2ZsZJc5M+sYO4axnlLg6fypYB5uAgcSPy1+Yuhg5OEQEzCVW/bEFCTML6Ek8 OXqECcQWFgiReLboJTOIzSKgIvFz7iWwVl4Be4kvH3exQyyWl5iwpYkFxOYUcJDoW9HDCnGE vUTL8p9sEPWCEidnPmGBmC8hcfDFC2aIGnWJQy2v2SYwCsxCUjYLSdkCRqZVjKLFqcXFuelG RnqpRZnJxcX5eXp5qSWbGIHBdnDLb6sdjAefOx5iFOBgVOLhPQYMQiHWxLLiytxDjBIczEoi vL7zg6OEeFMSK6tSi/Lji0pzUosPMUpzsCiJ8zqlWUQJCaQnlqRmp6YWpBbBZJk4OKUaGFM+ bLiT0rCVoyRxWRnXtN1+LWqTbDpW9V14zvZHnlVzY2OB5PKmF5PuLOHfeXfGgzJGy/Rsl/iL hjVOH2M/spu5Bts4yix5eDddsYHxj6t2Ywbjrm4DcZEzYg5NUyODjwVoiLI6fVOsvnLuSTmX YrpnJW9XrnVsaf1ThayLkprmq2teLl6nxFKckWioxVxUnAgAFetGozICAAA= X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v3 3/3] xlate: call tnl_neigh_snoop() from terminate_native_tunnel() X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Currenlty, OVS snoops any ARP or ND packets in any bridge and populates the tunnel neighbor cache with the retreived data. For instance, when ARP reply originated by a tenant is received in an overlay bridge, the ARP message is snooped and tunnel neighbor cache is filled with tenant data, however only tunnel neighbor data should be stored there. This patch moves tunnel neighbor snooping from do_xlate_actions() to terminate_native_tunnel() where native tunnel is terminated, in order to keep ARP neighbor cache clean, i.e. only packets comming from a native tunnel are snooped. By applying the patch, only ARP and Neighbor Advertisement messages addressing a tunnel endpoint (LOCAL port of underlay bridge) are snooped. In order to achieve this, IP addresses of the bridge are retrieved and then stored in xbridge by calling xlate_xbridge_set(). These data is then matched against the data extracted from an ARP or Neighbor Advertisement message in is_neighbor_reply_correct() which is invoked from terminate_native_tunnel(). Signed-off-by: Zoltan Balogh --- include/sparse/netinet/in.h | 10 +++ ofproto/ofproto-dpif-xlate.c | 147 ++++++++++++++++++++++++++++++++++++++++-- tests/tunnel-push-pop-ipv6.at | 68 ++++++++++++++++++- tests/tunnel-push-pop.at | 67 ++++++++++++++++++- 4 files changed, 282 insertions(+), 10 deletions(-) diff --git a/include/sparse/netinet/in.h b/include/sparse/netinet/in.h index 6abdb2331..eea41bd7f 100644 --- a/include/sparse/netinet/in.h +++ b/include/sparse/netinet/in.h @@ -123,6 +123,16 @@ struct sockaddr_in6 { (X)->s6_addr[10] == 0xff && \ (X)->s6_addr[11] == 0xff) +#define IN6_IS_ADDR_MC_LINKLOCAL(a) \ + (((const uint8_t *) (a))[0] == 0xff && \ + (((const uint8_t *) (a))[1] & 0xf) == 0x2) + +# define IN6_ARE_ADDR_EQUAL(a,b) \ + ((((const uint32_t *) (a))[0] == ((const uint32_t *) (b))[0]) && \ + (((const uint32_t *) (a))[1] == ((const uint32_t *) (b))[1]) && \ + (((const uint32_t *) (a))[2] == ((const uint32_t *) (b))[2]) && \ + (((const uint32_t *) (a))[3] == ((const uint32_t *) (b))[3])) + #define INET_ADDRSTRLEN 16 #define INET6_ADDRSTRLEN 46 diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 2328ec1da..16bc0cd96 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -90,6 +90,16 @@ VLOG_DEFINE_THIS_MODULE(ofproto_dpif_xlate); * recursive or not. */ #define MAX_RESUBMITS (MAX_DEPTH * MAX_DEPTH) +/* The structure holds an array of IP addresses assigned to a bridge and the + * number of elements in the array. These data are mutable and are evaluated + * when ARP or Neighbor Advertisement packets received on a native tunnel + * port are xlated. So 'ref_cnt' and RCU are used for synchronization. */ +struct xbridge_addr { + struct in6_addr *addr; /* Array of IP addresses of xbridge. */ + int n_addr; /* Number of IP addresses. */ + struct ovs_refcount ref_cnt; +}; + struct xbridge { struct hmap_node hmap_node; /* Node in global 'xbridges' map. */ struct ofproto_dpif *ofproto; /* Key in global 'xbridges' map. */ @@ -113,6 +123,8 @@ struct xbridge { /* Datapath feature support. */ struct dpif_backer_support support; + + struct xbridge_addr *addr; }; struct xbundle { @@ -576,7 +588,8 @@ static void xlate_xbridge_set(struct xbridge *, struct dpif *, const struct dpif_ipfix *, const struct netflow *, bool forward_bpdu, bool has_in_band, - const struct dpif_backer_support *); + const struct dpif_backer_support *, + const struct xbridge_addr *); static void xlate_xbundle_set(struct xbundle *xbundle, enum port_vlan_mode vlan_mode, uint16_t qinq_ethtype, int vlan, @@ -826,6 +839,56 @@ xlate_xport_init(struct xlate_cfg *xcfg, struct xport *xport) hash_ofp_port(xport->ofp_port)); } +static struct xbridge_addr * +xbridge_addr_create(struct xbridge *xbridge) +{ + struct xbridge_addr *xbridge_addr = xbridge->addr; + struct in6_addr *addr = NULL, *mask = NULL; + struct netdev *dev; + int err, n_addr = 0; + + err = netdev_open(xbridge->name, NULL, &dev); + if (!err) { + err = netdev_get_addr_list(dev, &addr, &mask, &n_addr); + if (!err) { + if (!xbridge->addr || + n_addr != xbridge->addr->n_addr || + (xbridge->addr->addr && memcmp(addr, xbridge->addr->addr, + sizeof(*addr) * n_addr))) { + xbridge_addr = xzalloc(sizeof *xbridge_addr); + xbridge_addr->addr = addr; + xbridge_addr->n_addr = n_addr; + ovs_refcount_init(&xbridge_addr->ref_cnt); + } else { + free(addr); + } + free(mask); + } + netdev_close(dev); + } + + return xbridge_addr; +} + +static struct xbridge_addr * +xbridge_addr_ref(const struct xbridge_addr *addr_) +{ + struct xbridge_addr *addr = CONST_CAST(struct xbridge_addr *, addr_); + if (addr) { + ovs_refcount_ref(&addr->ref_cnt); + } + return addr; +} + +static void +xbridge_addr_unref(struct xbridge_addr *addr) +{ + if (addr && ovs_refcount_unref_relaxed(&addr->ref_cnt) == 1) { + free(addr->addr); + free(addr); + } +} + static void xlate_xbridge_set(struct xbridge *xbridge, struct dpif *dpif, @@ -836,7 +899,8 @@ xlate_xbridge_set(struct xbridge *xbridge, const struct dpif_ipfix *ipfix, const struct netflow *netflow, bool forward_bpdu, bool has_in_band, - const struct dpif_backer_support *support) + const struct dpif_backer_support *support, + const struct xbridge_addr *addr) { if (xbridge->ml != ml) { mac_learning_unref(xbridge->ml); @@ -878,6 +942,11 @@ xlate_xbridge_set(struct xbridge *xbridge, xbridge->netflow = netflow_ref(netflow); } + if (xbridge->addr != addr) { + xbridge_addr_unref(xbridge->addr); + xbridge->addr = xbridge_addr_ref(addr); + } + xbridge->dpif = dpif; xbridge->forward_bpdu = forward_bpdu; xbridge->has_in_band = has_in_band; @@ -971,7 +1040,7 @@ xlate_xbridge_copy(struct xbridge *xbridge) xbridge->rstp, xbridge->ms, xbridge->mbridge, xbridge->sflow, xbridge->ipfix, xbridge->netflow, xbridge->forward_bpdu, xbridge->has_in_band, - &xbridge->support); + &xbridge->support, xbridge->addr); LIST_FOR_EACH (xbundle, list_node, &xbridge->xbundles) { xlate_xbundle_copy(new_xbridge, xbundle); } @@ -1126,6 +1195,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, const struct dpif_backer_support *support) { struct xbridge *xbridge; + struct xbridge_addr *xbridge_addr, *old_addr; ovs_assert(new_xcfg); @@ -1140,8 +1210,16 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, free(xbridge->name); xbridge->name = xstrdup(name); + xbridge_addr = xbridge_addr_create(xbridge); + old_addr = xbridge->addr; + xlate_xbridge_set(xbridge, dpif, ml, stp, rstp, ms, mbridge, sflow, ipfix, - netflow, forward_bpdu, has_in_band, support); + netflow, forward_bpdu, has_in_band, support, + xbridge_addr); + + if (xbridge_addr != old_addr) { + xbridge_addr_unref(xbridge_addr); + } } static void @@ -1171,6 +1249,7 @@ xlate_xbridge_remove(struct xlate_cfg *xcfg, struct xbridge *xbridge) netflow_unref(xbridge->netflow); stp_unref(xbridge->stp); rstp_unref(xbridge->rstp); + xbridge_addr_unref(xbridge->addr); hmap_destroy(&xbridge->xports); free(xbridge->name); free(xbridge); @@ -3655,6 +3734,54 @@ check_output_prerequisites(struct xlate_ctx *ctx, return true; } +/* Function verifies if destination address of received Neighbor Advertisement + * message stored in 'flow' is correct. It should be either FF02::1:FFXX:XXXX + * where XX:XXXX stands for the last 24 bits of 'ipv6_addr' or it should match + * 'ipv6_addr'. */ +static bool +is_nd_dst_correct(const struct flow *flow, const struct in6_addr *ipv6_addr) +{ + const uint8_t *flow_ipv6_addr = (uint8_t *) &flow->ipv6_dst; + const uint8_t *addr = (uint8_t *) ipv6_addr; + + return (IN6_IS_ADDR_MC_LINKLOCAL(flow_ipv6_addr) && + flow_ipv6_addr[11] == 0x01 && + flow_ipv6_addr[12] == 0xff && + flow_ipv6_addr[13] == addr[13] && + flow_ipv6_addr[14] == addr[14] && + flow_ipv6_addr[15] == addr[15]) || + IN6_ARE_ADDR_EQUAL(&flow->ipv6_dst, ipv6_addr); +} + +/* Function verifies if the ARP reply or Neighbor Advertisement represented by + * 'flow' addresses the 'xbridge' of 'ctx'. Returns true if the ARP TA or + * neighbor discovery destination is in the list of configured IP addresses of + * the bridge. Otherwise, it returns false. */ +static bool +is_neighbor_reply_correct(const struct xlate_ctx *ctx, const struct flow *flow) +{ + bool ret = false; + int i; + struct xbridge_addr *xbridge_addr = xbridge_addr_ref(ctx->xbridge->addr); + + /* Verify if 'nw_dst' of ARP or 'ipv6_dst' of ICMPV6 is in the list. */ + for (i = 0; xbridge_addr && i < xbridge_addr->n_addr; i++) { + struct in6_addr *ip_addr = &xbridge_addr->addr[i]; + if ((IN6_IS_ADDR_V4MAPPED(ip_addr) && + flow->dl_type == htons(ETH_TYPE_ARP) && + in6_addr_get_mapped_ipv4(ip_addr) == flow->nw_dst) || + (!IN6_IS_ADDR_V4MAPPED(ip_addr) && + is_nd_dst_correct(flow, ip_addr))) { + /* Found a match. */ + ret = true; + break; + } + } + + xbridge_addr_unref(xbridge_addr); + return ret; +} + static bool terminate_native_tunnel(struct xlate_ctx *ctx, ofp_port_t ofp_port, struct flow *flow, struct flow_wildcards *wc, @@ -3667,6 +3794,15 @@ terminate_native_tunnel(struct xlate_ctx *ctx, ofp_port_t ofp_port, if (ofp_port == OFPP_LOCAL && ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) { *tnl_port = tnl_port_map_lookup(flow, wc); + + /* If no tunnel port was found and it's about an ARP or ICMPv6 packet, + * do tunnel neighbor snooping. */ + if (*tnl_port == ODPP_NONE && + (flow->dl_type == htons(ETH_TYPE_ARP) || + flow->nw_proto == IPPROTO_ICMPV6) && + is_neighbor_reply_correct(ctx, flow)) { + tnl_neigh_snoop(flow, wc, ctx->xbridge->name); + } } return *tnl_port != ODPP_NONE; @@ -6183,9 +6319,6 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, struct flow *flow = &ctx->xin->flow; const struct ofpact *a; - if (ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) { - tnl_neigh_snoop(flow, wc, ctx->xbridge->name); - } /* dl_type already in the mask, not set below. */ if (!ofpacts_len) { diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at index 0b9d436db..b0f4a7e91 100644 --- a/tests/tunnel-push-pop-ipv6.at +++ b/tests/tunnel-push-pop-ipv6.at @@ -55,9 +55,73 @@ AT_CHECK([cat p0.pcap.txt | grep 93aa55aa55000086dd6000000000203aff2001cafe | un ]) dnl Check ARP Snoop -AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::94,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)']) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:c8,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:c8)']) -AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b7,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::93,dst=2001:cafe::94,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::93,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b7)']) +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl +2001:cafe::92 f8:bc:12:44:34:c8 br0 +]) + +dnl Receiving Neighbor Advertisement with incorrect 'nw_dst' should not alter tunnel neighbor cache +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::99,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl +2001:cafe::92 f8:bc:12:44:34:c8 br0 +]) + +dnl Receiving Neighbot Advertisement with incorrect VLAN id should not alter tunnel neighbor cache +AT_CHECK([ovs-vsctl set port br0 tag=10]) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x8100),vlan(vid=99,pcp=7),encap(eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6))']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl +2001:cafe::92 f8:bc:12:44:34:c8 br0 +]) + +dnl Receiving Neighbor Advertisement with correct VLAN id should alter tunnel neighbor cache +AT_CHECK([ovs-vsctl set port br0 tag=10]) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x8100),vlan(vid=10,pcp=7),encap(eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6))']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl +2001:cafe::92 f8:bc:12:44:34:b6 br0 +]) + +dnl Receiving Neighbor Advertisement in overlay bridge should not alter tunnel neighbor cache +AT_CHECK([ovs-vsctl add-port int-br p1 -- set interface p1 type=dummy ofport_request=200 other-config:hwaddr=aa:55:aa:55:00:99]) +AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(200),eth(src=f8:bc:12:44:34:c8,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::99,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:c8)']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/neigh/show | grep br | sort], [0], [dnl +2001:cafe::92 f8:bc:12:44:34:b6 br0 +]) + +dnl Receive Neighbor Advertisement without VLAN header +AT_CHECK([ovs-vsctl set port br0 tag=0]) +AT_CHECK([ovs-appctl tnl/neigh/flush], [0], [OK +]) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + + +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)']) + +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b7,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::93,dst=ff02::1:ff00:0088,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::93,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b7)']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl 2001:cafe::92 f8:bc:12:44:34:b6 br0 diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index b168f5f2f..4e259730c 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -70,9 +70,71 @@ ffffffffffffaa55aa55000008060001080006040001aa55aa550000010102580000000000000101 ]) dnl Check ARP Snoop +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:c8,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:c8,tha=00:00:00:00:00:00)']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/neigh/show | grep br0 | sort], [0], [dnl +1.1.2.92 f8:bc:12:44:34:c8 br0 +]) + +dnl Receiving ARP reply with incorrect 'tip' should not alter tunnel neighbor cache +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b8,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.90,op=2,sha=f8:bc:12:44:34:b8,tha=00:00:00:00:00:00)']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/neigh/show | grep br0 | sort], [0], [dnl +1.1.2.92 f8:bc:12:44:34:c8 br0 +]) + +dnl Receiving ARP reply with incorrect VLAN id should not alter tunnel neighbor cache +AT_CHECK([ovs-vsctl set port br0 tag=10]) +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x8100),vlan(vid=99,pcp=7),encap(eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00))']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/neigh/show | grep br0 | sort], [0], [dnl +1.1.2.92 f8:bc:12:44:34:c8 br0 +]) + +dnl Receiving ARP reply with correct VLAN id should alter tunnel neighbor cache +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x8100),vlan(vid=10,pcp=7),encap(eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00))']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/neigh/show | grep br0 | sort], [0], [dnl +1.1.2.92 f8:bc:12:44:34:b6 br0 +]) + +dnl Receiving ARP reply in overlay bridge should not alter tunnel neighbor cache +AT_CHECK([ovs-vsctl add-port int-br p1 -- set interface p1 type=dummy ofport_request=200 other-config:hwaddr=aa:55:aa:55:00:99]) +AT_CHECK([ovs-appctl netdev-dummy/receive p1 'recirc_id(0),in_port(200),eth(src=f8:bc:12:44:34:c8,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:c8,tha=00:00:00:00:00:00)']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/neigh/show | grep br | sort], [0], [dnl +1.1.2.92 f8:bc:12:44:34:b6 br0 +]) + +dnl Receive ARP reply without VLAN header +AT_CHECK([ovs-vsctl set port br0 tag=0]) +AT_CHECK([ovs-appctl tnl/neigh/flush], [0], [OK +]) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)']) AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b7,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.93,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b7,tha=00:00:00:00:00:00)']) +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl 1.1.2.92 f8:bc:12:44:34:b6 br0 1.1.2.93 f8:bc:12:44:34:b7 br0 @@ -190,9 +252,12 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 7'], [0], [dnl dnl Check GREL3 only accepts non-fragmented packets? AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004500007e79464000402fba550101025c0101025820000800000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637']) +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port [[37]]' | sort], [0], [dnl port 3: rx pkts=3, bytes=294, drop=?, errs=?, frame=?, over=?, crc=? - port 7: rx pkts=3, bytes=252, drop=?, errs=?, frame=?, over=?, crc=? + port 7: rx pkts=4, bytes=350, drop=?, errs=?, frame=?, over=?, crc=? ]) dnl Check decapsulation of Geneve packet with options