tunneling: Add df_default and df_inherit tunnel options.
authorAndrew Evans <aevans@nicira.com>
Sat, 30 Apr 2011 00:05:58 +0000 (17:05 -0700)
committerAndrew Evans <aevans@nicira.com>
Sat, 30 Apr 2011 00:05:58 +0000 (17:05 -0700)
Split existing pmtud tunnel option's functionality into three. Existing pmtud
option still exists, but now governs only whether datapath sends ICMP frag
needed messages. New df_inherit option controls whether DF bit is copied from
packet inner header to outer tunnel header. New df_default option controls
whether DF bit is set if inner packet isn't IP or if df_inherit is disabled.

Suggested-by: Jesse Gross <jesse@nicira.com>
Signed-off-by: Andrew Evans <aevans@nicira.com>
Feature #5456.

datapath/tunnel.c
include/openvswitch/tunnel.h
lib/netdev-vport.c
vswitchd/vswitch.xml

index 899d1cdcb8b4fa037fbc92bffc8148aeb993aede..70a4cd7ca3ab6a02288c59e9b099ff3f808a2c35 100644 (file)
@@ -725,8 +725,9 @@ static bool check_mtu(struct sk_buff *skb,
                      const struct tnl_mutable_config *mutable,
                      const struct rtable *rt, __be16 *frag_offp)
 {
+       bool df_inherit = mutable->flags & TNL_F_DF_INHERIT;
        bool pmtud = mutable->flags & TNL_F_PMTUD;
-       __be16 frag_off = 0;
+       __be16 frag_off = mutable->flags & TNL_F_DF_DEFAULT ? htons(IP_DF) : 0;
        int mtu = 0;
        unsigned int packet_length = skb->len - ETH_HLEN;
 
@@ -738,8 +739,6 @@ static bool check_mtu(struct sk_buff *skb,
        if (pmtud) {
                int vlan_header = 0;
 
-               frag_off = htons(IP_DF);
-
                /* The tag needs to go in packet regardless of where it
                 * currently is, so subtract it from the MTU.
                 */
@@ -756,7 +755,8 @@ static bool check_mtu(struct sk_buff *skb,
        if (skb->protocol == htons(ETH_P_IP)) {
                struct iphdr *iph = ip_hdr(skb);
 
-               frag_off |= iph->frag_off & htons(IP_DF);
+               if (df_inherit)
+                       frag_off = iph->frag_off & htons(IP_DF);
 
                if (pmtud && iph->frag_off & htons(IP_DF)) {
                        mtu = max(mtu, IP_MIN_MTU);
@@ -769,8 +769,10 @@ static bool check_mtu(struct sk_buff *skb,
        }
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        else if (skb->protocol == htons(ETH_P_IPV6)) {
-               /* IPv6 requires PMTUD if the packet is above the minimum MTU. */
-               if (packet_length > IPV6_MIN_MTU)
+               /* IPv6 requires end hosts to do fragmentation
+                * if the packet is above the minimum MTU.
+                */
+               if (df_inherit && packet_length > IPV6_MIN_MTU)
                        frag_off = htons(IP_DF);
 
                if (pmtud) {
index a394f8a8d6f05aca8bbce7203e578035b9c582d8..5e2e916444a6e4a0cca2a39a80f81598654ca1c1 100644 (file)
@@ -65,8 +65,10 @@ enum {
 #define TNL_F_CSUM             (1 << 0) /* Checksum packets. */
 #define TNL_F_TOS_INHERIT      (1 << 1) /* Inherit the ToS from the inner packet. */
 #define TNL_F_TTL_INHERIT      (1 << 2) /* Inherit the TTL from the inner packet. */
-#define TNL_F_PMTUD            (1 << 3) /* Enable path MTU discovery. */
-#define TNL_F_HDR_CACHE                (1 << 4) /* Enable tunnel header caching. */
-#define TNL_F_IPSEC            (1 << 5) /* Traffic is IPsec encrypted. */
+#define TNL_F_DF_INHERIT       (1 << 3) /* Inherit the DF bit from the inner packet. */
+#define TNL_F_DF_DEFAULT       (1 << 4) /* Set the DF bit if inherit off or not IP. */
+#define TNL_F_PMTUD            (1 << 5) /* Enable path MTU discovery. */
+#define TNL_F_HDR_CACHE                (1 << 6) /* Enable tunnel header caching. */
+#define TNL_F_IPSEC            (1 << 7) /* Traffic is IPsec encrypted. */
 
 #endif /* openvswitch/tunnel.h */
index be269415922d215f283d6d6decbb0e7a9b860910..f31f85fd10f5f22411b76743b03b6d6e5c2de133 100644 (file)
@@ -667,7 +667,7 @@ parse_tunnel_config(const char *name, const char *type,
     ovs_be32 daddr = htonl(0);
     uint32_t flags;
 
-    flags = TNL_F_PMTUD | TNL_F_HDR_CACHE;
+    flags = TNL_F_DF_DEFAULT | TNL_F_PMTUD | TNL_F_HDR_CACHE;
     if (!strcmp(type, "gre")) {
         is_gre = true;
     } else if (!strcmp(type, "ipsec_gre")) {
@@ -709,6 +709,14 @@ parse_tunnel_config(const char *name, const char *type,
             if (!strcmp(node->data, "true")) {
                 flags |= TNL_F_CSUM;
             }
+        } else if (!strcmp(node->name, "df_inherit")) {
+            if (!strcmp(node->data, "true")) {
+                flags |= TNL_F_DF_INHERIT;
+            }
+        } else if (!strcmp(node->name, "df_default")) {
+            if (!strcmp(node->data, "false")) {
+                flags &= ~TNL_F_DF_DEFAULT;
+            }
         } else if (!strcmp(node->name, "pmtud")) {
             if (!strcmp(node->data, "false")) {
                 flags &= ~TNL_F_PMTUD;
@@ -891,6 +899,12 @@ unparse_tunnel_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED,
     if (flags & TNL_F_CSUM) {
         smap_add(args, "csum", "true");
     }
+    if (flags & TNL_F_DF_INHERIT) {
+        smap_add(args, "df_inherit", "true");
+    }
+    if (!(flags & TNL_F_DF_DEFAULT)) {
+        smap_add(args, "df_default", "false");
+    }
     if (!(flags & TNL_F_PMTUD)) {
         smap_add(args, "pmtud", "false");
     }
index 48315fa9c1a68e2231106b33b2ca2bebbd068a8a..1db89dc5be9dbc6936af263659c7d6226fb7f0c9 100644 (file)
                 adds value for the GRE and encapsulated Ethernet headers.
                 Default is disabled, set to <code>true</code> to enable.</dd>
             </dl>
+            <dl>
+              <dt><code>df_inherit</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be copied
+                from the inner IP headers (those of the encapsulated traffic)
+                to the outer (tunnel) headers.  Default is disabled; set to
+                <code>true</code> to enable.</dd>
+            </dl>
+            <dl>
+              <dt><code>df_default</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be set by
+                default on tunnel headers if the <code>df_inherit</code> option
+                is not set, or if the encapsulated packet is not IP.  Default
+                is enabled; set to <code>false</code> to disable.</dd>
+            </dl>
             <dl>
               <dt><code>pmtud</code></dt>
               <dd>Optional.  Enable tunnel path MTU discovery.  If enabled
-                ``ICMP destination unreachable - fragmentation'' needed
+                ``ICMP Destination Unreachable - Fragmentation Needed''
                 messages will be generated for IPv4 packets with the DF bit set
                 and IPv6 packets above the minimum MTU if the packet size
-                exceeds the path MTU minus the size of the tunnel headers.  It
-                also forces the encapsulating packet DF bit to be set (it is
-                always set if the inner packet implies path MTU discovery).
+                exceeds the path MTU minus the size of the tunnel headers.
                 Note that this option causes behavior that is typically
                 reserved for routers and therefore is not entirely in
                 compliance with the IEEE 802.1D specification for bridges.
-                Default is enabled, set to <code>false</code> to disable.</dd>
+                Default is enabled; set to <code>false</code> to disable.</dd>
             </dl>
             <dl>
               <dt><code>header_cache</code></dt>
                 adds value for the GRE and encapsulated Ethernet headers.
                 Default is disabled, set to <code>true</code> to enable.</dd>
             </dl>
+            <dl>
+              <dt><code>df_inherit</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be copied
+                from the inner IP headers (those of the encapsulated traffic)
+                to the outer (tunnel) headers.  Default is disabled; set to
+                <code>true</code> to enable.</dd>
+            </dl>
+            <dl>
+              <dt><code>df_default</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be set by
+                default on tunnel headers if the <code>df_inherit</code> option
+                is not set, or if the encapsulated packet is not IP.  Default
+                is enabled; set to <code>false</code> to disable.</dd>
+            </dl>
             <dl>
               <dt><code>pmtud</code></dt>
               <dd>Optional.  Enable tunnel path MTU discovery.  If enabled
-                ``ICMP destination unreachable - fragmentation'' needed
+                ``ICMP Destination Unreachable - Fragmentation Needed''
                 messages will be generated for IPv4 packets with the DF bit set
                 and IPv6 packets above the minimum MTU if the packet size
-                exceeds the path MTU minus the size of the tunnel headers.  It
-                also forces the encapsulating packet DF bit to be set (it is
-                always set if the inner packet implies path MTU discovery).
+                exceeds the path MTU minus the size of the tunnel headers.
                 Note that this option causes behavior that is typically
                 reserved for routers and therefore is not entirely in
                 compliance with the IEEE 802.1D specification for bridges.
-                Default is enabled, set to <code>false</code> to disable.</dd>
+                Default is enabled; set to <code>false</code> to disable.</dd>
             </dl>
           </dd>
           <dt><code>capwap</code></dt>
                 (otherwise it will be the system default, typically 64).
                 Default is the system default TTL.</dd>
             </dl>
+            <dl>
+              <dt><code>df_inherit</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be copied
+                from the inner IP headers (those of the encapsulated traffic)
+                to the outer (tunnel) headers.  Default is disabled; set to
+                <code>true</code> to enable.</dd>
+            </dl>
+            <dl>
+              <dt><code>df_default</code></dt>
+              <dd>Optional.  If enabled, the Don't Fragment bit will be set by
+                default on tunnel headers if the <code>df_inherit</code> option
+                is not set, or if the encapsulated packet is not IP.  Default
+                is enabled; set to <code>false</code> to disable.</dd>
+            </dl>
             <dl>
               <dt><code>pmtud</code></dt>
               <dd>Optional.  Enable tunnel path MTU discovery.  If enabled
-                ``ICMP destination unreachable - fragmentation'' needed
+                ``ICMP Destination Unreachable - Fragmentation Needed''
                 messages will be generated for IPv4 packets with the DF bit set
                 and IPv6 packets above the minimum MTU if the packet size
-                exceeds the path MTU minus the size of the tunnel headers.  It
-                also forces the encapsulating packet DF bit to be set (it is
-                always set if the inner packet implies path MTU discovery).
+                exceeds the path MTU minus the size of the tunnel headers.
                 Note that this option causes behavior that is typically
                 reserved for routers and therefore is not entirely in
                 compliance with the IEEE 802.1D specification for bridges.
-                Default is enabled, set to <code>false</code> to disable.</dd>
+                Default is enabled; set to <code>false</code> to disable.</dd>
             </dl>
             <dl>
               <dt><code>header_cache</code></dt>