[ovs-dev] [PATCH v3 17/17] netdev: Add support for GENEVE/VXLAN tunnel segmentation

Pravin B Shelar pshelar at ovn.org
Tue May 10 17:31:00 UTC 2016


This patch adds support to segment large UDP based tunnel
packet. With this patch large packet generated by STT can
be forwarded over to GENEVE/VXLAN port.

Signed-off-by: Pravin B Shelar <pshelar at ovn.org>
---
 lib/dp-packet-lso.c     | 32 +++++++++++++++++++++++++++++++-
 lib/dp-packet-lso.h     |  1 +
 lib/netdev-native-tnl.c | 20 ++++++++++++++++----
 lib/netdev-vport.c      | 11 +++++------
 4 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/lib/dp-packet-lso.c b/lib/dp-packet-lso.c
index bdcc987..c40ffd2 100644
--- a/lib/dp-packet-lso.c
+++ b/lib/dp-packet-lso.c
@@ -235,11 +235,41 @@ segment_gre_packet(struct dp_packet *orig)
 }
 
 static struct dp_packet *
+segment_udp_tnl_packet(struct dp_packet *orig)
+{
+    struct dp_packet *seg_list, *seg;
+    uint8_t l2_pad_size = orig->l2_pad_size;
+    uint16_t l2_5_ofs = orig->l2_5_ofs;
+    uint16_t l3_ofs = orig->l3_ofs;
+    uint16_t l4_ofs = orig->l4_ofs;
+
+    seg_list = segment_eth_packet(orig, orig->lso.outer_hlen);
+    restore_outer_headers(orig, orig->lso.outer_hlen, l2_pad_size, l2_5_ofs,
+                          l3_ofs, l4_ofs);
+
+    FOR_EACH_LSO_SEG(seg_list, seg) {
+        struct udp_header *udp;
+        restore_outer_headers(seg, orig->lso.outer_hlen, l2_pad_size, l2_5_ofs,
+                              l3_ofs, l4_ofs);
+
+        udp = dp_packet_l4(seg);
+        udp->udp_len = htons(dp_packet_size(seg) - seg->l4_ofs);
+        if (udp->udp_csum) {
+            fixup_segment_cheksum(seg, orig, UDP_CSUM_OFFSET);
+        }
+    }
+    return seg_list;
+}
+
+static struct dp_packet *
 segment_l4_packet(struct dp_packet *orig)
 {
     if (orig->lso.type & DPBUF_LSO_GRE) {
         orig->lso.type &= ~DPBUF_LSO_GRE;
         return segment_gre_packet(orig);
+    } else if (orig->lso.type & DPBUF_LSO_UDP_TNL) {
+        orig->lso.type &= ~DPBUF_LSO_UDP_TNL;
+        return segment_udp_tnl_packet(orig);
     } else if (orig->lso.type & (DPBUF_LSO_TCPv4 | DPBUF_LSO_TCPv6)) {
         return segment_tcp_packet(orig);
     } else if (orig->lso.type & (DPBUF_LSO_UDPv4 | DPBUF_LSO_UDPv6)) {
@@ -258,7 +288,7 @@ segment_ipv4_packet(struct dp_packet *orig)
     int ip_offset = 0;
     bool inc_ip_id = false;
 
-    if (orig->lso.type & (DPBUF_LSO_TCPv4 | DPBUF_LSO_GRE)) {
+    if (orig->lso.type & (DPBUF_LSO_TCPv4 | DPBUF_LSO_GRE | DPBUF_LSO_UDP_TNL)) {
         inc_ip_id = true;
         ip_id = ntohs(orig_iph->ip_id);
     }
diff --git a/lib/dp-packet-lso.h b/lib/dp-packet-lso.h
index fdf93a6..8d1cf03 100644
--- a/lib/dp-packet-lso.h
+++ b/lib/dp-packet-lso.h
@@ -32,6 +32,7 @@
 #define DPBUF_LSO_UDPv4 (1 << 2)
 #define DPBUF_LSO_UDPv6 (1 << 3)
 #define DPBUF_LSO_GRE   (1 << 4)
+#define DPBUF_LSO_UDP_TNL   (1 << 5)
 
 struct dp_packet_lso_ctx {
     struct dp_packet *next;       /* Used to list lso segments. */
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index a716492..62ee945 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -227,20 +227,32 @@ netdev_tnl_push_udp_header(struct dp_packet *packet,
     udp->udp_src = netdev_tnl_get_src_port(packet);
     udp->udp_len = htons(ip_tot_size);
 
+    if (packet->lso.type) {
+        packet->lso.type |= DPBUF_LSO_UDP_TNL;
+        packet->lso.outer_hlen = data->header_len;
+    }
+
     if (udp->udp_csum) {
+        ovs_be32 udp_csum;
         uint32_t csum;
+
         if (netdev_tnl_is_header_ipv6(dp_packet_data(packet))) {
             csum = packet_csum_pseudoheader6(netdev_tnl_ipv6_hdr(dp_packet_data(packet)));
         } else {
             csum = packet_csum_pseudoheader(netdev_tnl_ip_hdr(dp_packet_data(packet)));
         }
 
-        csum = csum_continue(csum, udp, ip_tot_size);
-        udp->udp_csum = csum_finish(csum);
+        if (packet->lso.type) {
+            udp_csum = ~csum_finish(csum);
+        } else {
+            csum = csum_continue(csum, udp, ip_tot_size);
+            udp_csum = csum_finish(csum);
 
-        if (!udp->udp_csum) {
-            udp->udp_csum = htons(0xffff);
+            if (!udp_csum) {
+                udp_csum = htons(0xffff);
+            }
         }
+        udp->udp_csum = udp_csum;
     }
 }
 
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index c2f3f5f..225a8e6 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -212,10 +212,7 @@ netdev_vport_construct(struct netdev *netdev_)
     eth_addr_random(&dev->etheraddr);
 
     /* Add a default destination port for tunnel ports if none specified. */
-    if (!strcmp(type, "gre")) {
-        netdev_->supported_lso_types = DPBUF_LSO_TCPv4 | DPBUF_LSO_TCPv6 |
-                                       DPBUF_LSO_UDPv4 | DPBUF_LSO_UDPv6;
-    } else if (!strcmp(type, "geneve")) {
+    if (!strcmp(type, "geneve")) {
         dev->tnl_cfg.dst_port = htons(GENEVE_DST_PORT);
     } else if (!strcmp(type, "vxlan")) {
         dev->tnl_cfg.dst_port = htons(VXLAN_DST_PORT);
@@ -223,11 +220,13 @@ netdev_vport_construct(struct netdev *netdev_)
         dev->tnl_cfg.dst_port = htons(LISP_DST_PORT);
     } else if (!strcmp(type, "stt")) {
         dev->tnl_cfg.dst_port = htons(STT_DST_PORT);
+        netdev_stt_class_init();
+    }
+    if (strcmp(type, "lisp")) {
+        /* All tunnels except lisp is implemented in userspace. */
         netdev_->supported_lso_types = DPBUF_LSO_TCPv4 | DPBUF_LSO_TCPv6 |
                                        DPBUF_LSO_UDPv4 | DPBUF_LSO_UDPv6;
-        netdev_stt_class_init();
     }
-
     dev->tnl_cfg.dont_fragment = true;
     dev->tnl_cfg.ttl = DEFAULT_TTL;
     return 0;
-- 
2.5.5




More information about the dev mailing list