datapath: refactor ovs flow extract API.
authorPravin B Shelar <pshelar@nicira.com>
Wed, 13 Aug 2014 23:06:47 +0000 (16:06 -0700)
committerPravin B Shelar <pshelar@nicira.com>
Thu, 14 Aug 2014 19:22:10 +0000 (12:22 -0700)
OVS flow extract is called on packet receive or packet
execute code path.  Following patch defines separate API
for extracting flow-key in packet execute code path.

Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Andy Zhou <azhou@nicira.com>
datapath/actions.c
datapath/datapath.c
datapath/flow.c
datapath/flow.h
datapath/flow_netlink.c
datapath/flow_netlink.h

index 1583a95..263bd55 100644 (file)
@@ -554,11 +554,10 @@ static int execute_recirc(struct datapath *dp, struct sk_buff *skb,
                                 const struct nlattr *a)
 {
        struct sw_flow_key recirc_key;
-       const struct vport *p = OVS_CB(skb)->input_vport;
        uint32_t hash = OVS_CB(skb)->pkt_key->ovs_flow_hash;
        int err;
 
-       err = ovs_flow_extract(skb, p->port_no, &recirc_key);
+       err = ovs_flow_key_extract(skb, &recirc_key);
        if (err) {
                kfree_skb(skb);
                return err;
index e3ecb54..481b923 100644 (file)
@@ -293,7 +293,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
        OVS_CB(skb)->input_vport = p;
 
        /* Extract flow from 'skb' into 'key'. */
-       error = ovs_flow_extract(skb, p->port_no, &key);
+       error = ovs_flow_key_extract(skb, &key);
        if (unlikely(error)) {
                kfree_skb(skb);
                return;
@@ -570,13 +570,11 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
        if (IS_ERR(flow))
                goto err_kfree_skb;
 
-       err = ovs_flow_extract(packet, -1, &flow->key);
+       err = ovs_flow_key_extract_userspace(a[OVS_PACKET_ATTR_KEY], packet,
+                                            &flow->key);
        if (err)
                goto err_flow_free;
 
-       err = ovs_nla_get_flow_metadata(flow, a[OVS_PACKET_ATTR_KEY]);
-       if (err)
-               goto err_flow_free;
        acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_PACKET_ATTR_ACTIONS]));
        err = PTR_ERR(acts);
        if (IS_ERR(acts))
index c52081b..5fa3491 100644 (file)
@@ -16,8 +16,6 @@
  * 02110-1301, USA
  */
 
-#include "flow.h"
-#include "datapath.h"
 #include <linux/uaccess.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <net/ipv6.h>
 #include <net/ndisc.h>
 
+#include "datapath.h"
+#include "flow.h"
+#include "flow_netlink.h"
+
 #include "vlan.h"
 
 u64 ovs_flow_used_time(unsigned long flow_jiffies)
@@ -421,10 +423,9 @@ invalid:
 }
 
 /**
- * ovs_flow_extract - extracts a flow key from an Ethernet frame.
+ * key_extract - extracts a flow key from an Ethernet frame.
  * @skb: sk_buff that contains the frame, with skb->data pointing to the
  * Ethernet header
- * @in_port: port number on which @skb was received.
  * @key: output flow key
  *
  * The caller must ensure that skb->len >= ETH_HLEN.
@@ -443,19 +444,11 @@ invalid:
  *      of a correct length, otherwise the same as skb->network_header.
  *      For other key->eth.type values it is left untouched.
  */
-int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
+static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
 {
        int error;
        struct ethhdr *eth;
 
-       memset(key, 0, sizeof(*key));
-
-       key->phy.priority = skb->priority;
-       if (OVS_CB(skb)->tun_key)
-               memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
-       key->phy.in_port = in_port;
-       key->phy.skb_mark = skb->mark;
-
        skb_reset_mac_header(skb);
 
        /* Link layer.  We are guaranteed to have at least the 14 byte Ethernet
@@ -613,3 +606,33 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
 
        return 0;
 }
+
+int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+{
+       /* Extract metadata from packet. */
+
+       memset(key, 0, sizeof(*key));
+       if (OVS_CB(skb)->tun_key)
+               memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
+
+       key->phy.priority = skb->priority;
+       key->phy.in_port = OVS_CB(skb)->input_vport->port_no;
+       key->phy.skb_mark = skb->mark;
+
+       return key_extract(skb, key);
+}
+
+int ovs_flow_key_extract_userspace(const struct nlattr *attr,
+                                  struct sk_buff *skb,
+                                  struct sw_flow_key *key)
+{
+       int err;
+
+       memset(key, 0, sizeof(*key));
+       /* Extract metadata from netlink attributes. */
+       err = ovs_nla_get_flow_metadata(attr, key);
+       if (err)
+               return err;
+
+       return key_extract(skb, key);
+}
index 2018691..ffe2879 100644 (file)
@@ -190,6 +190,10 @@ void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
 void ovs_flow_stats_clear(struct sw_flow *);
 u64 ovs_flow_used_time(unsigned long flow_jiffies);
 
-int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *);
+int ovs_flow_key_extract(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,
+                                  struct sw_flow_key *key);
 
 #endif /* flow.h */
index 4b07d96..d0f1e90 100644 (file)
@@ -853,7 +853,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,
 
 /**
  * ovs_nla_get_flow_metadata - parses Netlink attributes into a flow key.
- * @flow: Receives extracted in_port, priority, tun_key and skb_mark.
+ * @key: Receives extracted in_port, priority, tun_key and skb_mark.
  * @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
  * sequence.
  *
@@ -862,35 +862,23 @@ int ovs_nla_get_match(struct sw_flow_match *match,
  * get the metadata, that is, the parts of the flow key that cannot be
  * extracted from the packet itself.
  */
-
-int ovs_nla_get_flow_metadata(struct sw_flow *flow,
-                             const struct nlattr *attr)
+int ovs_nla_get_flow_metadata(const struct nlattr *attr,
+                             struct sw_flow_key *key)
 {
-       struct ovs_key_ipv4_tunnel *tun_key = &flow->key.tun_key;
        const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
+       struct sw_flow_match match;
        u64 attrs = 0;
        int err;
-       struct sw_flow_match match;
-
-       flow->key.phy.in_port = DP_MAX_PORTS;
-       flow->key.phy.priority = 0;
-       flow->key.phy.skb_mark = 0;
-       flow->key.ovs_flow_hash = 0;
-       flow->key.recirc_id = 0;
-       memset(tun_key, 0, sizeof(flow->key.tun_key));
 
        err = parse_flow_nlattrs(attr, a, &attrs);
        if (err)
                return -EINVAL;
 
        memset(&match, 0, sizeof(match));
-       match.key = &flow->key;
+       match.key = key;
 
-       err = metadata_from_nlattrs(&match, &attrs, a, false);
-       if (err)
-               return err;
-
-       return 0;
+       key->phy.in_port = DP_MAX_PORTS;
+       return metadata_from_nlattrs(&match, &attrs, a, false);
 }
 
 int ovs_nla_put_flow(const struct sw_flow_key *swkey,
index 4401510..206e45a 100644 (file)
@@ -42,8 +42,8 @@ void ovs_match_init(struct sw_flow_match *match,
 
 int ovs_nla_put_flow(const struct sw_flow_key *,
                     const struct sw_flow_key *, struct sk_buff *);
-int ovs_nla_get_flow_metadata(struct sw_flow *flow,
-                             const struct nlattr *attr);
+int ovs_nla_get_flow_metadata(const struct nlattr *, struct sw_flow_key *);
+
 int ovs_nla_get_match(struct sw_flow_match *match,
                      const struct nlattr *,
                      const struct nlattr *);