This function can be used to build varius tunnel headers.

Signed-off-by: Pravin B Shelar <pshe...@ovn.org>
---
 lib/netdev-native-tnl.c | 128 ++++++++++++++++++++++++++++++++++--------------
 lib/netdev-native-tnl.h |  28 +++++++++--
 lib/netdev-provider.h   |   9 ++--
 lib/netdev.c            |  11 +++--
 lib/netdev.h            |   5 +-
 ofproto/tunnel.c        |  50 +------------------
 6 files changed, 136 insertions(+), 95 deletions(-)

diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index 2e181f2..375713a 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -244,32 +244,91 @@ netdev_tnl_push_udp_header(struct dp_packet *packet,
 }
 
 static void *
-udp_build_header(struct netdev_tunnel_config *tnl_cfg,
-                 const struct flow *tnl_flow,
-                 struct ovs_action_push_tnl *data,
+eth_build_header(struct ovs_action_push_tnl *data,
+                 uint16_t eth_proto,
+                 const struct eth_addr dmac,
+                 const struct eth_addr smac,
                  unsigned int *hlen)
 {
-    struct ip_header *ip;
-    struct ovs_16aligned_ip6_hdr *ip6;
-    struct udp_header *udp;
-    bool is_ipv6;
+    struct eth_header *eth;
+
+    /* Build Ethernet and IP headers. */
+    memset(data->header, 0, sizeof data->header);
 
+    eth = (struct eth_header *)data->header;
+    eth->eth_dst = dmac;
+    eth->eth_src = smac;
+    eth->eth_type = htons(eth_proto);
     *hlen = sizeof(struct eth_header);
+    return eth + 1;
+}
 
-    is_ipv6 = netdev_tnl_is_header_ipv6(data->header);
+void *
+netdev_tnl_ip_build_header(struct ovs_action_push_tnl *data,
+                           const struct flow *tnl_flow,
+                           uint8_t next_proto,
+                           unsigned int *hlen,
+                           const struct eth_addr dmac,
+                           const struct eth_addr smac,
+                           const struct in6_addr *src,
+                           bool *is_ipv6)
+{
+    ovs_be32 ip_src;
+    void *l3;
+
+    ip_src = in6_addr_get_mapped_ipv4(src);
+    l3 = eth_build_header(data,
+                          ip_src ? ETH_TYPE_IP : ETH_TYPE_IPV6,
+                          dmac, smac, hlen);
+
+    if (ip_src) {
+        struct ip_header *ip;
+
+        ip = (struct ip_header *) l3;
+
+        ip->ip_ihl_ver = IP_IHL_VER(5, 4);
+        ip->ip_tos = tnl_flow->tunnel.ip_tos;
+        ip->ip_ttl = tnl_flow->tunnel.ip_ttl;
+        ip->ip_frag_off = (tnl_flow->tunnel.flags & FLOW_TNL_F_DONT_FRAGMENT) ?
+                          htons(IP_DF) : 0;
+        put_16aligned_be32(&ip->ip_src, ip_src);
+        put_16aligned_be32(&ip->ip_dst, tnl_flow->tunnel.ip_dst);
+        ip->ip_proto = next_proto;
+        ip->ip_csum = csum(ip, sizeof *ip);
 
-    if (is_ipv6) {
-        ip6 = netdev_tnl_ipv6_hdr(data->header);
-        ip6->ip6_nxt = IPPROTO_UDP;
-        udp = (struct udp_header *) (ip6 + 1);
-        *hlen += IPV6_HEADER_LEN;
-    } else {
-        ip = netdev_tnl_ip_hdr(data->header);
-        ip->ip_proto = IPPROTO_UDP;
-        udp = (struct udp_header *) (ip + 1);
         *hlen += IP_HEADER_LEN;
+        *is_ipv6 = false;
+        return ip + 1;
+    } else {
+        struct ovs_16aligned_ip6_hdr *ip6;
+
+        ip6 = (struct ovs_16aligned_ip6_hdr *) l3;
+
+        ip6->ip6_vfc = 0x60;
+        ip6->ip6_hlim = tnl_flow->tunnel.ip_ttl;
+        ip6->ip6_nxt = next_proto;
+        memcpy(&ip6->ip6_src, src, sizeof(ovs_be32[4]));
+        memcpy(&ip6->ip6_dst, &tnl_flow->tunnel.ipv6_dst, sizeof(ovs_be32[4]));
+
+        *hlen += IPV6_HEADER_LEN;
+        *is_ipv6 = true;
+        return ip6 + 1;
     }
+}
+
+static void *
+udp_build_header(struct netdev_tunnel_config *tnl_cfg,
+                 const struct flow *tnl_flow,
+                 struct ovs_action_push_tnl *data,
+                 const struct eth_addr dmac,
+                 const struct eth_addr smac,
+                 const struct in6_addr *src,
+                 unsigned int *hlen)
+{
+    struct udp_header *udp;
+    bool is_ipv6;
 
+    udp = netdev_tnl_ip_build_header(data, tnl_flow, IPPROTO_UDP, hlen, dmac, 
smac, src, &is_ipv6);
     udp->udp_dst = tnl_cfg->dst_port;
 
     if (is_ipv6 || tnl_flow->tunnel.flags & FLOW_TNL_F_CSUM) {
@@ -399,32 +458,23 @@ netdev_gre_push_header(struct dp_packet *packet,
 int
 netdev_gre_build_header(const struct netdev *netdev,
                         struct ovs_action_push_tnl *data,
-                        const struct flow *tnl_flow)
+                        const struct flow *tnl_flow,
+                        const struct eth_addr dmac,
+                        const struct eth_addr smac,
+                        const struct in6_addr *src)
 {
     struct netdev_vport *dev = netdev_vport_cast(netdev);
     struct netdev_tunnel_config *tnl_cfg;
-    struct ip_header *ip;
-    struct ovs_16aligned_ip6_hdr *ip6;
     struct gre_base_hdr *greh;
     ovs_16aligned_be32 *options;
-    int hlen;
+    unsigned int hlen, offset;
     bool is_ipv6;
 
-    is_ipv6 = netdev_tnl_is_header_ipv6(data->header);
-
     /* XXX: RCUfy tnl_cfg. */
     ovs_mutex_lock(&dev->mutex);
     tnl_cfg = &dev->tnl_cfg;
 
-    if (is_ipv6) {
-        ip6 = netdev_tnl_ipv6_hdr(data->header);
-        ip6->ip6_nxt = IPPROTO_GRE;
-        greh = (struct gre_base_hdr *) (ip6 + 1);
-    } else {
-        ip = netdev_tnl_ip_hdr(data->header);
-        ip->ip_proto = IPPROTO_GRE;
-        greh = (struct gre_base_hdr *) (ip + 1);
-    }
+    greh = netdev_tnl_ip_build_header(data, tnl_flow, IPPROTO_GRE, &offset, 
dmac, smac, src, &is_ipv6);
 
     greh->protocol = htons(ETH_TYPE_TEB);
     greh->flags = 0;
@@ -492,7 +542,10 @@ err:
 int
 netdev_vxlan_build_header(const struct netdev *netdev,
                           struct ovs_action_push_tnl *data,
-                          const struct flow *tnl_flow)
+                          const struct flow *tnl_flow,
+                          const struct eth_addr dmac,
+                          const struct eth_addr smac,
+                          const struct in6_addr *src)
 {
     struct netdev_vport *dev = netdev_vport_cast(netdev);
     struct netdev_tunnel_config *tnl_cfg;
@@ -503,7 +556,7 @@ netdev_vxlan_build_header(const struct netdev *netdev,
     ovs_mutex_lock(&dev->mutex);
     tnl_cfg = &dev->tnl_cfg;
 
-    vxh = udp_build_header(tnl_cfg, tnl_flow, data, &hlen);
+    vxh = udp_build_header(tnl_cfg, tnl_flow, data, dmac, smac, src, &hlen);
 
     put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
     put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 
8));
@@ -572,7 +625,10 @@ err:
 int
 netdev_geneve_build_header(const struct netdev *netdev,
                            struct ovs_action_push_tnl *data,
-                           const struct flow *tnl_flow)
+                           const struct flow *tnl_flow,
+                           const struct eth_addr dmac,
+                           const struct eth_addr smac,
+                           const struct in6_addr *src)
 {
     struct netdev_vport *dev = netdev_vport_cast(netdev);
     struct netdev_tunnel_config *tnl_cfg;
@@ -585,7 +641,7 @@ netdev_geneve_build_header(const struct netdev *netdev,
     ovs_mutex_lock(&dev->mutex);
     tnl_cfg = &dev->tnl_cfg;
 
-    gnh = udp_build_header(tnl_cfg, tnl_flow, data, &hlen);
+    gnh = udp_build_header(tnl_cfg, tnl_flow, data, dmac, smac, src, &hlen);
 
     put_16aligned_be32(&gnh->vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8));
 
diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h
index e0d15fc..c6e1a5a 100644
--- a/lib/netdev-native-tnl.h
+++ b/lib/netdev-native-tnl.h
@@ -25,7 +25,11 @@
 int
 netdev_gre_build_header(const struct netdev *netdev,
                         struct ovs_action_push_tnl *data,
-                        const struct flow *tnl_flow);
+                        const struct flow *tnl_flow,
+                        const struct eth_addr dmac,
+                        const struct eth_addr smac,
+                        const struct in6_addr *src);
+
 void
 netdev_gre_push_header(struct dp_packet *packet,
                        const struct ovs_action_push_tnl *data);
@@ -38,14 +42,22 @@ netdev_tnl_push_udp_header(struct dp_packet *packet,
 int
 netdev_geneve_build_header(const struct netdev *netdev,
                            struct ovs_action_push_tnl *data,
-                           const struct flow *tnl_flow);
+                           const struct flow *tnl_flow,
+                           const struct eth_addr dmac,
+                           const struct eth_addr smac,
+                           const struct in6_addr *src);
+
 struct dp_packet *
 netdev_geneve_pop_header(struct dp_packet *packet);
 
 int
 netdev_vxlan_build_header(const struct netdev *netdev,
                           struct ovs_action_push_tnl *data,
-                          const struct flow *tnl_flow);
+                          const struct flow *tnl_flow,
+                          const struct eth_addr dmac,
+                          const struct eth_addr smac,
+                          const struct in6_addr *src);
+
 struct dp_packet *
 netdev_vxlan_pop_header(struct dp_packet *packet);
 
@@ -69,6 +81,16 @@ netdev_tnl_ipv6_hdr(void *eth)
     return (void *)((char *)eth + sizeof (struct eth_header));
 }
 
+void *
+netdev_tnl_ip_build_header(struct ovs_action_push_tnl *data,
+                           const struct flow *tnl_flow,
+                           uint8_t next_proto,
+                           unsigned int *hlen,
+                           const struct eth_addr dmac,
+                           const struct eth_addr smac,
+                           const struct in6_addr *src,
+                           bool *is_ipv6);
+
 extern uint16_t tnl_udp_port_min;
 extern uint16_t tnl_udp_port_max;
 
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index f4792a3..801043d 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -263,10 +263,13 @@ struct netdev_class {
     const struct netdev_tunnel_config *
         (*get_tunnel_config)(const struct netdev *netdev);
 
-    /* Build Partial Tunnel header.  Ethernet and ip header is already built,
-     * build_header() is suppose build protocol specific part of header. */
+    /* Build Tunnel header.  Ethernet and ip header parameters are passed to
+     * tunnel implementation to build entire outer header for given flow. */
     int (*build_header)(const struct netdev *, struct ovs_action_push_tnl 
*data,
-                        const struct flow *tnl_flow);
+                        const struct flow *tnl_flow,
+                        const struct eth_addr dmac,
+                        const struct eth_addr smac,
+                        const struct in6_addr *src);
 
     /* build_header() can not build entire header for all packets for given
      * flow.  Push header is called for packet to build header specific to
diff --git a/lib/netdev.c b/lib/netdev.c
index c3fdb44..c18c463 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -846,12 +846,15 @@ netdev_pop_header(struct netdev *netdev, struct 
dp_packet_batch *batch)
     batch->count = n_cnt;
 }
 
-int
-netdev_build_header(const struct netdev *netdev, struct ovs_action_push_tnl 
*data,
-                    const struct flow *tnl_flow)
+int netdev_build_header(const struct netdev *netdev,
+                        struct ovs_action_push_tnl *data,
+                        const struct flow *tnl_flow,
+                        const struct eth_addr dmac,
+                        const struct eth_addr smac,
+                        const struct in6_addr *src)
 {
     if (netdev->netdev_class->build_header) {
-        return netdev->netdev_class->build_header(netdev, data, tnl_flow);
+        return netdev->netdev_class->build_header(netdev, data, tnl_flow, 
dmac, smac, src);
     }
     return EOPNOTSUPP;
 }
diff --git a/lib/netdev.h b/lib/netdev.h
index a292167..2c76966 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -154,7 +154,10 @@ int netdev_send(struct netdev *, int qid, struct 
dp_packet_batch *,
 void netdev_send_wait(struct netdev *, int qid);
 
 int netdev_build_header(const struct netdev *, struct ovs_action_push_tnl 
*data,
-                        const struct flow *tnl_flow);
+                        const struct flow *tnl_flow,
+                        const struct eth_addr dmac,
+                        const struct eth_addr smac,
+                        const struct in6_addr *src);
 int netdev_push_header(const struct netdev *netdev,
                        struct dp_packet_batch *,
                        const struct ovs_action_push_tnl *data);
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
index 18297b2..be56ddf 100644
--- a/ofproto/tunnel.c
+++ b/ofproto/tunnel.c
@@ -689,62 +689,16 @@ tnl_port_build_header(const struct ofport_dpif *ofport,
                       const struct flow *tnl_flow,
                       const struct eth_addr dmac,
                       const struct eth_addr smac,
-                      const struct in6_addr * ipv6_src,
+                      const struct in6_addr *src,
                       struct ovs_action_push_tnl *data)
 {
     struct tnl_port *tnl_port;
-    struct eth_header *eth;
-    struct ip_header *ip;
-    struct ovs_16aligned_ip6_hdr *ip6;
-    void *l3;
     int res;
-    ovs_be32 ip_src;
 
     fat_rwlock_rdlock(&rwlock);
     tnl_port = tnl_find_ofport(ofport);
     ovs_assert(tnl_port);
-
-    ip_src = in6_addr_get_mapped_ipv4(ipv6_src);
-
-    /* Build Ethernet and IP headers. */
-    memset(data->header, 0, sizeof data->header);
-
-    eth = (struct eth_header *)data->header;
-    eth->eth_dst = dmac;
-    eth->eth_src = smac;
-    eth->eth_type = ip_src ? htons(ETH_TYPE_IP) : htons(ETH_TYPE_IPV6);
-
-    l3 = (eth + 1);
-
-    if (ip_src) {
-        ip = (struct ip_header *) l3;
-
-        ip->ip_ihl_ver = IP_IHL_VER(5, 4);
-        ip->ip_tos = tnl_flow->tunnel.ip_tos;
-        ip->ip_ttl = tnl_flow->tunnel.ip_ttl;
-        ip->ip_frag_off = (tnl_flow->tunnel.flags & FLOW_TNL_F_DONT_FRAGMENT) ?
-                          htons(IP_DF) : 0;
-
-        put_16aligned_be32(&ip->ip_src, ip_src);
-        put_16aligned_be32(&ip->ip_dst, tnl_flow->tunnel.ip_dst);
-    } else {
-        ip6 = (struct ovs_16aligned_ip6_hdr *) l3;
-
-        ip6->ip6_vfc = 0x60;
-        ip6->ip6_hlim = tnl_flow->tunnel.ip_ttl;
-
-        /* next header, plen - at netdev_build_header? */
-
-        memcpy(&ip6->ip6_src, ipv6_src, sizeof(ovs_be32[4]));
-        memcpy(&ip6->ip6_dst, &tnl_flow->tunnel.ipv6_dst, sizeof(ovs_be32[4]));
-    }
-
-    res = netdev_build_header(tnl_port->netdev, data, tnl_flow);
-
-    if (ip_src) {
-        ip->ip_csum = csum(ip, sizeof *ip);
-    }
-
+    res = netdev_build_header(tnl_port->netdev, data, tnl_flow, dmac, smac, 
src);
     fat_rwlock_unlock(&rwlock);
 
     return res;
-- 
2.5.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to