diff options
| author | David S. Miller <davem@davemloft.net> | 2013-11-04 16:25:04 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-11-04 16:25:04 -0500 |
| commit | 6fcf018ae4491dc11b080892fa9f3dbd928fdbb9 (patch) | |
| tree | f28592676e295183581d59149fd1eac913b229a2 /net | |
| parent | 5a6e55c461db3364aa5be919101db972bc859133 (diff) | |
| parent | 8ddd094675cfd453fc9838caa46ea108a4107183 (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/Makefile | 2 | ||||
| -rw-r--r-- | net/openvswitch/datapath.c | 668 | ||||
| -rw-r--r-- | net/openvswitch/datapath.h | 9 | ||||
| -rw-r--r-- | net/openvswitch/flow.c | 1605 | ||||
| -rw-r--r-- | net/openvswitch/flow.h | 132 | ||||
| -rw-r--r-- | net/openvswitch/flow_netlink.c | 1630 | ||||
| -rw-r--r-- | net/openvswitch/flow_netlink.h | 60 | ||||
| -rw-r--r-- | net/openvswitch/flow_table.c | 592 | ||||
| -rw-r--r-- | net/openvswitch/flow_table.h | 81 | ||||
| -rw-r--r-- | net/openvswitch/vport-gre.c | 2 | ||||
| -rw-r--r-- | net/openvswitch/vport-internal_dev.c | 2 | ||||
| -rw-r--r-- | net/openvswitch/vport-vxlan.c | 1 |
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) | ||
| 63 | static void rehash_flow_table(struct work_struct *work); | ||
| 64 | static DECLARE_DELAYED_WORK(rehash_flow_wq, rehash_flow_table); | ||
| 65 | |||
| 66 | int ovs_net_id __read_mostly; | 62 | int ovs_net_id __read_mostly; |
| 67 | 63 | ||
| 68 | static void ovs_notify(struct sk_buff *skb, struct genl_info *info, | 64 | static 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. */ | ||
| 459 | static 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 | |||
| 475 | static 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 | |||
| 504 | out: | ||
| 505 | (*sfa)->actions_len += req_size; | ||
| 506 | return (struct nlattr *) ((unsigned char *)(*sfa) + next_offset); | ||
| 507 | } | ||
| 508 | |||
| 509 | static 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 | |||
| 527 | static 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 | } | ||
