For example, consider the following OpenFlow rule: - IPv6 -> IPv4 tunnel translation: add-flow br-int 'in_port=vxlan_br-int_0, \ actions=set_field:8.8.8.7->tun_src, \ set_field:8.8.8.8->tun_dst,set_field:43->tun_id,geneve_br-int_1'
As any set_field action, flow wildcards are set to the tun_src/dst. The offload layer fails if not all matches are handled ("consumed"). Clear the irrelevant wildcards. Signed-off-by: Reuven Plevinsky <rplevin...@nvidia.com> --- ofproto/ofproto-dpif-xlate.c | 17 +++++++++++++ tests/tunnel-push-pop.at | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 2c8197fb7307..e2ba7e6b0250 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -8078,6 +8078,20 @@ xlate_wc_init(struct xlate_ctx *ctx) tnl_wc_init(&ctx->xin->flow, ctx->wc); } +static void +clear_tunnel_wc(const struct flow_tnl *spec, struct flow_tnl *mask) +{ + if (!spec->ip_src && !spec->ip_dst) { + mask->ip_src = 0; + mask->ip_dst = 0; + } + if (!ipv6_addr_is_set(&spec->ipv6_src) && + !ipv6_addr_is_set(&spec->ipv6_dst)) { + mask->ipv6_src = in6addr_any; + mask->ipv6_dst = in6addr_any; + } +} + static void xlate_wc_finish(struct xlate_ctx *ctx) { @@ -8152,6 +8166,9 @@ xlate_wc_finish(struct xlate_ctx *ctx) if (!flow_tnl_dst_is_set(&ctx->xin->upcall_flow->tunnel)) { memset(&ctx->wc->masks.tunnel, 0, sizeof ctx->wc->masks.tunnel); } + /* Both IPv4/IPv6 tunnel wc may be set because of set_fields action. + * Clear the irrelevant one. */ + clear_tunnel_wc(&ctx->xin->upcall_flow->tunnel, &ctx->wc->masks.tunnel); } /* This will tweak the odp actions generated. For now, it will: diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index 64c41460bbb2..9b46d249fe9f 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -1440,3 +1440,51 @@ AT_CHECK([tail -1 stdout], [0], OVS_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([tunnel - decap and re-encap with outer IP version conversion]) +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy]) +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0]) +AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=vxlan \ + options:key=flow options:remote_ip=flow \ + -- add-port int-br t2 -- set Interface t2 type=geneve \ + options:key=flow options:remote_ip=flow \ + ], [0]) + +AT_CHECK([ovs-ofctl add-flow br0 action=normal]) +dnl Setup dummy interface IP addresses. +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.1.1/24], [0], [OK +]) +AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::1/24], [0], [OK +]) +dnl Checking that a local routes for added IPs were successfully installed. +AT_CHECK([ovs-appctl ovs/route/show | grep Cached | sort], [0], [dnl +Cached: 1.1.1.0/24 dev br0 SRC 1.1.1.1 local +Cached: 2001:ca00::/24 dev br0 SRC 2001:cafe::1 local +]) +dnl Add entries +AT_CHECK([ovs-appctl tnl/neigh/set br0 1.1.1.2 aa:bb:cc:00:00:01], [0], [OK +]) +AT_CHECK([ovs-appctl tnl/neigh/set br0 2001:cafe::2 aa:bb:cc:00:00:01], [0], [OK +]) +AT_CHECK([ovs-appctl tnl/neigh/show | grep br0 | sort], [0], [dnl +1.1.1.2 aa:bb:cc:00:00:01 br0 +2001:cafe::2 aa:bb:cc:00:00:01 br0 +]) + +AT_CHECK([ovs-ofctl add-flow int-br 'in_port=t1,tun_ipv6_src=2001:cafe::1,tun_ipv6_dst=2001:cafe::2,tun_id=0x7a,actions=set_field:1.1.1.1->tun_src,set_field:1.1.1.2->tun_dst,set_field:0x7b->tun_id,t2']) +AT_CHECK([ovs-ofctl add-flow int-br 'in_port=t2,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_id=0x7b,actions=set_field:2001:cafe::1->tun_ipv6_src,set_field:2001:cafe::2->tun_ipv6_dst,set_field:0x7a->tun_id,set_field:0.0.0.0->tun_src,set_field:0.0.0.0->tun_dst,t1']) + +AT_CHECK([ovs-appctl ofproto/trace --names ovs-dummy 'tunnel(tun_id=0x7a,ipv6_src=2001:cafe::1,ipv6_dst=2001:cafe::2,ttl=64),in_port(4789)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,tun_id=0x7a,tun_ipv6_src=2001:cafe::1,tun_ipv6_dst=2001:cafe::2,tun_tos=0,tun_flags=-df-csum+key,in_port=t1,dl_type=0x05ff +Datapath actions: tnl_push(tnl_port(genev_sys_6081),header(size=50,type=5,eth(dst=aa:bb:cc:00:00:01,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.1.1,dst=1.1.1.2,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(br0)),p0 +]) + +AT_CHECK([ovs-appctl ofproto/trace --names ovs-dummy 'tunnel(tun_id=0x7b,src=1.1.1.1,dst=1.1.1.2,ttl=64),in_port(6081)'], [0], [stdout]) +AT_CHECK([tail -2 stdout], [0], + [Megaflow: recirc_id=0,eth,tun_id=0x7b,tun_src=1.1.1.1,tun_dst=1.1.1.2,tun_tos=0,tun_flags=-df-csum+key,in_port=t2,dl_type=0x05ff +Datapath actions: tnl_push(tnl_port(vxlan_sys_4789),header(size=70,type=4,eth(dst=aa:bb:cc:00:00:01,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::1,dst=2001:cafe::2,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=4789,csum=0xffff),vxlan(flags=0x8000000,vni=0x7a)),out_port(br0)),p0 +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP -- 2.34.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev