aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/openvswitch/datapath.c21
-rw-r--r--net/openvswitch/datapath.h5
-rw-r--r--net/openvswitch/flow.c49
-rw-r--r--net/openvswitch/flow.h6
-rw-r--r--net/openvswitch/flow_netlink.c22
-rw-r--r--net/openvswitch/flow_netlink.h4
-rw-r--r--net/openvswitch/vport.c5
7 files changed, 71 insertions, 41 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 458096da138a..0cce8e60d5ed 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -237,8 +237,9 @@ void ovs_dp_detach_port(struct vport *p)
237} 237}
238 238
239/* Must be called with rcu_read_lock. */ 239/* Must be called with rcu_read_lock. */
240void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) 240void ovs_dp_process_received_packet(struct sk_buff *skb)
241{ 241{
242 const struct vport *p = OVS_CB(skb)->input_vport;
242 struct datapath *dp = p->dp; 243 struct datapath *dp = p->dp;
243 struct sw_flow *flow; 244 struct sw_flow *flow;
244 struct dp_stats_percpu *stats; 245 struct dp_stats_percpu *stats;
@@ -250,7 +251,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
250 stats = this_cpu_ptr(dp->stats_percpu); 251 stats = this_cpu_ptr(dp->stats_percpu);
251 252
252 /* Extract flow from 'skb' into 'key'. */ 253 /* Extract flow from 'skb' into 'key'. */
253 error = ovs_flow_extract(skb, p->port_no, &key); 254 error = ovs_flow_key_extract(skb, &key);
254 if (unlikely(error)) { 255 if (unlikely(error)) {
255 kfree_skb(skb); 256 kfree_skb(skb);
256 return; 257 return;
@@ -514,6 +515,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
514 struct sw_flow *flow; 515 struct sw_flow *flow;
515 struct datapath *dp; 516 struct datapath *dp;
516 struct ethhdr *eth; 517 struct ethhdr *eth;
518 struct vport *input_vport;
517 int len; 519 int len;
518 int err; 520 int err;
519 521
@@ -548,13 +550,11 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
548 if (IS_ERR(flow)) 550 if (IS_ERR(flow))
549 goto err_kfree_skb; 551 goto err_kfree_skb;
550 552
551 err = ovs_flow_extract(packet, -1, &flow->key); 553 err = ovs_flow_key_extract_userspace(a[OVS_PACKET_ATTR_KEY], packet,
554 &flow->key);
552 if (err) 555 if (err)
553 goto err_flow_free; 556 goto err_flow_free;
554 557
555 err = ovs_nla_get_flow_metadata(flow, a[OVS_PACKET_ATTR_KEY]);
556 if (err)
557 goto err_flow_free;
558 acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_PACKET_ATTR_ACTIONS])); 558 acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_PACKET_ATTR_ACTIONS]));
559 err = PTR_ERR(acts); 559 err = PTR_ERR(acts);
560 if (IS_ERR(acts)) 560 if (IS_ERR(acts))
@@ -576,6 +576,15 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
576 if (!dp) 576 if (!dp)
577 goto err_unlock; 577 goto err_unlock;
578 578
579 input_vport = ovs_vport_rcu(dp, flow->key.phy.in_port);
580 if (!input_vport)
581 input_vport = ovs_vport_rcu(dp, OVSP_LOCAL);
582
583 if (!input_vport)
584 goto err_unlock;
585
586 OVS_CB(packet)->input_vport = input_vport;
587
579 local_bh_disable(); 588 local_bh_disable();
580 err = ovs_execute_actions(dp, packet, &flow->key); 589 err = ovs_execute_actions(dp, packet, &flow->key);
581 local_bh_enable(); 590 local_bh_enable();
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index b576483aab7c..2b982fae6a11 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -97,10 +97,13 @@ struct datapath {
97 * @flow: The flow associated with this packet. May be %NULL if no flow. 97 * @flow: The flow associated with this packet. May be %NULL if no flow.
98 * @tun_key: Key for the tunnel that encapsulated this packet. NULL if the 98 * @tun_key: Key for the tunnel that encapsulated this packet. NULL if the
99 * packet is not being tunneled. 99 * packet is not being tunneled.
100 * @input_vport: The original vport packet came in on. This value is cached
101 * when a packet is received by OVS.
100 */ 102 */
101struct ovs_skb_cb { 103struct ovs_skb_cb {
102 struct sw_flow *flow; 104 struct sw_flow *flow;
103 struct ovs_key_ipv4_tunnel *tun_key; 105 struct ovs_key_ipv4_tunnel *tun_key;
106 struct vport *input_vport;
104}; 107};
105#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb) 108#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
106 109
@@ -181,7 +184,7 @@ static inline struct vport *ovs_vport_ovsl(const struct datapath *dp, int port_n
181extern struct notifier_block ovs_dp_device_notifier; 184extern struct notifier_block ovs_dp_device_notifier;
182extern struct genl_family dp_vport_genl_family; 185extern struct genl_family dp_vport_genl_family;
183 186
184void ovs_dp_process_received_packet(struct vport *, struct sk_buff *); 187void ovs_dp_process_received_packet(struct sk_buff *);
185void ovs_dp_detach_port(struct vport *); 188void ovs_dp_detach_port(struct vport *);
186int ovs_dp_upcall(struct datapath *, struct sk_buff *, 189int ovs_dp_upcall(struct datapath *, struct sk_buff *,
187 const struct dp_upcall_info *); 190 const struct dp_upcall_info *);
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 7064da92f420..d186eb65a391 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -16,8 +16,6 @@
16 * 02110-1301, USA 16 * 02110-1301, USA
17 */ 17 */
18 18
19#include "flow.h"
20#include "datapath.h"
21#include <linux/uaccess.h> 19#include <linux/uaccess.h>
22#include <linux/netdevice.h> 20#include <linux/netdevice.h>
23#include <linux/etherdevice.h> 21#include <linux/etherdevice.h>
@@ -46,6 +44,10 @@
46#include <net/ipv6.h> 44#include <net/ipv6.h>
47#include <net/ndisc.h> 45#include <net/ndisc.h>
48 46
47#include "datapath.h"
48#include "flow.h"
49#include "flow_netlink.h"
50
49u64 ovs_flow_used_time(unsigned long flow_jiffies) 51u64 ovs_flow_used_time(unsigned long flow_jiffies)
50{ 52{
51 struct timespec cur_ts; 53 struct timespec cur_ts;
@@ -420,10 +422,9 @@ invalid:
420} 422}
421 423
422/** 424/**
423 * ovs_flow_extract - extracts a flow key from an Ethernet frame. 425 * key_extract - extracts a flow key from an Ethernet frame.
424 * @skb: sk_buff that contains the frame, with skb->data pointing to the 426 * @skb: sk_buff that contains the frame, with skb->data pointing to the
425 * Ethernet header 427 * Ethernet header
426 * @in_port: port number on which @skb was received.
427 * @key: output flow key 428 * @key: output flow key
428 * 429 *
429 * The caller must ensure that skb->len >= ETH_HLEN. 430 * The caller must ensure that skb->len >= ETH_HLEN.
@@ -442,19 +443,11 @@ invalid:
442 * of a correct length, otherwise the same as skb->network_header. 443 * of a correct length, otherwise the same as skb->network_header.
443 * For other key->eth.type values it is left untouched. 444 * For other key->eth.type values it is left untouched.
444 */ 445 */
445int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key) 446static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
446{ 447{
447 int error; 448 int error;
448 struct ethhdr *eth; 449 struct ethhdr *eth;
449 450
450 memset(key, 0, sizeof(*key));
451
452 key->phy.priority = skb->priority;
453 if (OVS_CB(skb)->tun_key)
454 memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
455 key->phy.in_port = in_port;
456 key->phy.skb_mark = skb->mark;
457
458 skb_reset_mac_header(skb); 451 skb_reset_mac_header(skb);
459 452
460 /* Link layer. We are guaranteed to have at least the 14 byte Ethernet 453 /* 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 } 603 }
611 } 604 }
612 } 605 }
613
614 return 0; 606 return 0;
615} 607}
608
609int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key)
610{
611 /* Extract metadata from packet. */
612 memset(key, 0, sizeof(*key));
613 if (OVS_CB(skb)->tun_key)
614 memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
615
616 key->phy.priority = skb->priority;
617 key->phy.in_port = OVS_CB(skb)->input_vport->port_no;
618 key->phy.skb_mark = skb->mark;
619
620 return key_extract(skb, key);
621}
622
623int ovs_flow_key_extract_userspace(const struct nlattr *attr,
624 struct sk_buff *skb,
625 struct sw_flow_key *key)
626{
627 int err;
628
629 memset(key, 0, sizeof(*key));
630 /* Extract metadata from netlink attributes. */
631 err = ovs_nla_get_flow_metadata(attr, key);
632 if (err)
633 return err;
634
635 return key_extract(skb, key);
636}
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 5e5aaed3a85b..251789b6ec45 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -187,6 +187,10 @@ void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
187void ovs_flow_stats_clear(struct sw_flow *); 187void ovs_flow_stats_clear(struct sw_flow *);
188u64 ovs_flow_used_time(unsigned long flow_jiffies); 188u64 ovs_flow_used_time(unsigned long flow_jiffies);
189 189
190int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *); 190int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key);
191/* Extract key from packet coming from userspace. */
192int ovs_flow_key_extract_userspace(const struct nlattr *attr,
193 struct sk_buff *skb,
194 struct sw_flow_key *key);
191 195
192#endif /* flow.h */ 196#endif /* flow.h */
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index d757848da89c..630b320fbf3e 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -836,7 +836,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,
836 836
837/** 837/**
838 * ovs_nla_get_flow_metadata - parses Netlink attributes into a flow key. 838 * ovs_nla_get_flow_metadata - parses Netlink attributes into a flow key.
839 * @flow: Receives extracted in_port, priority, tun_key and skb_mark. 839 * @key: Receives extracted in_port, priority, tun_key and skb_mark.
840 * @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute 840 * @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
841 * sequence. 841 * sequence.
842 * 842 *
@@ -846,32 +846,24 @@ int ovs_nla_get_match(struct sw_flow_match *match,
846 * extracted from the packet itself. 846 * extracted from the packet itself.
847 */ 847 */
848 848
849int ovs_nla_get_flow_metadata(struct sw_flow *flow, 849int ovs_nla_get_flow_metadata(const struct nlattr *attr,
850 const struct nlattr *attr) 850 struct sw_flow_key *key)
851{ 851{
852 struct ovs_key_ipv4_tunnel *tun_key = &flow->key.tun_key;
853 const struct nlattr *a[OVS_KEY_ATTR_MAX + 1]; 852 const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
853 struct sw_flow_match match;
854 u64 attrs = 0; 854 u64 attrs = 0;
855 int err; 855 int err;
856 struct sw_flow_match match;
857
858 flow->key.phy.in_port = DP_MAX_PORTS;
859 flow->key.phy.priority = 0;
860 flow->key.phy.skb_mark = 0;
861 memset(tun_key, 0, sizeof(flow->key.tun_key));
862 856
863 err = parse_flow_nlattrs(attr, a, &attrs); 857 err = parse_flow_nlattrs(attr, a, &attrs);
864 if (err) 858 if (err)
865 return -EINVAL; 859 return -EINVAL;
866 860
867 memset(&match, 0, sizeof(match)); 861 memset(&match, 0, sizeof(match));
868 match.key = &flow->key; 862 match.key = key;
869 863
870 err = metadata_from_nlattrs(&match, &attrs, a, false); 864 key->phy.in_port = DP_MAX_PORTS;
871 if (err)
872 return err;
873 865
874 return 0; 866 return metadata_from_nlattrs(&match, &attrs, a, false);
875} 867}
876 868
877int ovs_nla_put_flow(const struct sw_flow_key *swkey, 869int ovs_nla_put_flow(const struct sw_flow_key *swkey,
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h
index 440151045d39..206e45add888 100644
--- a/net/openvswitch/flow_netlink.h
+++ b/net/openvswitch/flow_netlink.h
@@ -42,8 +42,8 @@ void ovs_match_init(struct sw_flow_match *match,
42 42
43int ovs_nla_put_flow(const struct sw_flow_key *, 43int ovs_nla_put_flow(const struct sw_flow_key *,
44 const struct sw_flow_key *, struct sk_buff *); 44 const struct sw_flow_key *, struct sk_buff *);
45int ovs_nla_get_flow_metadata(struct sw_flow *flow, 45int ovs_nla_get_flow_metadata(const struct nlattr *, struct sw_flow_key *);
46 const struct nlattr *attr); 46
47int ovs_nla_get_match(struct sw_flow_match *match, 47int ovs_nla_get_match(struct sw_flow_match *match,
48 const struct nlattr *, 48 const struct nlattr *,
49 const struct nlattr *); 49 const struct nlattr *);
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index f7e63f9df7b9..acf31aa89e01 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2007-2012 Nicira, Inc. 2 * Copyright (c) 2007-2014 Nicira, Inc.
3 * 3 *
4 * This program is free software; you can redistribute it and/or 4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public 5 * 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 u64_stats_update_end(&stats->syncp); 443 u64_stats_update_end(&stats->syncp);
444 444
445 OVS_CB(skb)->tun_key = tun_key; 445 OVS_CB(skb)->tun_key = tun_key;
446 ovs_dp_process_received_packet(vport, skb); 446 OVS_CB(skb)->input_vport = vport;
447 ovs_dp_process_received_packet(skb);
447} 448}
448 449
449/** 450/**