From c135bba1a9b83fcc32a48bab3039b9626c51c03e Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Tue, 29 Jul 2014 15:25:02 -0700 Subject: [PATCH] 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 --- datapath/actions.c | 3 +- datapath/datapath.c | 10 ++--- datapath/flow.c | 82 ++++++++++++++++++++++++++--------------- datapath/flow.h | 6 ++- datapath/flow_netlink.c | 31 +++++++--------- datapath/flow_netlink.h | 4 +- 6 files changed, 78 insertions(+), 58 deletions(-) diff --git a/datapath/actions.c b/datapath/actions.c index 792c3a9f7..5a0bfa9d3 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -649,11 +649,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 1185f6067..91c65a0d8 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -300,7 +300,7 @@ void ovs_dp_process_received_packet(struct sk_buff *skb) struct sw_flow_key key; /* Extract flow from 'skb' into 'key'. */ - error = ovs_flow_extract(skb, OVS_CB(skb)->input_vport->port_no, &key); + error = ovs_flow_key_extract(skb, &key); if (unlikely(error)) { kfree_skb(skb); return; @@ -354,7 +354,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, return PTR_ERR(segs); if (gso_type & SKB_GSO_UDP) { - /* The initial flow key extracted by ovs_flow_extract() + /* The initial flow key extracted by ovs_flow_key_extract() * in this case is for a first fragment, so we need to * properly mark later fragments. */ @@ -581,13 +581,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 e23479681..7fdce6af5 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 "mpls.h" #include "vlan.h" @@ -425,10 +427,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. @@ -447,35 +448,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; - if (OVS_CB(skb)->tun_info) { - struct ovs_tunnel_info *tun_info = OVS_CB(skb)->tun_info; - memcpy(&key->tun_key, &tun_info->tunnel, - sizeof(key->tun_key)); - if (tun_info->options) { - BUILD_BUG_ON((1 << (sizeof(tun_info->options_len) * 8)) - 1 - > sizeof(key->tun_opts)); - memcpy(GENEVE_OPTS(key, tun_info->options_len), - tun_info->options, tun_info->options_len); - key->tun_opts_len = tun_info->options_len; - } else { - key->tun_opts_len = 0; - } - } else { - key->tun_opts_len = 0; - memset(&key->tun_key, 0, sizeof(key->tun_key)); - } - - key->phy.priority = skb->priority; - key->phy.in_port = in_port; - key->phy.skb_mark = skb->mark; - key->ovs_flow_hash = 0; - key->recirc_id = 0; - /* Flags are always used as part of stats. */ key->tp.flags = 0; @@ -694,3 +671,50 @@ 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. */ + + if (OVS_CB(skb)->tun_info) { + struct ovs_tunnel_info *tun_info = OVS_CB(skb)->tun_info; + + memcpy(&key->tun_key, &tun_info->tunnel, sizeof(key->tun_key)); + + BUILD_BUG_ON(((1 << (sizeof(tun_info->options_len) * 8)) - 1) > + sizeof(key->tun_opts)); + + if (tun_info->options) { + memcpy(GENEVE_OPTS(key, tun_info->options_len), + tun_info->options, tun_info->options_len); + key->tun_opts_len = tun_info->options_len; + } else { + key->tun_opts_len = 0; + } + } else { + key->tun_opts_len = 0; + memset(&key->tun_key, 0, 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; + key->ovs_flow_hash = 0; + key->recirc_id = 0; + + 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; + + /* 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 f6afa482f..69664cd94 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -217,6 +217,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 37646e4d2..ada21aece 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -992,7 +992,7 @@ free_newmask: /** * 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. * @@ -1001,35 +1001,30 @@ free_newmask: * 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; + key->tun_opts_len = 0; + memset(&key->tun_key, 0, sizeof(key->tun_key)); + key->phy.priority = 0; + key->phy.skb_mark = 0; + key->phy.in_port = DP_MAX_PORTS; + key->ovs_flow_hash = 0; + key->recirc_id = 0; - return 0; + return metadata_from_nlattrs(&match, &attrs, a, false); } int ovs_nla_put_flow(struct datapath *dp, const struct sw_flow_key *swkey, diff --git a/datapath/flow_netlink.h b/datapath/flow_netlink.h index 0c20e8640..16da26418 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(struct datapath *dp, 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 *); -- 2.20.1