@@ -204,6 +204,8 @@ struct flow_wildcards {
((WC)->masks.FIELD |= (MASK))
#define WC_UNMASK_FIELD(WC, FIELD) \
memset(&(WC)->masks.FIELD, 0, sizeof (WC)->masks.FIELD)
+#define WC_FIELD_MASKED(WC, FIELD) \
+ ((WC)->masks.FIELD != 0)
void flow_wildcards_init_catchall(struct flow_wildcards *);
@@ -4070,7 +4070,17 @@ terminate_native_tunnel(struct xlate_ctx *ctx,
struct flow *flow,
/* XXX: Write better Filter for tunnel port. We can use in_port
* in tunnel-port flow to avoid these checks completely. */
if (ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) {
- *tnl_port = tnl_port_map_lookup(flow, wc);
+ /* to check if the wc contains src info, if not, erase all
+ * source info including smac, and sip
+ */
+ if (!WC_FIELD_MASKED(wc, nw_src)) {
+ *tnl_port = tnl_port_map_lookup(flow, wc);
+ if (*tnl_port != ODPP_NONE && !WC_FIELD_MASKED(wc, nw_src)) {
+ memset(&wc->masks.dl_src, 0, sizeof wc->masks.dl_src);
+ }
+ } else {
+ *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. */
@@ -7599,6 +7609,10 @@ xlate_actions(struct xlate_in *xin, struct
xlate_out *xout)
ctx.xin->xport_uuid = in_port->uuid;
}
+ if (in_port && in_port->is_tunnel) {
+ tnl_wc_init_by_port(in_port->ofport, ctx.wc);
+ }
+
if (flow->packet_type != htonl(PT_ETH) && in_port &&
in_port->pt_mode == NETDEV_PT_LEGACY_L3 && ctx.table_id == 0) {
/* Add dummy Ethernet header to non-L2 packet if it's coming from a
@@ -300,6 +300,23 @@ tnl_port_del(const struct ofport_dpif *ofport,
odp_port_t odp_port)
fat_rwlock_unlock(&rwlock);
}
+void
+tnl_wc_init_by_port(const struct ofport_dpif *ofport,
+ struct flow_wildcards *wc)
+{
+ struct tnl_port *tnl_port;
+
+ fat_rwlock_rdlock(&rwlock);
+ tnl_port = tnl_find_ofport(ofport);
+ if (tnl_port) {
+ if (tnl_port->match.ip_dst_flow) {
+ WC_UNMASK_FIELD(wc, tunnel.ip_src);
+ WC_UNMASK_FIELD(wc, tunnel.ipv6_src);
+ }
+ }
+ fat_rwlock_unlock(&rwlock);
+}
+
/* Looks in the table of tunnels for a tunnel matching the metadata in 'flow'.
* Returns the 'ofport' corresponding to the new in_port, or a null pointer if
* none is found.
@@ -45,7 +45,8 @@ bool tnl_process_ecn(struct flow *);
odp_port_t tnl_port_send(const struct ofport_dpif *, struct flow *,
struct flow_wildcards *wc);
const char *tnl_port_get_type(const struct ofport_dpif *tnl_port);
-
+void tnl_wc_init_by_port(const struct ofport_dpif *ofport,
+ struct flow_wildcards *wc);
/* Returns true if 'flow' should be submitted to tnl_port_receive(). */
static inline bool
tnl_port_should_receive(const struct flow *flow)
@@ -1019,7 +1019,7 @@ ovs-appctl time/warp 1000
AT_CHECK([
ovs-appctl dpctl/dump-flows --names dummy@ovs-dummy | strip_used
| grep -v ipv6 | sort
], [0], [flow-dump from the main thread:
-recirc_id(0),in_port(p0),packet_type(ns=0,id=0),eth(src=aa:bb:cc:00:00:02,dst=aa:bb:cc:00:00:01),eth_type(0x0800),ipv4(dst=20.0.0.1,proto=47,frag=no),
packets:3, bytes:378, used:0.0s, actions:tnl_pop(gre_sys)
+recirc_id(0),in_port(p0),packet_type(ns=0,id=0),eth(dst=aa:bb:cc:00:00:01),eth_type(0x0800),ipv4(dst=20.0.0.1,proto=47,frag=no),
packets:3, bytes:378, used:0.0s, actions:tnl_pop(gre_sys)
tunnel(src=20.0.0.2,dst=20.0.0.1,flags(-df-csum)),recirc_id(0),in_port(gre_sys),packet_type(ns=1,id=0x8847),eth_type(0x8847),mpls(label=999/0x0,tc=0/0,ttl=64/0x0,bos=1/1),
packets:3, bytes:264, used:0.0s,
actions:push_eth(src=00:00:00:00:00:00,dst=00:00:00:00:00:00),pop_mpls(eth_type=0x800),recirc(0x1)
tunnel(src=20.0.0.2,dst=20.0.0.1,flags(-df-csum)),recirc_id(0x1),in_port(gre_sys),packet_type(ns=0,id=0),eth(dst=00:00:00:00:00:00),eth_type(0x0800),ipv4(ttl=64,frag=no),
packets:3, bytes:294, used:0.0s, actions:set(ipv4(ttl=63)),int-br
])
@@ -429,7 +429,7 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port
5'], [0], [dnl
port 5: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=?
])
AT_CHECK([ovs-appctl dpif/dump-flows int-br | grep 'in_port(6081)'], [0], [dnl
-tunnel(tun_id=0x7b,ipv6_src=2001:cafe::92,ipv6_dst=2001:cafe::88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no),
packets:0, bytes:0, used:never,
actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=3,rule_cookie=0,controller_id=0,max_len=65535))
+tunnel(tun_id=0x7b,ipv6_dst=2001:cafe::88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no),
packets:0, bytes:0, used:never,
actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=3,rule_cookie=0,controller_id=0,max_len=65535))
])
ovs-appctl time/warp 10000
@@ -499,7 +499,7 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port
5'], [0], [dnl
port 5: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=?
])
AT_CHECK([ovs-appctl dpif/dump-flows int-br | grep 'in_port(6081)'], [0], [dnl
-tunnel(tun_id=0x7b,src=1.1.2.92,dst=1.1.2.88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no),
packets:0, bytes:0, used:never,
actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=2,rule_cookie=0,controller_id=0,max_len=65535))
+tunnel(tun_id=0x7b,dst=1.1.2.88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no),
if the tunnel is specified as "ip_remote=flow", we can try to generate a megaflow which ignores all source address, such as source mac, source IP address in the outter header of the packet. This can reduce the number of megaflows and avoid expensive upcalls and improve the performance. Signed-off-by: hepeng <hepeng.0320@bytedance.com> --- include/openvswitch/flow.h | 2 ++ ofproto/ofproto-dpif-xlate.c | 16 +++++++++++++++- ofproto/tunnel.c | 17 +++++++++++++++++ ofproto/tunnel.h | 3 ++- tests/packet-type-aware.at | 2 +- tests/tunnel-push-pop-ipv6.at | 2 +- tests/tunnel-push-pop.at | 2 +- 7 files changed, 39 insertions(+), 5 deletions(-) packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=2,rule_cookie=0,controller_id=0,max_len=65535)) ]) ovs-appctl time/warp 10000 -- 2.20.1