aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-07-25 02:18:21 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-25 02:18:21 -0400
commit9239079080fe364189d13020441c46f9f0e0071d (patch)
tree913a82ae0c7968736e6e2ef6211b744cd4787383 /net
parent10f29808605118bee8666d4b2c776c07d04cdc0a (diff)
parentd9e0ecb81417c34ef8c02a6880d23c362300cda0 (diff)
Merge branch 'net_next_ovs' of git://git.kernel.org/pub/scm/linux/kernel/git/pshelar/openvswitch
Pravin B Shelar says: ==================== Open vSwitch Following patches adds three features to OVS 1. Add fairness to upcall processing. 2. Hash action. 3. Enable Tunnel GSO features. Rest of patches are bug fixes related to patches from same series. v2 series changes first patch according to comment from Dave Miller. v3 series changes first patch according to comment from Nikolay Aleksandrov. v4 series update recirc patch commit msg. v5 series resolve conflict with net-next, updated recic action patch. v6 series sends all patches. v7 series drop recirc patches. v8 series checkpatch fix v9 series drop HASH action patch. update sample action commit msg. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/openvswitch/actions.c50
-rw-r--r--net/openvswitch/datapath.c26
-rw-r--r--net/openvswitch/vport-internal_dev.c5
-rw-r--r--net/openvswitch/vport.c101
-rw-r--r--net/openvswitch/vport.h27
5 files changed, 184 insertions, 25 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index e70d8b18e962..fe5cda0deb39 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -38,7 +38,7 @@
38#include "vport.h" 38#include "vport.h"
39 39
40static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, 40static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
41 const struct nlattr *attr, int len, bool keep_skb); 41 const struct nlattr *attr, int len);
42 42
43static int make_writable(struct sk_buff *skb, int write_len) 43static int make_writable(struct sk_buff *skb, int write_len)
44{ 44{
@@ -434,11 +434,17 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
434 return ovs_dp_upcall(dp, skb, &upcall); 434 return ovs_dp_upcall(dp, skb, &upcall);
435} 435}
436 436
437static bool last_action(const struct nlattr *a, int rem)
438{
439 return a->nla_len == rem;
440}
441
437static int sample(struct datapath *dp, struct sk_buff *skb, 442static int sample(struct datapath *dp, struct sk_buff *skb,
438 const struct nlattr *attr) 443 const struct nlattr *attr)
439{ 444{
440 const struct nlattr *acts_list = NULL; 445 const struct nlattr *acts_list = NULL;
441 const struct nlattr *a; 446 const struct nlattr *a;
447 struct sk_buff *sample_skb;
442 int rem; 448 int rem;
443 449
444 for (a = nla_data(attr), rem = nla_len(attr); rem > 0; 450 for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
@@ -455,8 +461,34 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
455 } 461 }
456 } 462 }
457 463
458 return do_execute_actions(dp, skb, nla_data(acts_list), 464 rem = nla_len(acts_list);
459 nla_len(acts_list), true); 465 a = nla_data(acts_list);
466
467 /* Actions list is either empty or only contains a single user-space
468 * action, the latter being a special case as it is the only known
469 * usage of the sample action.
470 * In these special cases don't clone the skb as there are no
471 * side-effects in the nested actions.
472 * Otherwise, clone in case the nested actions have side effects.
473 */
474 if (likely(rem == 0 || (nla_type(a) == OVS_ACTION_ATTR_USERSPACE &&
475 last_action(a, rem)))) {
476 sample_skb = skb;
477 skb_get(skb);
478 } else {
479 sample_skb = skb_clone(skb, GFP_ATOMIC);
480 if (!sample_skb) /* Skip sample action when out of memory. */
481 return 0;
482 }
483
484 /* Note that do_execute_actions() never consumes skb.
485 * In the case where skb has been cloned above it is the clone that
486 * is consumed. Otherwise the skb_get(skb) call prevents
487 * consumption by do_execute_actions(). Thus, it is safe to simply
488 * return the error code and let the caller (also
489 * do_execute_actions()) free skb on error.
490 */
491 return do_execute_actions(dp, sample_skb, a, rem);
460} 492}
461 493
462static int execute_set_action(struct sk_buff *skb, 494static int execute_set_action(struct sk_buff *skb,
@@ -507,7 +539,7 @@ static int execute_set_action(struct sk_buff *skb,
507 539
508/* Execute a list of actions against 'skb'. */ 540/* Execute a list of actions against 'skb'. */
509static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, 541static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
510 const struct nlattr *attr, int len, bool keep_skb) 542 const struct nlattr *attr, int len)
511{ 543{
512 /* Every output action needs a separate clone of 'skb', but the common 544 /* Every output action needs a separate clone of 'skb', but the common
513 * case is just a single output action, so that doing a clone and 545 * case is just a single output action, so that doing a clone and
@@ -562,12 +594,9 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
562 } 594 }
563 } 595 }
564 596
565 if (prev_port != -1) { 597 if (prev_port != -1)
566 if (keep_skb)
567 skb = skb_clone(skb, GFP_ATOMIC);
568
569 do_output(dp, skb, prev_port); 598 do_output(dp, skb, prev_port);
570 } else if (!keep_skb) 599 else
571 consume_skb(skb); 600 consume_skb(skb);
572 601
573 return 0; 602 return 0;
@@ -579,6 +608,5 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb)
579 struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts); 608 struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
580 609
581 OVS_CB(skb)->tun_key = NULL; 610 OVS_CB(skb)->tun_key = NULL;
582 return do_execute_actions(dp, skb, acts->actions, 611 return do_execute_actions(dp, skb, acts->actions, acts->actions_len);
583 acts->actions_len, false);
584} 612}
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 20f59b62721a..3c461e1e4554 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -266,7 +266,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
266 upcall.cmd = OVS_PACKET_CMD_MISS; 266 upcall.cmd = OVS_PACKET_CMD_MISS;
267 upcall.key = &key; 267 upcall.key = &key;
268 upcall.userdata = NULL; 268 upcall.userdata = NULL;
269 upcall.portid = p->upcall_portid; 269 upcall.portid = ovs_vport_find_upcall_portid(p, skb);
270 ovs_dp_upcall(dp, skb, &upcall); 270 ovs_dp_upcall(dp, skb, &upcall);
271 consume_skb(skb); 271 consume_skb(skb);
272 stats_counter = &stats->n_missed; 272 stats_counter = &stats->n_missed;
@@ -464,7 +464,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
464 upcall->dp_ifindex = dp_ifindex; 464 upcall->dp_ifindex = dp_ifindex;
465 465
466 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); 466 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY);
467 ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb); 467 err = ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb);
468 BUG_ON(err);
468 nla_nest_end(user_skb, nla); 469 nla_nest_end(user_skb, nla);
469 470
470 if (upcall_info->userdata) 471 if (upcall_info->userdata)
@@ -1373,7 +1374,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
1373 parms.options = NULL; 1374 parms.options = NULL;
1374 parms.dp = dp; 1375 parms.dp = dp;
1375 parms.port_no = OVSP_LOCAL; 1376 parms.port_no = OVSP_LOCAL;
1376 parms.upcall_portid = nla_get_u32(a[OVS_DP_ATTR_UPCALL_PID]); 1377 parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID];
1377 1378
1378 ovs_dp_change(dp, a); 1379 ovs_dp_change(dp, a);
1379 1380
@@ -1632,8 +1633,8 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
1632 1633
1633 if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) || 1634 if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) ||
1634 nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) || 1635 nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) ||
1635 nla_put_string(skb, OVS_VPORT_ATTR_NAME, vport->ops->get_name(vport)) || 1636 nla_put_string(skb, OVS_VPORT_ATTR_NAME,
1636 nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, vport->upcall_portid)) 1637 vport->ops->get_name(vport)))
1637 goto nla_put_failure; 1638 goto nla_put_failure;
1638 1639
1639 ovs_vport_get_stats(vport, &vport_stats); 1640 ovs_vport_get_stats(vport, &vport_stats);
@@ -1641,6 +1642,9 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
1641 &vport_stats)) 1642 &vport_stats))
1642 goto nla_put_failure; 1643 goto nla_put_failure;
1643 1644
1645 if (ovs_vport_get_upcall_portids(vport, skb))
1646 goto nla_put_failure;
1647
1644 err = ovs_vport_get_options(vport, skb); 1648 err = ovs_vport_get_options(vport, skb);
1645 if (err == -EMSGSIZE) 1649 if (err == -EMSGSIZE)
1646 goto error; 1650 goto error;
@@ -1762,7 +1766,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
1762 parms.options = a[OVS_VPORT_ATTR_OPTIONS]; 1766 parms.options = a[OVS_VPORT_ATTR_OPTIONS];
1763 parms.dp = dp; 1767 parms.dp = dp;
1764 parms.port_no = port_no; 1768 parms.port_no = port_no;
1765 parms.upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); 1769 parms.upcall_portids = a[OVS_VPORT_ATTR_UPCALL_PID];
1766 1770
1767 vport = new_vport(&parms); 1771 vport = new_vport(&parms);
1768 err = PTR_ERR(vport); 1772 err = PTR_ERR(vport);
@@ -1812,8 +1816,14 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
1812 goto exit_unlock_free; 1816 goto exit_unlock_free;
1813 } 1817 }
1814 1818
1815 if (a[OVS_VPORT_ATTR_UPCALL_PID]) 1819
1816 vport->upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); 1820 if (a[OVS_VPORT_ATTR_UPCALL_PID]) {
1821 struct nlattr *ids = a[OVS_VPORT_ATTR_UPCALL_PID];
1822
1823 err = ovs_vport_set_upcall_portids(vport, ids);
1824 if (err)
1825 goto exit_unlock_free;
1826 }
1817 1827
1818 err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, 1828 err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
1819 info->snd_seq, 0, OVS_VPORT_CMD_NEW); 1829 info->snd_seq, 0, OVS_VPORT_CMD_NEW);
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index bd658555afdf..84516126e5f3 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -140,11 +140,14 @@ static void do_setup(struct net_device *netdev)
140 netdev->tx_queue_len = 0; 140 netdev->tx_queue_len = 0;
141 141
142 netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST | 142 netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST |
143 NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE; 143 NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
144 NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL;
144 145
145 netdev->vlan_features = netdev->features; 146 netdev->vlan_features = netdev->features;
147 netdev->hw_enc_features = netdev->features;
146 netdev->features |= NETIF_F_HW_VLAN_CTAG_TX; 148 netdev->features |= NETIF_F_HW_VLAN_CTAG_TX;
147 netdev->hw_features = netdev->features & ~NETIF_F_LLTX; 149 netdev->hw_features = netdev->features & ~NETIF_F_LLTX;
150
148 eth_hw_addr_random(netdev); 151 eth_hw_addr_random(netdev);
149} 152}
150 153
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index 42c0f4a0b78c..702fb21bfe15 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -134,10 +134,12 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
134 134
135 vport->dp = parms->dp; 135 vport->dp = parms->dp;
136 vport->port_no = parms->port_no; 136 vport->port_no = parms->port_no;
137 vport->upcall_portid = parms->upcall_portid;
138 vport->ops = ops; 137 vport->ops = ops;
139 INIT_HLIST_NODE(&vport->dp_hash_node); 138 INIT_HLIST_NODE(&vport->dp_hash_node);
140 139
140 if (ovs_vport_set_upcall_portids(vport, parms->upcall_portids))
141 return ERR_PTR(-EINVAL);
142
141 vport->percpu_stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 143 vport->percpu_stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
142 if (!vport->percpu_stats) { 144 if (!vport->percpu_stats) {
143 kfree(vport); 145 kfree(vport);
@@ -161,6 +163,10 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
161 */ 163 */
162void ovs_vport_free(struct vport *vport) 164void ovs_vport_free(struct vport *vport)
163{ 165{
166 /* vport is freed from RCU callback or error path, Therefore
167 * it is safe to use raw dereference.
168 */
169 kfree(rcu_dereference_raw(vport->upcall_portids));
164 free_percpu(vport->percpu_stats); 170 free_percpu(vport->percpu_stats);
165 kfree(vport); 171 kfree(vport);
166} 172}
@@ -327,6 +333,99 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
327} 333}
328 334
329/** 335/**
336 * ovs_vport_set_upcall_portids - set upcall portids of @vport.
337 *
338 * @vport: vport to modify.
339 * @ids: new configuration, an array of port ids.
340 *
341 * Sets the vport's upcall_portids to @ids.
342 *
343 * Returns 0 if successful, -EINVAL if @ids is zero length or cannot be parsed
344 * as an array of U32.
345 *
346 * Must be called with ovs_mutex.
347 */
348int ovs_vport_set_upcall_portids(struct vport *vport, struct nlattr *ids)
349{
350 struct vport_portids *old, *vport_portids;
351
352 if (!nla_len(ids) || nla_len(ids) % sizeof(u32))
353 return -EINVAL;
354
355 old = ovsl_dereference(vport->upcall_portids);
356
357 vport_portids = kmalloc(sizeof(*vport_portids) + nla_len(ids),
358 GFP_KERNEL);
359 if (!vport_portids)
360 return -ENOMEM;
361
362 vport_portids->n_ids = nla_len(ids) / sizeof(u32);
363 vport_portids->rn_ids = reciprocal_value(vport_portids->n_ids);
364 nla_memcpy(vport_portids->ids, ids, nla_len(ids));
365
366 rcu_assign_pointer(vport->upcall_portids, vport_portids);
367
368 if (old)
369 kfree_rcu(old, rcu);
370 return 0;
371}
372
373/**
374 * ovs_vport_get_upcall_portids - get the upcall_portids of @vport.
375 *
376 * @vport: vport from which to retrieve the portids.
377 * @skb: sk_buff where portids should be appended.
378 *
379 * Retrieves the configuration of the given vport, appending the
380 * %OVS_VPORT_ATTR_UPCALL_PID attribute which is the array of upcall
381 * portids to @skb.
382 *
383 * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room.
384 * If an error occurs, @skb is left unmodified. Must be called with
385 * ovs_mutex or rcu_read_lock.
386 */
387int ovs_vport_get_upcall_portids(const struct vport *vport,
388 struct sk_buff *skb)
389{
390 struct vport_portids *ids;
391
392 ids = rcu_dereference_ovsl(vport->upcall_portids);
393
394 if (vport->dp->user_features & OVS_DP_F_VPORT_PIDS)
395 return nla_put(skb, OVS_VPORT_ATTR_UPCALL_PID,
396 ids->n_ids * sizeof(u32), (void *)ids->ids);
397 else
398 return nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, ids->ids[0]);
399}
400
401/**
402 * ovs_vport_find_upcall_portid - find the upcall portid to send upcall.
403 *
404 * @vport: vport from which the missed packet is received.
405 * @skb: skb that the missed packet was received.
406 *
407 * Uses the skb_get_hash() to select the upcall portid to send the
408 * upcall.
409 *
410 * Returns the portid of the target socket. Must be called with rcu_read_lock.
411 */
412u32 ovs_vport_find_upcall_portid(const struct vport *p, struct sk_buff *skb)
413{
414 struct vport_portids *ids;
415 u32 ids_index;
416 u32 hash;
417
418 ids = rcu_dereference(p->upcall_portids);
419
420 if (ids->n_ids == 1 && ids->ids[0] == 0)
421 return 0;
422
423 hash = skb_get_hash(skb);
424 ids_index = hash - ids->n_ids * reciprocal_divide(hash, ids->rn_ids);
425 return ids->ids[ids_index];
426}
427
428/**
330 * ovs_vport_receive - pass up received packet to the datapath for processing 429 * ovs_vport_receive - pass up received packet to the datapath for processing
331 * 430 *
332 * @vport: vport that received the packet 431 * @vport: vport that received the packet
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 8d721e62f388..35f89d84b45e 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -23,6 +23,7 @@
23#include <linux/list.h> 23#include <linux/list.h>
24#include <linux/netlink.h> 24#include <linux/netlink.h>
25#include <linux/openvswitch.h> 25#include <linux/openvswitch.h>
26#include <linux/reciprocal_div.h>
26#include <linux/skbuff.h> 27#include <linux/skbuff.h>
27#include <linux/spinlock.h> 28#include <linux/spinlock.h>
28#include <linux/u64_stats_sync.h> 29#include <linux/u64_stats_sync.h>
@@ -52,6 +53,10 @@ void ovs_vport_get_stats(struct vport *, struct ovs_vport_stats *);
52int ovs_vport_set_options(struct vport *, struct nlattr *options); 53int ovs_vport_set_options(struct vport *, struct nlattr *options);
53int ovs_vport_get_options(const struct vport *, struct sk_buff *); 54int ovs_vport_get_options(const struct vport *, struct sk_buff *);
54 55
56int ovs_vport_set_upcall_portids(struct vport *, struct nlattr *pids);
57int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *);
58u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *);
59
55int ovs_vport_send(struct vport *, struct sk_buff *); 60int ovs_vport_send(struct vport *, struct sk_buff *);
56 61
57/* The following definitions are for implementers of vport devices: */ 62/* The following definitions are for implementers of vport devices: */
@@ -62,13 +67,27 @@ struct vport_err_stats {
62 u64 tx_dropped; 67 u64 tx_dropped;
63 u64 tx_errors; 68 u64 tx_errors;
64}; 69};
70/**
71 * struct vport_portids - array of netlink portids of a vport.
72 * must be protected by rcu.
73 * @rn_ids: The reciprocal value of @n_ids.
74 * @rcu: RCU callback head for deferred destruction.
75 * @n_ids: Size of @ids array.
76 * @ids: Array storing the Netlink socket pids to be used for packets received
77 * on this port that miss the flow table.
78 */
79struct vport_portids {
80 struct reciprocal_value rn_ids;
81 struct rcu_head rcu;
82 u32 n_ids;
83 u32 ids[];
84};
65 85
66/** 86/**
67 * struct vport - one port within a datapath 87 * struct vport - one port within a datapath
68 * @rcu: RCU callback head for deferred destruction. 88 * @rcu: RCU callback head for deferred destruction.
69 * @dp: Datapath to which this port belongs. 89 * @dp: Datapath to which this port belongs.
70 * @upcall_portid: The Netlink port to use for packets received on this port that 90 * @upcall_portids: RCU protected 'struct vport_portids'.
71 * miss the flow table.
72 * @port_no: Index into @dp's @ports array. 91 * @port_no: Index into @dp's @ports array.
73 * @hash_node: Element in @dev_table hash table in vport.c. 92 * @hash_node: Element in @dev_table hash table in vport.c.
74 * @dp_hash_node: Element in @datapath->ports hash table in datapath.c. 93 * @dp_hash_node: Element in @datapath->ports hash table in datapath.c.
@@ -80,7 +99,7 @@ struct vport_err_stats {
80struct vport { 99struct vport {
81 struct rcu_head rcu; 100 struct rcu_head rcu;
82 struct datapath *dp; 101 struct datapath *dp;
83 u32 upcall_portid; 102 struct vport_portids __rcu *upcall_portids;
84 u16 port_no; 103 u16 port_no;
85 104
86 struct hlist_node hash_node; 105 struct hlist_node hash_node;
@@ -111,7 +130,7 @@ struct vport_parms {
111 /* For ovs_vport_alloc(). */ 130 /* For ovs_vport_alloc(). */
112 struct datapath *dp; 131 struct datapath *dp;
113 u16 port_no; 132 u16 port_no;
114 u32 upcall_portid; 133 struct nlattr *upcall_portids;
115}; 134};
116 135
117/** 136/**