aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-11-04 16:25:04 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-04 16:25:04 -0500
commit6fcf018ae4491dc11b080892fa9f3dbd928fdbb9 (patch)
treef28592676e295183581d59149fd1eac913b229a2 /net
parent5a6e55c461db3364aa5be919101db972bc859133 (diff)
parent8ddd094675cfd453fc9838caa46ea108a4107183 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch
Jesse Gross says: ==================== Open vSwitch A set of updates for net-next/3.13. Major changes are: * Restructure flow handling code to be more logically organized and easier to read. * Rehashing of the flow table is moved from a workqueue to flow installation time. Before, heavy load could block the workqueue for excessive periods of time. * Additional debugging information is provided to help diagnose megaflows. * It's now possible to match on TCP flags. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/openvswitch/Makefile2
-rw-r--r--net/openvswitch/datapath.c668
-rw-r--r--net/openvswitch/datapath.h9
-rw-r--r--net/openvswitch/flow.c1605
-rw-r--r--net/openvswitch/flow.h132
-rw-r--r--net/openvswitch/flow_netlink.c1630
-rw-r--r--net/openvswitch/flow_netlink.h60
-rw-r--r--net/openvswitch/flow_table.c592
-rw-r--r--net/openvswitch/flow_table.h81
-rw-r--r--net/openvswitch/vport-gre.c2
-rw-r--r--net/openvswitch/vport-internal_dev.c2
-rw-r--r--net/openvswitch/vport-vxlan.c1
12 files changed, 2496 insertions, 2288 deletions
diff --git a/net/openvswitch/Makefile b/net/openvswitch/Makefile
index ea36e99089af..3591cb5dae91 100644
--- a/net/openvswitch/Makefile
+++ b/net/openvswitch/Makefile
@@ -9,6 +9,8 @@ openvswitch-y := \
9 datapath.o \ 9 datapath.o \
10 dp_notify.o \ 10 dp_notify.o \
11 flow.o \ 11 flow.o \
12 flow_netlink.o \
13 flow_table.o \
12 vport.o \ 14 vport.o \
13 vport-internal_dev.o \ 15 vport-internal_dev.o \
14 vport-netdev.o 16 vport-netdev.o
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 2aa13bd7f2b2..1408adc2a2a7 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -55,14 +55,10 @@
55 55
56#include "datapath.h" 56#include "datapath.h"
57#include "flow.h" 57#include "flow.h"
58#include "flow_netlink.h"
58#include "vport-internal_dev.h" 59#include "vport-internal_dev.h"
59#include "vport-netdev.h" 60#include "vport-netdev.h"
60 61
61
62#define REHASH_FLOW_INTERVAL (10 * 60 * HZ)
63static void rehash_flow_table(struct work_struct *work);
64static DECLARE_DELAYED_WORK(rehash_flow_wq, rehash_flow_table);
65
66int ovs_net_id __read_mostly; 62int ovs_net_id __read_mostly;
67 63
68static void ovs_notify(struct sk_buff *skb, struct genl_info *info, 64static void ovs_notify(struct sk_buff *skb, struct genl_info *info,
@@ -165,7 +161,7 @@ static void destroy_dp_rcu(struct rcu_head *rcu)
165{ 161{
166 struct datapath *dp = container_of(rcu, struct datapath, rcu); 162 struct datapath *dp = container_of(rcu, struct datapath, rcu);
167 163
168 ovs_flow_tbl_destroy((__force struct flow_table *)dp->table, false); 164 ovs_flow_tbl_destroy(&dp->table);
169 free_percpu(dp->stats_percpu); 165 free_percpu(dp->stats_percpu);
170 release_net(ovs_dp_get_net(dp)); 166 release_net(ovs_dp_get_net(dp));
171 kfree(dp->ports); 167 kfree(dp->ports);
@@ -225,6 +221,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
225 struct dp_stats_percpu *stats; 221 struct dp_stats_percpu *stats;
226 struct sw_flow_key key; 222 struct sw_flow_key key;
227 u64 *stats_counter; 223 u64 *stats_counter;
224 u32 n_mask_hit;
228 int error; 225 int error;
229 226
230 stats = this_cpu_ptr(dp->stats_percpu); 227 stats = this_cpu_ptr(dp->stats_percpu);
@@ -237,7 +234,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
237 } 234 }
238 235
239 /* Look up flow. */ 236 /* Look up flow. */
240 flow = ovs_flow_lookup(rcu_dereference(dp->table), &key); 237 flow = ovs_flow_tbl_lookup(&dp->table, &key, &n_mask_hit);
241 if (unlikely(!flow)) { 238 if (unlikely(!flow)) {
242 struct dp_upcall_info upcall; 239 struct dp_upcall_info upcall;
243 240
@@ -262,6 +259,7 @@ out:
262 /* Update datapath statistics. */ 259 /* Update datapath statistics. */
263 u64_stats_update_begin(&stats->sync); 260 u64_stats_update_begin(&stats->sync);
264 (*stats_counter)++; 261 (*stats_counter)++;
262 stats->n_mask_hit += n_mask_hit;
265 u64_stats_update_end(&stats->sync); 263 u64_stats_update_end(&stats->sync);
266} 264}
267 265
@@ -435,7 +433,7 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
435 upcall->dp_ifindex = dp_ifindex; 433 upcall->dp_ifindex = dp_ifindex;
436 434
437 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); 435 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY);
438 ovs_flow_to_nlattrs(upcall_info->key, upcall_info->key, user_skb); 436 ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb);
439 nla_nest_end(user_skb, nla); 437 nla_nest_end(user_skb, nla);
440 438
441 if (upcall_info->userdata) 439 if (upcall_info->userdata)
@@ -455,398 +453,6 @@ out:
455 return err; 453 return err;
456} 454}
457 455
458/* Called with ovs_mutex. */
459static int flush_flows(struct datapath *dp)
460{
461 struct flow_table *old_table;
462 struct flow_table *new_table;
463
464 old_table = ovsl_dereference(dp->table);
465 new_table = ovs_flow_tbl_alloc(TBL_MIN_BUCKETS);
466 if (!new_table)
467 return -ENOMEM;
468
469 rcu_assign_pointer(dp->table, new_table);
470
471 ovs_flow_tbl_destroy(old_table, true);
472 return 0;
473}
474
475static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa, int attr_len)
476{
477
478 struct sw_flow_actions *acts;
479 int new_acts_size;
480 int req_size = NLA_ALIGN(attr_len);
481 int next_offset = offsetof(struct sw_flow_actions, actions) +
482 (*sfa)->actions_len;
483
484 if (req_size <= (ksize(*sfa) - next_offset))
485 goto out;
486
487 new_acts_size = ksize(*sfa) * 2;
488
489 if (new_acts_size > MAX_ACTIONS_BUFSIZE) {
490 if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size)
491 return ERR_PTR(-EMSGSIZE);
492 new_acts_size = MAX_ACTIONS_BUFSIZE;
493 }
494
495 acts = ovs_flow_actions_alloc(new_acts_size);
496 if (IS_ERR(acts))
497 return (void *)acts;
498
499 memcpy(acts->actions, (*sfa)->actions, (*sfa)->actions_len);
500 acts->actions_len = (*sfa)->actions_len;
501 kfree(*sfa);
502 *sfa = acts;
503
504out:
505 (*sfa)->actions_len += req_size;
506 return (struct nlattr *) ((unsigned char *)(*sfa) + next_offset);
507}
508
509static int add_action(struct sw_flow_actions **sfa, int attrtype, void *data, int len)
510{
511 struct nlattr *a;
512
513 a = reserve_sfa_size(sfa, nla_attr_size(len));
514 if (IS_ERR(a))
515 return PTR_ERR(a);
516
517 a->nla_type = attrtype;
518 a->nla_len = nla_attr_size(len);
519
520 if (data)
521 memcpy(nla_data(a), data, len);
522 memset((unsigned char *) a + a->nla_len, 0, nla_padlen(len));
523
524 return 0;
525}
526
527static inline int add_nested_action_start(struct sw_flow_actions **sfa, int attrtype)
528{
529 int used = (*sfa)->actions_len;
530 int err;
531
532 err = add_action(sfa, attrtype, NULL, 0);
533 if (err)
534 return err;
535
536 return used;
537}