tunnel: Don't wildcard TTL and TOS in some circumstances.
authorJustin Pettit <jpettit@nicira.com>
Thu, 13 Jun 2013 23:46:33 +0000 (16:46 -0700)
committerJustin Pettit <jpettit@nicira.com>
Fri, 14 Jun 2013 00:20:00 +0000 (17:20 -0700)
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 <jpettit@nicira.com>
ofproto/ofproto-dpif.c
ofproto/tunnel.c
ofproto/tunnel.h
tests/ofproto-dpif.at

index ebb3829..4cb4db6 100644 (file)
@@ -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 */
index 8d29184..c6dba01 100644 (file)
@@ -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;
     }
 
index 1b055ae..1b2d362 100644 (file)
@@ -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
index 2f2546d..1f5d0fd 100644 (file)
@@ -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: <del>
+in_port=3,nw_tos=0,nw_ecn=1,nw_ttl=64, n_subfacets:1, used:0.0s, Datapath actions: <del>
+in_port=3,nw_tos=252,nw_ecn=1,nw_ttl=128, n_subfacets:1, used:0.0s, Datapath actions: <del>
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP