openvswitch: Wrap struct ovs_key_ipv4_tunnel in a new structure.
authorJesse Gross <jesse@nicira.com>
Fri, 3 Oct 2014 22:35:31 +0000 (15:35 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 6 Oct 2014 04:32:20 +0000 (00:32 -0400)
Currently, the flow information that is matched for tunnels and
the tunnel data passed around with packets is the same. However,
as additional information is added this is not necessarily desirable,
as in the case of pointers.

This adds a new structure for tunnel metadata which currently contains
only the existing struct. This change is purely internal to the kernel
since the current OVS_KEY_ATTR_IPV4_TUNNEL is simply a compressed version
of OVS_KEY_ATTR_TUNNEL that is translated at flow setup.

Signed-off-by: Jesse Gross <jesse@nicira.com>
Signed-off-by: Andy Zhou <azhou@nicira.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/openvswitch.h
net/openvswitch/actions.c
net/openvswitch/datapath.h
net/openvswitch/flow.c
net/openvswitch/flow.h
net/openvswitch/flow_netlink.c
net/openvswitch/vport-gre.c
net/openvswitch/vport-vxlan.c
net/openvswitch/vport.c
net/openvswitch/vport.h

index 7c06106f5af5e064d1387112155db506eb96ae65..6753032832e253baa66a81d27a1fd783dc392776 100644 (file)
@@ -294,7 +294,7 @@ enum ovs_key_attr {
        OVS_KEY_ATTR_RECIRC_ID, /* u32 recirc id */
 
 #ifdef __KERNEL__
-       OVS_KEY_ATTR_IPV4_TUNNEL,  /* struct ovs_key_ipv4_tunnel */
+       OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ovs_tunnel_info */
 #endif
        __OVS_KEY_ATTR_MAX
 };
index 6932a42e41a29712610d4138df91b765e3184e58..006886dbee36b075fc7054ec1ddc87781a75d739 100644 (file)
@@ -590,8 +590,8 @@ static int execute_set_action(struct sk_buff *skb,
                skb->mark = nla_get_u32(nested_attr);
                break;
 
-       case OVS_KEY_ATTR_IPV4_TUNNEL:
-               OVS_CB(skb)->egress_tun_key = nla_data(nested_attr);
+       case OVS_KEY_ATTR_TUNNEL_INFO:
+               OVS_CB(skb)->egress_tun_info = nla_data(nested_attr);
                break;
 
        case OVS_KEY_ATTR_ETHERNET:
@@ -778,6 +778,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
        acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
 
        this_cpu_inc(exec_actions_level);
+       OVS_CB(skb)->egress_tun_info = NULL;
        err = do_execute_actions(dp, skb, key,
                                 acts->actions, acts->actions_len);
 
index ac3f3df96961f9d4956db5f8fa9d54d41b4f3b3b..974135439c5c77af2e7ee0684054589e1a81779c 100644 (file)
@@ -102,8 +102,8 @@ struct datapath {
  */
 struct ovs_skb_cb {
        struct sw_flow          *flow;
+       struct ovs_tunnel_info  *egress_tun_info;
        struct vport            *input_vport;
-       struct ovs_key_ipv4_tunnel  *egress_tun_key;
 };
 #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
 
index 913bdc1a83c06d283089037570179ed0380e516f..2924cb34086821fc9df3d8a9afd199d55b67e864 100644 (file)
@@ -642,12 +642,12 @@ int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
        return key_extract(skb, key);
 }
 
-int ovs_flow_key_extract(struct ovs_key_ipv4_tunnel *tun_key,
+int ovs_flow_key_extract(struct ovs_tunnel_info *tun_info,
                         struct sk_buff *skb, struct sw_flow_key *key)
 {
        /* Extract metadata from packet. */
-       if (tun_key)
-               memcpy(&key->tun_key, tun_key, sizeof(key->tun_key));
+       if (tun_info)
+               memcpy(&key->tun_key, &tun_info->tunnel, sizeof(key->tun_key));
        else
                memset(&key->tun_key, 0, sizeof(key->tun_key));
 
index 0f5db4ec565d00b3c25e2c0a1a17e1d200ed33d1..fe5a71b81c1fdbc723c3b2fc7105b1052f88d9a3 100644 (file)
@@ -49,20 +49,24 @@ struct ovs_key_ipv4_tunnel {
        u8   ipv4_ttl;
 } __packed __aligned(4); /* Minimize padding. */
 
-static inline void ovs_flow_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,
-                                        const struct iphdr *iph, __be64 tun_id,
-                                        __be16 tun_flags)
+struct ovs_tunnel_info {
+       struct ovs_key_ipv4_tunnel tunnel;
+};
+
+static inline void ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
+                                         const struct iphdr *iph,
+                                         __be64 tun_id, __be16 tun_flags)
 {
-       tun_key->tun_id = tun_id;
-       tun_key->ipv4_src = iph->saddr;
-       tun_key->ipv4_dst = iph->daddr;
-       tun_key->ipv4_tos = iph->tos;
-       tun_key->ipv4_ttl = iph->ttl;
-       tun_key->tun_flags = tun_flags;
+       tun_info->tunnel.tun_id = tun_id;
+       tun_info->tunnel.ipv4_src = iph->saddr;
+       tun_info->tunnel.ipv4_dst = iph->daddr;
+       tun_info->tunnel.ipv4_tos = iph->tos;
+       tun_info->tunnel.ipv4_ttl = iph->ttl;
+       tun_info->tunnel.tun_flags = tun_flags;
 
        /* clear struct padding. */
-       memset((unsigned char *) tun_key + OVS_TUNNEL_KEY_SIZE, 0,
-              sizeof(*tun_key) - OVS_TUNNEL_KEY_SIZE);
+       memset((unsigned char *)&tun_info->tunnel + OVS_TUNNEL_KEY_SIZE, 0,
+              sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);
 }
 
 struct sw_flow_key {
@@ -190,8 +194,8 @@ void ovs_flow_stats_clear(struct sw_flow *);
 u64 ovs_flow_used_time(unsigned long flow_jiffies);
 
 int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
-int ovs_flow_key_extract(struct ovs_key_ipv4_tunnel *tun_key,
-                        struct sk_buff *skb, struct sw_flow_key *key);
+int ovs_flow_key_extract(struct ovs_tunnel_info *tun_info, struct sk_buff *skb,
+                        struct sw_flow_key *key);
 /* Extract key from packet coming from userspace. */
 int ovs_flow_key_extract_userspace(const struct nlattr *attr,
                                   struct sk_buff *skb,
index 22c855fa0bc2c4c30833c95b866595eb8d06f049..5d6194d9dadc79a979aab988a1839450ba5783d4 100644 (file)
@@ -1148,13 +1148,14 @@ out:
        return  (struct nlattr *) ((unsigned char *)(*sfa) + next_offset);
 }
 
-static int add_action(struct sw_flow_actions **sfa, int attrtype, void *data, int len)
+static struct nlattr *__add_action(struct sw_flow_actions **sfa,
+                                  int attrtype, void *data, int len)
 {
        struct nlattr *a;
 
        a = reserve_sfa_size(sfa, nla_attr_size(len));
        if (IS_ERR(a))
-               return PTR_ERR(a);
+               return a;
 
        a->nla_type = attrtype;
        a->nla_len = nla_attr_size(len);
@@ -1163,6 +1164,18 @@ static int add_action(struct sw_flow_actions **sfa, int attrtype, void *data, in
                memcpy(nla_data(a), data, len);
        memset((unsigned char *) a + a->nla_len, 0, nla_padlen(len));
 
+       return a;
+}
+
+static int add_action(struct sw_flow_actions **sfa, int attrtype,
+                     void *data, int len)
+{
+       struct nlattr *a;
+
+       a = __add_action(sfa, attrtype, data, len);
+       if (IS_ERR(a))
+               return PTR_ERR(a);
+
        return 0;
 }
 
@@ -1268,6 +1281,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
 {
        struct sw_flow_match match;
        struct sw_flow_key key;
+       struct ovs_tunnel_info *tun_info;
+       struct nlattr *a;
        int err, start;
 
        ovs_match_init(&match, &key, NULL);
@@ -1279,8 +1294,14 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
        if (start < 0)
                return start;
 
-       err = add_action(sfa, OVS_KEY_ATTR_IPV4_TUNNEL, &match.key->tun_key,
-                       sizeof(match.key->tun_key));
+       a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
+                        sizeof(*tun_info));
+       if (IS_ERR(a))
+               return PTR_ERR(a);
+
+       tun_info = nla_data(a);
+       tun_info->tunnel = key.tun_key;
+
        add_nested_action_end(*sfa, start);
 
        return err;
@@ -1563,17 +1584,20 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
        int err;
 
        switch (key_type) {
-       case OVS_KEY_ATTR_IPV4_TUNNEL:
+       case OVS_KEY_ATTR_TUNNEL_INFO: {
+               struct ovs_tunnel_info *tun_info = nla_data(ovs_key);
+
                start = nla_nest_start(skb, OVS_ACTION_ATTR_SET);
                if (!start)
                        return -EMSGSIZE;
 
-               err = ipv4_tun_to_nlattr(skb, nla_data(ovs_key),
-                                            nla_data(ovs_key));
+               err = ipv4_tun_to_nlattr(skb, &tun_info->tunnel,
+                                        nla_data(ovs_key));
                if (err)
                        return err;
                nla_nest_end(skb, start);
                break;
+       }
        default:
                if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key))
                        return -EMSGSIZE;
index 309cca6e816f54791afc24470a9b6eb40a37dd69..fe768bd600eb5cf7a87f61f8277f5df02dfbe004 100644 (file)
@@ -63,8 +63,10 @@ static __be16 filter_tnl_flags(__be16 flags)
 static struct sk_buff *__build_header(struct sk_buff *skb,
                                      int tunnel_hlen)
 {
-       const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->egress_tun_key;
        struct tnl_ptk_info tpi;
+       const struct ovs_key_ipv4_tunnel *tun_key;
+
+       tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
 
        skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM));
        if (IS_ERR(skb))
@@ -92,7 +94,7 @@ static __be64 key_to_tunnel_id(__be32 key, __be32 seq)
 static int gre_rcv(struct sk_buff *skb,
                   const struct tnl_ptk_info *tpi)
 {
-       struct ovs_key_ipv4_tunnel tun_key;
+       struct ovs_tunnel_info tun_info;
        struct ovs_net *ovs_net;
        struct vport *vport;
        __be64 key;
@@ -103,10 +105,10 @@ static int gre_rcv(struct sk_buff *skb,
                return PACKET_REJECT;
 
        key = key_to_tunnel_id(tpi->key, tpi->seq);
-       ovs_flow_tun_key_init(&tun_key, ip_hdr(skb), key,
-                             filter_tnl_flags(tpi->flags));
+       ovs_flow_tun_info_init(&tun_info, ip_hdr(skb), key,
+                              filter_tnl_flags(tpi->flags));
 
-       ovs_vport_receive(vport, skb, &tun_key);
+       ovs_vport_receive(vport, skb, &tun_info);
        return PACKET_RCVD;
 }
 
@@ -137,12 +139,12 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
        __be16 df;
        int err;
 
-       if (unlikely(!OVS_CB(skb)->egress_tun_key)) {
+       if (unlikely(!OVS_CB(skb)->egress_tun_info)) {
                err = -EINVAL;
                goto error;
        }
 
-       tun_key = OVS_CB(skb)->egress_tun_key;
+       tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
        /* Route lookup */
        memset(&fl, 0, sizeof(fl));
        fl.daddr = tun_key->ipv4_dst;
index f19539bb8adcc299b55b5daf4f89c0b8004404e4..5fbff2c1ee49b382d7a385ee8c6da85c300183ee 100644 (file)
@@ -58,7 +58,7 @@ static inline struct vxlan_port *vxlan_vport(const struct vport *vport)
 /* Called with rcu_read_lock and BH disabled. */
 static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, __be32 vx_vni)
 {
-       struct ovs_key_ipv4_tunnel tun_key;
+       struct ovs_tunnel_info tun_info;
        struct vport *vport = vs->data;
        struct iphdr *iph;
        __be64 key;
@@ -66,9 +66,9 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, __be32 vx_vni)
        /* Save outer tunnel values */
        iph = ip_hdr(skb);
        key = cpu_to_be64(ntohl(vx_vni) >> 8);
-       ovs_flow_tun_key_init(&tun_key, iph, key, TUNNEL_KEY);
+       ovs_flow_tun_info_init(&tun_info, iph, key, TUNNEL_KEY);
 
-       ovs_vport_receive(vport, skb, &tun_key);
+       ovs_vport_receive(vport, skb, &tun_info);
 }
 
 static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb)
@@ -147,12 +147,12 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
        __be16 df;
        int err;
 
-       if (unlikely(!OVS_CB(skb)->egress_tun_key)) {
+       if (unlikely(!OVS_CB(skb)->egress_tun_info)) {
                err = -EINVAL;
                goto error;
        }
 
-       tun_key = OVS_CB(skb)->egress_tun_key;
+       tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
        /* Route lookup */
        memset(&fl, 0, sizeof(fl));
        fl.daddr = tun_key->ipv4_dst;
index 5df8377fcfb1d59a721fbecbed70f2313cafe8cf..3e50ee8a218c400cf90dfc50c62fc35634992a6c 100644 (file)
@@ -432,7 +432,7 @@ u32 ovs_vport_find_upcall_portid(const struct vport *p, struct sk_buff *skb)
  * skb->data should point to the Ethernet header.
  */
 void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
-                      struct ovs_key_ipv4_tunnel *tun_key)
+                      struct ovs_tunnel_info *tun_info)
 {
        struct pcpu_sw_netstats *stats;
        struct sw_flow_key key;
@@ -445,9 +445,9 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
        u64_stats_update_end(&stats->syncp);
 
        OVS_CB(skb)->input_vport = vport;
-       OVS_CB(skb)->egress_tun_key = NULL;
+       OVS_CB(skb)->egress_tun_info = NULL;
        /* Extract flow from 'skb' into 'key'. */
-       error = ovs_flow_key_extract(tun_key, skb, &key);
+       error = ovs_flow_key_extract(tun_info, skb, &key);
        if (unlikely(error)) {
                kfree_skb(skb);
                return;
index 0efd62fef1e81ca4d0ae472a0e737e8b0f1b6652..e28964aba02178a28e6901d4e876e566625a03a7 100644 (file)
@@ -207,7 +207,7 @@ static inline struct vport *vport_from_priv(void *priv)
 }
 
 void ovs_vport_receive(struct vport *, struct sk_buff *,
-                      struct ovs_key_ipv4_tunnel *);
+                      struct ovs_tunnel_info *);
 
 /* List of statically compiled vport implementations.  Don't forget to also
  * add yours to the list at the top of vport.c. */