From: Justin Pettit Date: Thu, 13 Jun 2013 23:46:33 +0000 (-0700) Subject: tunnel: Don't wildcard TTL and TOS in some circumstances. X-Git-Tag: v1.11.0~81 X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fovs.git;a=commitdiff_plain;h=f1a8ff5cb88ffa3ce2277b6cb50a17072e7dff54 tunnel: Don't wildcard TTL and TOS in some circumstances. For tunnels, we need to handle the facet's wildcards specially in a couple of cases: - Don't wildcard TTL for facets if "ttl" option is "inherit". - Never wildcard the ECN bits, since they are always inherited. - Wildcard the rest of the TOS field if the "tos" option is "inherit". Issue #17911 Signed-off-by: Justin Pettit --- diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index ebb3829f0..4cb4db678 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -5720,9 +5720,10 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet) ofpbuf_use_stub(&odp_actions, odp_actions_stub, sizeof odp_actions_stub); if (ofport->tnl_port) { + struct flow_wildcards wc; struct dpif_flow_stats stats; - odp_port = tnl_port_send(ofport->tnl_port, &flow); + odp_port = tnl_port_send(ofport->tnl_port, &flow, &wc); if (odp_port == OVSP_NONE) { return ENODEV; } @@ -6078,7 +6079,8 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port, * matches, while explicit set actions on tunnel metadata are. */ struct flow_tnl flow_tnl = ctx->xin->flow.tunnel; - odp_port = tnl_port_send(ofport->tnl_port, &ctx->xin->flow); + odp_port = tnl_port_send(ofport->tnl_port, &ctx->xin->flow, + &ctx->xout->wc); if (odp_port == OVSP_NONE) { xlate_report(ctx, "Tunneling decided against output"); goto out; /* restore flow_nw_tos */ diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index 8d29184f1..c6dba0127 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -220,7 +220,8 @@ tnl_port_receive(struct flow *flow) * port that the output should happen on. May return OVSP_NONE if the output * shouldn't occur. */ uint32_t -tnl_port_send(const struct tnl_port *tnl_port, struct flow *flow) +tnl_port_send(const struct tnl_port *tnl_port, struct flow *flow, + struct flow_wildcards *wc) { const struct netdev_tunnel_config *cfg; char *pre_flow_str = NULL; @@ -245,14 +246,18 @@ tnl_port_send(const struct tnl_port *tnl_port, struct flow *flow) } if (cfg->ttl_inherit && is_ip_any(flow)) { + wc->masks.nw_ttl = 0xff; flow->tunnel.ip_ttl = flow->nw_ttl; } else { flow->tunnel.ip_ttl = cfg->ttl; } if (cfg->tos_inherit && is_ip_any(flow)) { + wc->masks.nw_tos = 0xff; flow->tunnel.ip_tos = flow->nw_tos & IP_DSCP_MASK; } else { + /* ECN fields are always inherited. */ + wc->masks.nw_tos |= IP_ECN_MASK; flow->tunnel.ip_tos = cfg->tos; } diff --git a/ofproto/tunnel.h b/ofproto/tunnel.h index 1b055aef4..1b2d362b0 100644 --- a/ofproto/tunnel.h +++ b/ofproto/tunnel.h @@ -38,7 +38,8 @@ struct tnl_port *tnl_port_add(const struct ofport *, uint32_t odp_port); void tnl_port_del(struct tnl_port *); const struct ofport *tnl_port_receive(struct flow *); -uint32_t tnl_port_send(const struct tnl_port *, struct flow *); +uint32_t tnl_port_send(const struct tnl_port *, struct flow *, + struct flow_wildcards *wc); /* Returns true if 'flow' should be submitted to tnl_port_receive(). */ static inline bool diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index 2f2546d82..1f5d0fdad 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -2330,3 +2330,36 @@ in_port=1,vlan_tci=0x0000/0x0fff,dl_src=50:54:00:00:00:0b, n_subfacets:1, used:0 ]) OVS_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([ofproto-dpif megaflow - tunnels]) +OVS_VSWITCHD_START( + [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1 \ + ofport_request=1 -- \ + add-port br0 p2 -- set Interface p2 type=gre options:remote_ip=1.1.1.1 \ + ofport_request=2 options:key=flow -- \ + add-port br0 p3 -- set Interface p3 type=dummy ofport_request=3 \ + ofport_request=3 -- \ + add-port br0 p4 -- set Interface p4 type=gre options:remote_ip=1.1.1.2 \ + options:tos=inherit options:ttl=inherit ofport_request=4 options:key=flow]) +AT_DATA([flows.txt], [dnl +in_port=1,actions=output(2) +in_port=3,actions=output(4) +]) +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) +dnl ECN bits are always copied out, but don't use 0x3 (CE), since that +dnl will cause the packet to be dropped. +AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0xfd,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [success +]) +AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0x1,ttl=64,frag=no),icmp(type=8,code=0)'], [0], [success +]) +AT_CHECK([ovs-appctl netdev-dummy/receive p3 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0xfd,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [success +]) +AT_CHECK([ovs-appctl netdev-dummy/receive p3 'in_port(3),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0x1,ttl=64,frag=no),icmp(type=8,code=0)'], [0], [success +]) +AT_CHECK([ovs-appctl dpif/dump-megaflows br0 | STRIP_XOUT], [0], [dnl +in_port=1,nw_ecn=1, n_subfacets:2, used:0.0s, Datapath actions: +in_port=3,nw_tos=0,nw_ecn=1,nw_ttl=64, n_subfacets:1, used:0.0s, Datapath actions: +in_port=3,nw_tos=252,nw_ecn=1,nw_ttl=128, n_subfacets:1, used:0.0s, Datapath actions: +]) +OVS_VSWITCHD_STOP +AT_CLEANUP