[ovs-dev] [PATCH 6/9] tunneling: Factor out common UDP tunnel code.

Jesse Gross jesse at nicira.com
Mon Mar 30 22:14:49 UTC 2015


Currently, the userspace VXLAN implementation contains the code
for generating and parsing both the UDP and VXLAN headers. This
pulls out the UDP portion for better layering and to make it
easier to support additional UDP based tunnels and features.

Signed-off-by: Jesse Gross <jesse at nicira.com>
---
 lib/netdev-vport.c | 105 ++++++++++++++++++++++++++++++++---------------------
 lib/odp-util.c     |  37 +++++++++++--------
 2 files changed, 85 insertions(+), 57 deletions(-)

diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 0e0d791..0c9f5a4 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -876,6 +876,65 @@ push_ip_header(struct dp_packet *packet,
     return ip + 1;
 }
 
+static void *
+udp_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl)
+{
+    struct udp_header *udp;
+
+    udp = ip_extract_tnl_md(packet, tnl);
+    if (!udp) {
+        return NULL;
+    }
+
+    tnl->tp_src = udp->udp_src;
+    tnl->tp_dst = udp->udp_dst;
+
+    return udp + 1;
+}
+
+static ovs_be16
+get_src_port(struct dp_packet *packet)
+{
+    uint32_t hash;
+
+    hash = dp_packet_get_dp_hash(packet);
+
+    return htons((((uint64_t) hash * (tnl_udp_port_max - tnl_udp_port_min)) >> 32) +
+                 tnl_udp_port_min);
+}
+
+static void *
+push_udp_header(struct dp_packet *packet, const void *header, int size)
+{
+    struct udp_header *udp;
+    int ip_tot_size;
+
+    udp = push_ip_header(packet, header, size, &ip_tot_size);
+
+    /* set udp src port */
+    udp->udp_src = get_src_port(packet);
+    udp->udp_len = htons(ip_tot_size - sizeof (struct ip_header));
+    /* udp_csum is zero */
+
+    return udp + 1;
+}
+
+static void *
+udp_build_header(struct netdev_tunnel_config *tnl_cfg,
+                 struct ovs_action_push_tnl *data)
+{
+    struct ip_header *ip;
+    struct udp_header *udp;
+
+    ip = ip_hdr(data->header);
+    ip->ip_proto = IPPROTO_UDP;
+
+    udp = (struct udp_header *) (ip + 1);
+    udp->udp_dst = tnl_cfg->dst_port;
+
+    return udp + 1;
+}
+
 static int
 gre_header_len(ovs_be16 flags)
 {
@@ -1068,7 +1127,6 @@ vxlan_extract_md(struct dp_packet *packet)
 {
     struct pkt_metadata *md = &packet->md;
     struct flow_tnl *tnl = &md->tunnel;
-    struct udp_header *udp;
     struct vxlanhdr *vxh;
 
     memset(md, 0, sizeof *md);
@@ -1076,11 +1134,10 @@ vxlan_extract_md(struct dp_packet *packet)
         return;
     }
 
-    udp = ip_extract_tnl_md(packet, tnl);
-    if (!udp) {
+    vxh = udp_extract_tnl_md(packet, tnl);
+    if (!vxh) {
         return;
     }
-    vxh = (struct vxlanhdr *) (udp + 1);
 
     if (get_16aligned_be32(&vxh->vx_flags) != htonl(VXLAN_FLAGS) ||
        (get_16aligned_be32(&vxh->vx_vni) & htonl(0xff))) {
@@ -1090,8 +1147,6 @@ vxlan_extract_md(struct dp_packet *packet)
         reset_tnl_md(md);
         return;
     }
-    tnl->tp_src = udp->udp_src;
-    tnl->tp_dst = udp->udp_dst;
     tnl->tun_id = htonll(ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
 
     dp_packet_reset_packet(packet, VXLAN_HLEN);
@@ -1116,21 +1171,14 @@ netdev_vxlan_build_header(const struct netdev *netdev,
 {
     struct netdev_vport *dev = netdev_vport_cast(netdev);
     struct netdev_tunnel_config *tnl_cfg;
-    struct ip_header *ip;
-    struct udp_header *udp;
     struct vxlanhdr *vxh;
 
     /* XXX: RCUfy tnl_cfg. */
     ovs_mutex_lock(&dev->mutex);
     tnl_cfg = &dev->tnl_cfg;
 
-    ip = ip_hdr(data->header);
-    ip->ip_proto = IPPROTO_UDP;
+    vxh = udp_build_header(tnl_cfg, data);
 
-    udp = (struct udp_header *) (ip + 1);
-    udp->udp_dst = tnl_cfg->dst_port;
-
-    vxh = (struct vxlanhdr *) (udp + 1);
     put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
     put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8));
 
@@ -1140,32 +1188,6 @@ netdev_vxlan_build_header(const struct netdev *netdev,
     return 0;
 }
 
-static ovs_be16
-get_src_port(struct dp_packet *packet)
-{
-    uint32_t hash;
-
-    hash = dp_packet_get_dp_hash(packet);
-
-    return htons((((uint64_t) hash * (tnl_udp_port_max - tnl_udp_port_min)) >> 32) +
-                 tnl_udp_port_min);
-}
-
-static void
-netdev_vxlan_push_header__(struct dp_packet *packet,
-                           const void *header, int size)
-{
-    struct udp_header *udp;
-    int ip_tot_size;
-
-    udp = push_ip_header(packet, header, size, &ip_tot_size);
-
-    /* set udp src port */
-    udp->udp_src = get_src_port(packet);
-    udp->udp_len = htons(ip_tot_size - sizeof (struct ip_header));
-    /* udp_csum is zero */
-}
-
 static int
 netdev_vxlan_push_header(const struct netdev *netdev OVS_UNUSED,
                          struct dp_packet **packets, int cnt,
@@ -1174,8 +1196,7 @@ netdev_vxlan_push_header(const struct netdev *netdev OVS_UNUSED,
     int i;
 
     for (i = 0; i < cnt; i++) {
-        netdev_vxlan_push_header__(packets[i],
-                                   data->header, VXLAN_HLEN);
+        push_udp_header(packets[i], data->header, VXLAN_HLEN);
         packets[i]->md = PKT_METADATA_INITIALIZER(u32_to_odp(data->out_port));
     }
     return 0;
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 7c24512..83382db 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -510,6 +510,18 @@ format_odp_hash_action(struct ds *ds, const struct ovs_action_hash *hash_act)
     ds_put_format(ds, ")");
 }
 
+static const void *
+format_udp_tnl_push_header(struct ds *ds, const struct ip_header *ip)
+{
+    const struct udp_header *udp;
+
+    udp = (const struct udp_header *) (ip + 1);
+    ds_put_format(ds, "udp(src=%"PRIu16",dst=%"PRIu16"),",
+                  ntohs(udp->udp_src), ntohs(udp->udp_dst));
+
+    return udp + 1;
+}
+
 static void
 format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
 {
@@ -541,15 +553,9 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
 
     if (data->tnl_type == OVS_VPORT_TYPE_VXLAN) {
         const struct vxlanhdr *vxh;
-        const struct udp_header *udp;
 
-        /* UDP */
-        udp = (const struct udp_header *) (ip + 1);
-        ds_put_format(ds, "udp(src=%"PRIu16",dst=%"PRIu16"),",
-                      ntohs(udp->udp_src), ntohs(udp->udp_dst));
+        vxh = format_udp_tnl_push_header(ds, ip);
 
-        /* VxLan */
-        vxh = (const struct vxlanhdr *)   (udp + 1);
         ds_put_format(ds, "vxlan(flags=0x%"PRIx32",vni=0x%"PRIx32")",
                       ntohl(get_16aligned_be32(&vxh->vx_flags)),
                       ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
@@ -887,7 +893,6 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data)
     greh = (struct gre_base_hdr *) l4;
     if (ovs_scan_len(s, &n, "udp(src=%"SCNi16",dst=%"SCNi16"),",
                          &udp_src, &udp_dst)) {
-        struct vxlanhdr *vxh;
         uint32_t vx_flags, vx_vni;
 
         udp->udp_src = htons(udp_src);
@@ -895,16 +900,18 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data)
         udp->udp_len = 0;
         udp->udp_csum = 0;
 
-        vxh = (struct vxlanhdr *) (udp + 1);
-        if (!ovs_scan_len(s, &n, "vxlan(flags=0x%"SCNx32",vni=0x%"SCNx32"))",
+        if (ovs_scan_len(s, &n, "vxlan(flags=0x%"SCNx32",vni=0x%"SCNx32"))",
                             &vx_flags, &vx_vni)) {
+            struct vxlanhdr *vxh = (struct vxlanhdr *) (udp + 1);
+
+            put_16aligned_be32(&vxh->vx_flags, htonl(vx_flags));
+            put_16aligned_be32(&vxh->vx_vni, htonl(vx_vni << 8));
+            tnl_type = OVS_VPORT_TYPE_VXLAN;
+            header_len = sizeof *eth + sizeof *ip +
+                         sizeof *udp + sizeof *vxh;
+        } else {
             return -EINVAL;
         }
-        put_16aligned_be32(&vxh->vx_flags, htonl(vx_flags));
-        put_16aligned_be32(&vxh->vx_vni, htonl(vx_vni << 8));
-        tnl_type = OVS_VPORT_TYPE_VXLAN;
-        header_len = sizeof *eth + sizeof *ip +
-                     sizeof *udp + sizeof *vxh;
     } else if (ovs_scan_len(s, &n, "gre((flags=0x%"SCNx16",proto=0x%"SCNx16")",
                          &greh->flags, &gre_proto)){
 
-- 
1.9.1




More information about the dev mailing list