Commit 83c8df26 authored by Pravin B Shelar's avatar Pravin B Shelar

openvswitch: 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: default avatarPravin B Shelar <pshelar@nicira.com>
Acked-by: default avatarAndy Zhou <azhou@nicira.com>
parent 2ff3e4e4
...@@ -237,8 +237,9 @@ void ovs_dp_detach_port(struct vport *p) ...@@ -237,8 +237,9 @@ void ovs_dp_detach_port(struct vport *p)
} }
/* Must be called with rcu_read_lock. */ /* Must be called with rcu_read_lock. */
void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) void ovs_dp_process_received_packet(struct sk_buff *skb)
{ {
const struct vport *p = OVS_CB(skb)->input_vport;
struct datapath *dp = p->dp; struct datapath *dp = p->dp;
struct sw_flow *flow; struct sw_flow *flow;
struct dp_stats_percpu *stats; struct dp_stats_percpu *stats;
...@@ -250,7 +251,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) ...@@ -250,7 +251,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
stats = this_cpu_ptr(dp->stats_percpu); stats = this_cpu_ptr(dp->stats_percpu);
/* Extract flow from 'skb' into 'key'. */ /* 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)) { if (unlikely(error)) {
kfree_skb(skb); kfree_skb(skb);
return; return;
...@@ -514,6 +515,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) ...@@ -514,6 +515,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
struct sw_flow *flow; struct sw_flow *flow;
struct datapath *dp; struct datapath *dp;
struct ethhdr *eth; struct ethhdr *eth;
struct vport *input_vport;
int len; int len;
int err; int err;
...@@ -548,13 +550,11 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) ...@@ -548,13 +550,11 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
if (IS_ERR(flow)) if (IS_ERR(flow))
goto err_kfree_skb; 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) if (err)
goto err_flow_free; 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])); acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_PACKET_ATTR_ACTIONS]));
err = PTR_ERR(acts); err = PTR_ERR(acts);
if (IS_ERR(acts)) if (IS_ERR(acts))
...@@ -576,6 +576,15 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) ...@@ -576,6 +576,15 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
if (!dp) if (!dp)
goto err_unlock; goto err_unlock;
input_vport = ovs_vport_rcu(dp, flow->key.phy.in_port);
if (!input_vport)
input_vport = ovs_vport_rcu(dp, OVSP_LOCAL);
if (!input_vport)
goto err_unlock;
OVS_CB(packet)->input_vport = input_vport;
local_bh_disable(); local_bh_disable();
err = ovs_execute_actions(dp, packet, &flow->key); err = ovs_execute_actions(dp, packet, &flow->key);
local_bh_enable(); local_bh_enable();
......
...@@ -97,10 +97,13 @@ struct datapath { ...@@ -97,10 +97,13 @@ struct datapath {
* @flow: The flow associated with this packet. May be %NULL if no flow. * @flow: The flow associated with this packet. May be %NULL if no flow.
* @tun_key: Key for the tunnel that encapsulated this packet. NULL if the * @tun_key: Key for the tunnel that encapsulated this packet. NULL if the
* packet is not being tunneled. * packet is not being tunneled.
* @input_vport: The original vport packet came in on. This value is cached
* when a packet is received by OVS.
*/ */
struct ovs_skb_cb { struct ovs_skb_cb {
struct sw_flow *flow; struct sw_flow *flow;
struct ovs_key_ipv4_tunnel *tun_key; struct ovs_key_ipv4_tunnel *tun_key;
struct vport *input_vport;
}; };
#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb) #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
...@@ -181,7 +184,7 @@ static inline struct vport *ovs_vport_ovsl(const struct datapath *dp, int port_n ...@@ -181,7 +184,7 @@ static inline struct vport *ovs_vport_ovsl(const struct datapath *dp, int port_n
extern struct notifier_block ovs_dp_device_notifier; extern struct notifier_block ovs_dp_device_notifier;
extern struct genl_family dp_vport_genl_family; extern struct genl_family dp_vport_genl_family;
void ovs_dp_process_received_packet(struct vport *, struct sk_buff *); void ovs_dp_process_received_packet(struct sk_buff *);
void ovs_dp_detach_port(struct vport *); void ovs_dp_detach_port(struct vport *);
int ovs_dp_upcall(struct datapath *, struct sk_buff *, int ovs_dp_upcall(struct datapath *, struct sk_buff *,
const struct dp_upcall_info *); const struct dp_upcall_info *);
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
* 02110-1301, USA * 02110-1301, USA
*/ */
#include "flow.h"
#include "datapath.h"
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
...@@ -46,6 +44,10 @@ ...@@ -46,6 +44,10 @@
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/ndisc.h> #include <net/ndisc.h>
#include "datapath.h"
#include "flow.h"
#include "flow_netlink.h"
u64 ovs_flow_used_time(unsigned long flow_jiffies) u64 ovs_flow_used_time(unsigned long flow_jiffies)
{ {
struct timespec cur_ts; struct timespec cur_ts;
...@@ -420,10 +422,9 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, ...@@ -420,10 +422,9 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
} }
/** /**
* 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 * @skb: sk_buff that contains the frame, with skb->data pointing to the
* Ethernet header * Ethernet header
* @in_port: port number on which @skb was received.
* @key: output flow key * @key: output flow key
* *
* The caller must ensure that skb->len >= ETH_HLEN. * The caller must ensure that skb->len >= ETH_HLEN.
...@@ -442,19 +443,11 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, ...@@ -442,19 +443,11 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
* of a correct length, otherwise the same as skb->network_header. * of a correct length, otherwise the same as skb->network_header.
* For other key->eth.type values it is left untouched. * 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; int error;
struct ethhdr *eth; 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); skb_reset_mac_header(skb);
/* Link layer. We are guaranteed to have at least the 14 byte Ethernet /* Link layer. We are guaranteed to have at least the 14 byte Ethernet
...@@ -610,6 +603,34 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key) ...@@ -610,6 +603,34 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
} }
} }
} }
return 0; 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);
}
...@@ -187,6 +187,10 @@ void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *, ...@@ -187,6 +187,10 @@ void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
void ovs_flow_stats_clear(struct sw_flow *); void ovs_flow_stats_clear(struct sw_flow *);
u64 ovs_flow_used_time(unsigned long flow_jiffies); 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 */ #endif /* flow.h */
...@@ -836,7 +836,7 @@ int ovs_nla_get_match(struct sw_flow_match *match, ...@@ -836,7 +836,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,
/** /**
* ovs_nla_get_flow_metadata - parses Netlink attributes into a flow key. * 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 * @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
* sequence. * sequence.
* *
...@@ -846,32 +846,24 @@ int ovs_nla_get_match(struct sw_flow_match *match, ...@@ -846,32 +846,24 @@ int ovs_nla_get_match(struct sw_flow_match *match,
* extracted from the packet itself. * extracted from the packet itself.
*/ */
int ovs_nla_get_flow_metadata(struct sw_flow *flow, int ovs_nla_get_flow_metadata(const struct nlattr *attr,
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]; const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
struct sw_flow_match match;
u64 attrs = 0; u64 attrs = 0;
int err; 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;
memset(tun_key, 0, sizeof(flow->key.tun_key));
err = parse_flow_nlattrs(attr, a, &attrs); err = parse_flow_nlattrs(attr, a, &attrs);
if (err) if (err)
return -EINVAL; return -EINVAL;
memset(&match, 0, sizeof(match)); memset(&match, 0, sizeof(match));
match.key = &flow->key; match.key = key;
err = metadata_from_nlattrs(&match, &attrs, a, false); key->phy.in_port = DP_MAX_PORTS;
if (err)
return err;
return 0; return metadata_from_nlattrs(&match, &attrs, a, false);
} }
int ovs_nla_put_flow(const struct sw_flow_key *swkey, int ovs_nla_put_flow(const struct sw_flow_key *swkey,
......
...@@ -42,8 +42,8 @@ void ovs_match_init(struct sw_flow_match *match, ...@@ -42,8 +42,8 @@ void ovs_match_init(struct sw_flow_match *match,
int ovs_nla_put_flow(const struct sw_flow_key *, int ovs_nla_put_flow(const struct sw_flow_key *,
const struct sw_flow_key *, struct sk_buff *); const struct sw_flow_key *, struct sk_buff *);
int ovs_nla_get_flow_metadata(struct sw_flow *flow, int ovs_nla_get_flow_metadata(const struct nlattr *, struct sw_flow_key *);
const struct nlattr *attr);
int ovs_nla_get_match(struct sw_flow_match *match, int ovs_nla_get_match(struct sw_flow_match *match,
const struct nlattr *, const struct nlattr *,
const struct nlattr *); const struct nlattr *);
......
/* /*
* Copyright (c) 2007-2012 Nicira, Inc. * Copyright (c) 2007-2014 Nicira, Inc.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public * modify it under the terms of version 2 of the GNU General Public
...@@ -443,7 +443,8 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb, ...@@ -443,7 +443,8 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
u64_stats_update_end(&stats->syncp); u64_stats_update_end(&stats->syncp);
OVS_CB(skb)->tun_key = tun_key; OVS_CB(skb)->tun_key = tun_key;
ovs_dp_process_received_packet(vport, skb); OVS_CB(skb)->input_vport = vport;
ovs_dp_process_received_packet(skb);
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment