From: Pravin B Shelar Date: Wed, 13 Aug 2014 23:06:47 +0000 (-0700) Subject: datapath: refactor ovs flow extract API. X-Git-Tag: v2.3.1~62 X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fovs.git;a=commitdiff_plain;h=e58ba93dfaa5455f667af4b99ee7f53b8520157c datapath: refactor ovs flow extract API. 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 Acked-by: Andy Zhou --- diff --git a/datapath/actions.c b/datapath/actions.c index 1583a9503..263bd55e4 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -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; diff --git a/datapath/datapath.c b/datapath/datapath.c index e3ecb5439..481b923e3 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -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)) diff --git a/datapath/flow.c b/datapath/flow.c index c52081b2f..5fa349195 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -16,8 +16,6 @@ * 02110-1301, USA */ -#include "flow.h" -#include "datapath.h" #include #include #include @@ -45,6 +43,10 @@ #include #include +#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); +} diff --git a/datapath/flow.h b/datapath/flow.h index 201869128..ffe287988 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -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 */ diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c index 4b07d9632..d0f1e90c3 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -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, diff --git a/datapath/flow_netlink.h b/datapath/flow_netlink.h index 440151045..206e45add 100644 --- a/datapath/flow_netlink.h +++ b/datapath/flow_netlink.h @@ -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 *);