diff options
| author | Pravin B Shelar <pshelar@nicira.com> | 2013-09-17 12:38:23 -0400 |
|---|---|---|
| committer | Jesse Gross <jesse@nicira.com> | 2013-09-17 12:38:23 -0400 |
| commit | e7f133290660d976da8cb20e9bc7310d0cd19341 (patch) | |
| tree | c4eb7687f7aeb2c20a3e23006d811a7495ca9ed4 /net/openvswitch | |
| parent | 272b98c6455f00884f0350f775c5342358ebb73f (diff) | |
openvswitch: Move flow table rehashing to flow install.
Rehashing in ovs-workqueue can cause ovs-mutex lock contentions
in case of heavy flow setups where both needs ovs-mutex. So by
moving rehashing to flow-setup we can eliminate contention.
This also simplify ovs locking and reduces dependence on
workqueue.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'net/openvswitch')
| -rw-r--r-- | net/openvswitch/datapath.c | 50 | ||||
| -rw-r--r-- | net/openvswitch/datapath.h | 2 |
2 files changed, 13 insertions, 39 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 2aa13bd7f2b2..2e1a9c24e380 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -60,8 +60,6 @@ | |||
| 60 | 60 | ||
| 61 | 61 | ||
| 62 | #define REHASH_FLOW_INTERVAL (10 * 60 * HZ) | 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 | 63 | ||
| 66 | int ovs_net_id __read_mostly; | 64 | int ovs_net_id __read_mostly; |
| 67 | 65 | ||
| @@ -1289,22 +1287,25 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
| 1289 | /* Check if this is a duplicate flow */ | 1287 | /* Check if this is a duplicate flow */ |
| 1290 | flow = ovs_flow_lookup(table, &key); | 1288 | flow = ovs_flow_lookup(table, &key); |
| 1291 | if (!flow) { | 1289 | if (!flow) { |
| 1290 | struct flow_table *new_table = NULL; | ||
| 1292 | struct sw_flow_mask *mask_p; | 1291 | struct sw_flow_mask *mask_p; |
| 1292 | |||
| 1293 | /* Bail out if we're not allowed to create a new flow. */ | 1293 | /* Bail out if we're not allowed to create a new flow. */ |
| 1294 | error = -ENOENT; | 1294 | error = -ENOENT; |
| 1295 | if (info->genlhdr->cmd == OVS_FLOW_CMD_SET) | 1295 | if (info->genlhdr->cmd == OVS_FLOW_CMD_SET) |
| 1296 | goto err_unlock_ovs; | 1296 | goto err_unlock_ovs; |
| 1297 | 1297 | ||
| 1298 | /* Expand table, if necessary, to make room. */ | 1298 | /* Expand table, if necessary, to make room. */ |
| 1299 | if (ovs_flow_tbl_need_to_expand(table)) { | 1299 | if (ovs_flow_tbl_need_to_expand(table)) |
| 1300 | struct flow_table *new_table; | ||
| 1301 | |||
| 1302 | new_table = ovs_flow_tbl_expand(table); | 1300 | new_table = ovs_flow_tbl_expand(table); |
| 1303 | if (!IS_ERR(new_table)) { | 1301 | else if (time_after(jiffies, dp->last_rehash + REHASH_FLOW_INTERVAL)) |
| 1304 | rcu_assign_pointer(dp->table, new_table); | 1302 | new_table = ovs_flow_tbl_rehash(table); |
| 1305 | ovs_flow_tbl_destroy(table, true); | 1303 | |
| 1306 | table = ovsl_dereference(dp->table); | 1304 | if (new_table && !IS_ERR(new_table)) { |
| 1307 | } | 1305 | rcu_assign_pointer(dp->table, new_table); |
| 1306 | ovs_flow_tbl_destroy(table, true); | ||
| 1307 | table = ovsl_dereference(dp->table); | ||
| 1308 | dp->last_rehash = jiffies; | ||
| 1308 | } | 1309 | } |
| 1309 | 1310 | ||
| 1310 | /* Allocate flow. */ | 1311 | /* Allocate flow. */ |
| @@ -2336,32 +2337,6 @@ error: | |||
| 2336 | return err; | 2337 | return err; |
| 2337 | } | 2338 | } |
| 2338 | 2339 | ||
| 2339 | static void rehash_flow_table(struct work_struct *work) | ||
| 2340 | { | ||
| 2341 | struct datapath *dp; | ||
| 2342 | struct net *net; | ||
| 2343 | |||
| 2344 | ovs_lock(); | ||
| 2345 | rtnl_lock(); | ||
| 2346 | for_each_net(net) { | ||
| 2347 | struct ovs_net *ovs_net = net_generic(net, ovs_net_id); | ||
| 2348 | |||
| 2349 | list_for_each_entry(dp, &ovs_net->dps, list_node) { | ||
| 2350 | struct flow_table *old_table = ovsl_dereference(dp->table); | ||
| 2351 | struct flow_table *new_table; | ||
| 2352 | |||
| 2353 | new_table = ovs_flow_tbl_rehash(old_table); | ||
| 2354 | if (!IS_ERR(new_table)) { | ||
| 2355 | rcu_assign_pointer(dp->table, new_table); | ||
| 2356 | ovs_flow_tbl_destroy(old_table, true); | ||
| 2357 | } | ||
| 2358 | } | ||
| 2359 | } | ||
| 2360 | rtnl_unlock(); | ||
| 2361 | ovs_unlock(); | ||
| 2362 | schedule_delayed_work(&rehash_flow_wq, REHASH_FLOW_INTERVAL); | ||
| 2363 | } | ||
| 2364 | |||
| 2365 | static int __net_init ovs_init_net(struct net *net) | 2340 | static int __net_init ovs_init_net(struct net *net) |
| 2366 | { | 2341 | { |
| 2367 | struct ovs_net *ovs_net = net_generic(net, ovs_net_id); | 2342 | struct ovs_net *ovs_net = net_generic(net, ovs_net_id); |
| @@ -2419,8 +2394,6 @@ static int __init dp_init(void) | |||
| 2419 | if (err < 0) | 2394 | if (err < 0) |
| 2420 | goto error_unreg_notifier; | 2395 | goto error_unreg_notifier; |
| 2421 | 2396 | ||
| 2422 | schedule_delayed_work(&rehash_flow_wq, REHASH_FLOW_INTERVAL); | ||
| 2423 | |||
| 2424 | return 0; | 2397 | return 0; |
| 2425 | 2398 | ||
| 2426 | error_unreg_notifier: | 2399 | error_unreg_notifier: |
| @@ -2437,7 +2410,6 @@ error: | |||
| 2437 | 2410 | ||
| 2438 | static void dp_cleanup(void) | 2411 | static void dp_cleanup(void) |
| 2439 | { | 2412 | { |
| 2440 | cancel_delayed_work_sync(&rehash_flow_wq); | ||
| 2441 | dp_unregister_genl(ARRAY_SIZE(dp_genl_families)); | 2413 | dp_unregister_genl(ARRAY_SIZE(dp_genl_families)); |
| 2442 | unregister_netdevice_notifier(&ovs_dp_device_notifier); | 2414 | unregister_netdevice_notifier(&ovs_dp_device_notifier); |
| 2443 | unregister_pernet_device(&ovs_net_ops); | 2415 | unregister_pernet_device(&ovs_net_ops); |
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index 4d109c176ef3..2c15541f3b46 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h | |||
| @@ -62,6 +62,7 @@ struct dp_stats_percpu { | |||
| 62 | * ovs_mutex and RCU. | 62 | * ovs_mutex and RCU. |
| 63 | * @stats_percpu: Per-CPU datapath statistics. | 63 | * @stats_percpu: Per-CPU datapath statistics. |
| 64 | * @net: Reference to net namespace. | 64 | * @net: Reference to net namespace. |
| 65 | * @last_rehash: Timestamp of last rehash. | ||
| 65 | * | 66 | * |
| 66 | * Context: See the comment on locking at the top of datapath.c for additional | 67 | * Context: See the comment on locking at the top of datapath.c for additional |
| 67 | * locking information. | 68 | * locking information. |
| @@ -83,6 +84,7 @@ struct datapath { | |||
| 83 | /* Network namespace ref. */ | 84 | /* Network namespace ref. */ |
| 84 | struct net *net; | 85 | struct net *net; |
| 85 | #endif | 86 | #endif |
| 87 | unsigned long last_rehash; | ||
| 86 | }; | 88 | }; |
| 87 | 89 | ||
| 88 | /** | 90 | /** |
