]> git.proxmox.com Git - mirror_ovs.git/commitdiff
netdev-native-tnl: Introduce ip_build_header()
authorPravin B Shelar <pshelar@ovn.org>
Tue, 24 May 2016 03:27:14 +0000 (20:27 -0700)
committerPravin B Shelar <pshelar@ovn.org>
Tue, 24 May 2016 03:27:14 +0000 (20:27 -0700)
The native tunneling build tunnel header code is spread across
two different modules, it makes pretty hard to follow the code.
Following patch refactors the code to move all code to
netdev-ative-tnl module.

Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
Acked-by: Jesse Gross <jesse@kernel.org>
lib/netdev-native-tnl.c
lib/netdev-native-tnl.h
lib/netdev-provider.h
lib/netdev.c
lib/netdev.h
ofproto/ofproto-dpif-xlate.c
ofproto/tunnel.c
ofproto/tunnel.h

index 123f3b2e235ded8cdf5ba0f9de6cd473ee42a0d2..ba87835b24c46015d736f75d0ecbf9d471511713 100644 (file)
@@ -245,41 +245,83 @@ 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,
-                 unsigned int *hlen)
+eth_build_header(struct ovs_action_push_tnl *data,
+                 const struct netdev_tnl_build_header_params *params)
 {
-    struct ip_header *ip;
-    struct ovs_16aligned_ip6_hdr *ip6;
-    struct udp_header *udp;
-    bool is_ipv6;
+    uint16_t eth_proto = params->is_ipv6 ? ETH_TYPE_IPV6 : ETH_TYPE_IP;
+    struct eth_header *eth;
 
-    *hlen = sizeof(struct eth_header);
+    memset(data->header, 0, sizeof data->header);
 
-    is_ipv6 = netdev_tnl_is_header_ipv6(data->header);
+    eth = (struct eth_header *)data->header;
+    eth->eth_dst = params->dmac;
+    eth->eth_src = params->smac;
+    eth->eth_type = htons(eth_proto);
+    data->header_len = sizeof(struct eth_header);
+    return eth + 1;
+}
 
-    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;
+void *
+netdev_tnl_ip_build_header(struct ovs_action_push_tnl *data,
+                           const struct netdev_tnl_build_header_params *params,
+                           uint8_t next_proto)
+{
+    void *l3;
+
+    l3 = eth_build_header(data, params);
+    if (!params->is_ipv6) {
+        ovs_be32 ip_src = in6_addr_get_mapped_ipv4(params->s_ip);
+        struct ip_header *ip;
+
+        ip = (struct ip_header *) l3;
+
+        ip->ip_ihl_ver = IP_IHL_VER(5, 4);
+        ip->ip_tos = params->flow->tunnel.ip_tos;
+        ip->ip_ttl = params->flow->tunnel.ip_ttl;
+        ip->ip_proto = next_proto;
+        put_16aligned_be32(&ip->ip_src, ip_src);
+        put_16aligned_be32(&ip->ip_dst, params->flow->tunnel.ip_dst);
+
+        ip->ip_frag_off = (params->flow->tunnel.flags & FLOW_TNL_F_DONT_FRAGMENT) ?
+                          htons(IP_DF) : 0;
+
+        ip->ip_csum = csum(ip, sizeof *ip);
+
+        data->header_len += IP_HEADER_LEN;
+        return ip + 1;
     } else {
-        ip = netdev_tnl_ip_hdr(data->header);
-        ip->ip_proto = IPPROTO_UDP;
-        udp = (struct udp_header *) (ip + 1);
-        *hlen += IP_HEADER_LEN;
+        struct ovs_16aligned_ip6_hdr *ip6;
+
+        ip6 = (struct ovs_16aligned_ip6_hdr *) l3;
+
+        ip6->ip6_vfc = 0x60;
+        ip6->ip6_hlim = params->flow->tunnel.ip_ttl;
+        ip6->ip6_nxt = next_proto;
+        memcpy(&ip6->ip6_src, params->s_ip, sizeof(ovs_be32[4]));
+        memcpy(&ip6->ip6_dst, &params->flow->tunnel.ipv6_dst, sizeof(ovs_be32[4]));
+
+        data->header_len += IPV6_HEADER_LEN;
+        return ip6 + 1;
     }
+}
+
+static void *
+udp_build_header(struct netdev_tunnel_config *tnl_cfg,
+                 struct ovs_action_push_tnl *data,
+                 const struct netdev_tnl_build_header_params *params)
+{
+    struct udp_header *udp;
 
+    udp = netdev_tnl_ip_build_header(data, params, IPPROTO_UDP);
     udp->udp_dst = tnl_cfg->dst_port;
 
-    if (is_ipv6 || tnl_flow->tunnel.flags & FLOW_TNL_F_CSUM) {
+    if (params->is_ipv6 || params->flow->tunnel.flags & FLOW_TNL_F_CSUM) {
         /* Write a value in now to mark that we should compute the checksum
          * later. 0xffff is handy because it is transparent to the
          * calculation. */
         udp->udp_csum = htons(0xffff);
     }
-
+    data->header_len += sizeof *udp;
     return udp + 1;
 }
 
@@ -400,38 +442,25 @@ 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 netdev_tnl_build_header_params *params)
 {
     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;
-    bool is_ipv6;
-
-    is_ipv6 = netdev_tnl_is_header_ipv6(data->header);
+    unsigned int hlen;
 
     /* 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, params, IPPROTO_GRE);
 
     greh->protocol = htons(ETH_TYPE_TEB);
     greh->flags = 0;
 
     options = (ovs_16aligned_be32 *) (greh + 1);
-    if (tnl_flow->tunnel.flags & FLOW_TNL_F_CSUM) {
+    if (params->flow->tunnel.flags & FLOW_TNL_F_CSUM) {
         greh->flags |= htons(GRE_CSUM);
         put_16aligned_be32(options, 0);
         options++;
@@ -440,7 +469,7 @@ netdev_gre_build_header(const struct netdev *netdev,
     if (tnl_cfg->out_key_present) {
         greh->flags |= htons(GRE_KEY);
         put_16aligned_be32(options, (OVS_FORCE ovs_be32)
-                                    ((OVS_FORCE uint64_t) tnl_flow->tunnel.tun_id >> 32));
+                                    ((OVS_FORCE uint64_t) params->flow->tunnel.tun_id >> 32));
         options++;
     }
 
@@ -448,8 +477,7 @@ netdev_gre_build_header(const struct netdev *netdev,
 
     hlen = (uint8_t *) options - (uint8_t *) greh;
 
-    data->header_len = sizeof(struct eth_header) + hlen +
-                       (is_ipv6 ? IPV6_HEADER_LEN : IP_HEADER_LEN);
+    data->header_len += hlen;
     data->tnl_type = OVS_VPORT_TYPE_GRE;
     return 0;
 }
@@ -493,24 +521,23 @@ err:
 int
 netdev_vxlan_build_header(const struct netdev *netdev,
                           struct ovs_action_push_tnl *data,
-                          const struct flow *tnl_flow)
+                          const struct netdev_tnl_build_header_params *params)
 {
     struct netdev_vport *dev = netdev_vport_cast(netdev);
     struct netdev_tunnel_config *tnl_cfg;
     struct vxlanhdr *vxh;
-    unsigned int hlen;
 
     /* XXX: RCUfy tnl_cfg. */
     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, data, params);
 
     put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
-    put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8));
+    put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8));
 
     ovs_mutex_unlock(&dev->mutex);
-    data->header_len = hlen + VXLAN_HLEN;
+    data->header_len += sizeof *vxh;
     data->tnl_type = OVS_VPORT_TYPE_VXLAN;
     return 0;
 }
@@ -573,34 +600,33 @@ err:
 int
 netdev_geneve_build_header(const struct netdev *netdev,
                            struct ovs_action_push_tnl *data,
-                           const struct flow *tnl_flow)
+                           const struct netdev_tnl_build_header_params *params)
 {
     struct netdev_vport *dev = netdev_vport_cast(netdev);
     struct netdev_tunnel_config *tnl_cfg;
     struct genevehdr *gnh;
     int opt_len;
     bool crit_opt;
-    unsigned int hlen;
 
     /* XXX: RCUfy tnl_cfg. */
     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, data, params);
 
-    put_16aligned_be32(&gnh->vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8));
+    put_16aligned_be32(&gnh->vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8));
 
     ovs_mutex_unlock(&dev->mutex);
 
-    opt_len = tun_metadata_to_geneve_header(&tnl_flow->tunnel,
+    opt_len = tun_metadata_to_geneve_header(&params->flow->tunnel,
                                             gnh->options, &crit_opt);
 
     gnh->opt_len = opt_len / 4;
-    gnh->oam = !!(tnl_flow->tunnel.flags & FLOW_TNL_F_OAM);
+    gnh->oam = !!(params->flow->tunnel.flags & FLOW_TNL_F_OAM);
     gnh->critical = crit_opt ? 1 : 0;
     gnh->proto_type = htons(ETH_TYPE_TEB);
 
-    data->header_len = hlen + GENEVE_BASE_HLEN + opt_len;
+    data->header_len += sizeof *gnh + opt_len;
     data->tnl_type = OVS_VPORT_TYPE_GENEVE;
     return 0;
 }
index e0d15fc44cd3e48cc23948bd9a0097e35957d3c2..ed81857caf0030298b35c116fb66663fdde4f12d 100644 (file)
@@ -25,7 +25,8 @@
 int
 netdev_gre_build_header(const struct netdev *netdev,
                         struct ovs_action_push_tnl *data,
-                        const struct flow *tnl_flow);
+                        const struct netdev_tnl_build_header_params *params);
+
 void
 netdev_gre_push_header(struct dp_packet *packet,
                        const struct ovs_action_push_tnl *data);
@@ -38,14 +39,16 @@ 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 netdev_tnl_build_header_params *params);
+
 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 netdev_tnl_build_header_params *params);
+
 struct dp_packet *
 netdev_vxlan_pop_header(struct dp_packet *packet);
 
@@ -69,6 +72,11 @@ 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 netdev_tnl_build_header_params *params,
+                           uint8_t next_proto);
+
 extern uint16_t tnl_udp_port_min;
 extern uint16_t tnl_udp_port_max;
 
index be12e7cd70d4112e1da2ec30ddf3754bd58da79a..5da377f99991295b0848f8a95df4aa7f2681419b 100644 (file)
@@ -32,6 +32,7 @@
 extern "C" {
 #endif
 
+struct netdev_tnl_build_header_params;
 #define NETDEV_NUMA_UNSPEC OVS_NUMA_UNSPEC
 
 /* A network device (e.g. an Ethernet device).
@@ -276,10 +277,10 @@ 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 netdev_tnl_build_header_params *params);
 
     /* build_header() can not build entire header for all packets for given
      * flow.  Push header is called for packet to build header specific to
index 24e0f18f7564a93fc391a61d18348e930b8f8232..4be806d186c478c7774fa154892edab498514d41 100644 (file)
@@ -741,12 +741,26 @@ 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)
+void
+netdev_init_tnl_build_header_params(struct netdev_tnl_build_header_params *params,
+                                    const struct flow *tnl_flow,
+                                    const struct in6_addr *src,
+                                    struct eth_addr dmac,
+                                    struct eth_addr smac)
+{
+    params->flow = tnl_flow;
+    params->dmac = dmac;
+    params->smac = smac;
+    params->s_ip = src;
+    params->is_ipv6 = !IN6_IS_ADDR_V4MAPPED(src);
+}
+
+int netdev_build_header(const struct netdev *netdev,
+                        struct ovs_action_push_tnl *data,
+                        const struct netdev_tnl_build_header_params *params)
 {
     if (netdev->netdev_class->build_header) {
-        return netdev->netdev_class->build_header(netdev, data, tnl_flow);
+        return netdev->netdev_class->build_header(netdev, data, params);
     }
     return EOPNOTSUPP;
 }
index 6d6e4aba66489d3c5dd8c223d4e63532dbae0c21..cdefcd532b92b8d1a28be43a915828d1c06fe9a8 100644 (file)
@@ -152,8 +152,26 @@ int netdev_send(struct netdev *, int qid, struct dp_packet_batch *,
                 bool may_steal);
 void netdev_send_wait(struct netdev *, int qid);
 
+/* native tunnel APIs */
+/* Structure to pass parameters required to build a tunnel header. */
+struct netdev_tnl_build_header_params {
+    const struct flow *flow;
+    const struct in6_addr *s_ip;
+    struct eth_addr dmac;
+    struct eth_addr smac;
+    bool is_ipv6;
+};
+
+void
+netdev_init_tnl_build_header_params(struct netdev_tnl_build_header_params *params,
+                                    const struct flow *tnl_flow,
+                                    const struct in6_addr *src,
+                                    struct eth_addr dmac,
+                                    struct eth_addr smac);
+
 int netdev_build_header(const struct netdev *, struct ovs_action_push_tnl *data,
-                        const struct flow *tnl_flow);
+                        const struct netdev_tnl_build_header_params *params);
+
 int netdev_push_header(const struct netdev *netdev,
                        struct dp_packet_batch *,
                        const struct ovs_action_push_tnl *data);
index 9aa69ac2e0df0921b6a410cbe1fd72364c72e615..af26c64fcc399c666c8059886c4a6e17bec6dd9c 100644 (file)
@@ -2882,6 +2882,7 @@ static int
 build_tunnel_send(struct xlate_ctx *ctx, const struct xport *xport,
                   const struct flow *flow, odp_port_t tunnel_odp_port)
 {
+    struct netdev_tnl_build_header_params tnl_params;
     struct ovs_action_push_tnl tnl_push_data;
     struct xport *out_dev = NULL;
     ovs_be32 s_ip = 0, d_ip = 0;
@@ -2942,8 +2943,8 @@ build_tunnel_send(struct xlate_ctx *ctx, const struct xport *xport,
                  ETH_ADDR_ARGS(smac), ipv6_string_mapped(buf_sip6, &s_ip6),
                  ETH_ADDR_ARGS(dmac), buf_dip6);
 
-    err = tnl_port_build_header(xport->ofport, flow,
-                                dmac, smac, &s_ip6, &tnl_push_data);
+    netdev_init_tnl_build_header_params(&tnl_params, flow, &s_ip6, dmac, smac);
+    err = tnl_port_build_header(xport->ofport, &tnl_push_data, &tnl_params);
     if (err) {
         return err;
     }
index cc04ca5c3eece0f71721b5ed08b19009ffa7707e..9695c54e08e8601b4bb2158728df28aa6833414c 100644 (file)
@@ -690,65 +690,16 @@ tnl_port_get_name(const struct tnl_port *tnl_port) OVS_REQ_RDLOCK(rwlock)
 
 int
 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,
-                      struct ovs_action_push_tnl *data)
+                      struct ovs_action_push_tnl *data,
+                      const struct netdev_tnl_build_header_params *params)
 {
     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, params);
     fat_rwlock_unlock(&rwlock);
 
     return res;
index 1f3dfc23d878c54a734f8f18fec5f5ddaa382f39..b0ec67c2bd746a73ebc07b89b58b0dbbbb0aa658 100644 (file)
@@ -28,6 +28,7 @@
 struct ovs_action_push_tnl;
 struct ofport_dpif;
 struct netdev;
+struct netdev_tnl_build_header_params;
 
 void ofproto_tunnel_init(void);
 bool tnl_port_reconfigure(const struct ofport_dpif *, const struct netdev *,
@@ -50,11 +51,9 @@ tnl_port_should_receive(const struct flow *flow)
     return flow_tnl_dst_is_set(&flow->tunnel);
 }
 
-int 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,
-                          struct ovs_action_push_tnl *data);
+int
+tnl_port_build_header(const struct ofport_dpif *ofport,
+                      struct ovs_action_push_tnl *data,
+                      const struct netdev_tnl_build_header_params *params);
 
 #endif /* tunnel.h */