[ovs-dev] [PATCH] datapath: refactor ovs flow extract API.

Andy Zhou azhou at nicira.com
Tue Aug 5 19:32:56 UTC 2014


The refactor is pretty nice in general. I wonder if the new public
ovs_flow_extrac_ APIs can actually reflect the intended use case as
highlighted in the commit message.

Also, It may be nice to separate out the ovs_flow_extract__ use cases
for recirc.

Andy


On Tue, Jul 29, 2014 at 3:25 PM, Pravin B Shelar <pshelar at nicira.com> wrote:
> OVS flow extract is called on packet receive or packet
> execute code path.  Following patch defines separate API
> for these two cases to simplify code.
>
> Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
> ---
>  datapath/actions.c      |  3 +-
>  datapath/datapath.c     |  8 ++---
>  datapath/flow.c         | 82 ++++++++++++++++++++++++++++++++-----------------
>  datapath/flow.h         |  4 ++-
>  datapath/flow_netlink.c | 31 ++++++++-----------
>  datapath/flow_netlink.h |  4 +--
>  6 files changed, 75 insertions(+), 57 deletions(-)
>
> diff --git a/datapath/actions.c b/datapath/actions.c
> index 792c3a9..65b4892 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_extract(skb, &recirc_key);
>         if (err) {
>                 kfree_skb(skb);
>                 return err;
> diff --git a/datapath/datapath.c b/datapath/datapath.c
> index 1185f60..7d4b599 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_extract(skb, &key);
>         if (unlikely(error)) {
>                 kfree_skb(skb);
>                 return;
> @@ -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_extract_nla_metadata(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 e234796..89f4d05 100644
> --- a/datapath/flow.c
> +++ b/datapath/flow.c
> @@ -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>
> @@ -45,6 +43,10 @@
>  #include <net/ipv6.h>
>  #include <net/ndisc.h>
>
> +#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.
> + * flow_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 flow_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_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 flow_extract(skb, key);
> +}
> +
> +int ovs_flow_extract_nla_metadata(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 flow_extract(skb, key);
> +}
> diff --git a/datapath/flow.h b/datapath/flow.h
> index f6afa48..5cacc9e 100644
> --- a/datapath/flow.h
> +++ b/datapath/flow.h
> @@ -217,6 +217,8 @@ 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_extract(struct sk_buff *skb, struct sw_flow_key *key);
> +int ovs_flow_extract_nla_metadata(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 e1eadbb..a996e52 100644
> --- a/datapath/flow_netlink.c
> +++ b/datapath/flow_netlink.c
> @@ -991,7 +991,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.
>   *
> @@ -1000,35 +1000,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 0c20e86..16da264 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 *);
> --
> 1.9.3
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev



More information about the dev mailing list