aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch/datapath.c
diff options
context:
space:
mode:
authorAndy Zhou <azhou@nicira.com>2013-08-07 23:01:00 -0400
committerJesse Gross <jesse@nicira.com>2013-08-23 19:43:07 -0400
commit03f0d916aa0317592dda11bd17c7357858719b6c (patch)
tree436f94d9c4846cadfa73ee0822f44a6383f3a2f3 /net/openvswitch/datapath.c
parent3fa34de67861abfc4846ccec886ca549d46ae56c (diff)
openvswitch: Mega flow implementation
Add wildcarded flow support in kernel datapath. Wildcarded flow can improve OVS flow set up performance by avoid sending matching new flows to the user space program. The exact performance boost will largely dependent on wildcarded flow hit rate. In case all new flows hits wildcard flows, the flow set up rate is within 5% of that of linux bridge module. Pravin has made significant contributions to this patch. Including API clean ups and bug fixes. Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Signed-off-by: Andy Zhou <azhou@nicira.com> Signed-off-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r--net/openvswitch/datapath.c140
1 files changed, 100 insertions, 40 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 9d97ef3c9830..d29cd9aa4a67 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2007-2012 Nicira, Inc. 2 * Copyright (c) 2007-2013 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
@@ -165,7 +165,7 @@ static void destroy_dp_rcu(struct rcu_head *rcu)
165{ 165{
166 struct datapath *dp = container_of(rcu, struct datapath, rcu); 166 struct datapath *dp = container_of(rcu, struct datapath, rcu);
167 167
168 ovs_flow_tbl_destroy((__force struct flow_table *)dp->table); 168 ovs_flow_tbl_destroy((__force struct flow_table *)dp->table, false);
169 free_percpu(dp->stats_percpu); 169 free_percpu(dp->stats_percpu);
170 release_net(ovs_dp_get_net(dp)); 170 release_net(ovs_dp_get_net(dp));
171 kfree(dp->ports); 171 kfree(dp->ports);
@@ -226,19 +226,18 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
226 struct sw_flow_key key; 226 struct sw_flow_key key;
227 u64 *stats_counter; 227 u64 *stats_counter;
228 int error; 228 int error;
229 int key_len;
230 229
231 stats = this_cpu_ptr(dp->stats_percpu); 230 stats = this_cpu_ptr(dp->stats_percpu);
232 231
233 /* Extract flow from 'skb' into 'key'. */ 232 /* Extract flow from 'skb' into 'key'. */
234 error = ovs_flow_extract(skb, p->port_no, &key, &key_len); 233 error = ovs_flow_extract(skb, p->port_no, &key);
235 if (unlikely(error)) { 234 if (unlikely(error)) {
236 kfree_skb(skb); 235 kfree_skb(skb);
237 return; 236 return;
238 } 237 }
239 238
240 /* Look up flow. */ 239 /* Look up flow. */
241 flow = ovs_flow_tbl_lookup(rcu_dereference(dp->table), &key, key_len); 240 flow = ovs_flow_lookup(rcu_dereference(dp->table), &key);
242 if (unlikely(!flow)) { 241 if (unlikely(!flow)) {
243 struct dp_upcall_info upcall; 242 struct dp_upcall_info upcall;
244 243
@@ -253,6 +252,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
253 } 252 }
254 253
255 OVS_CB(skb)->flow = flow; 254 OVS_CB(skb)->flow = flow;
255 OVS_CB(skb)->pkt_key = &key;
256 256
257 stats_counter = &stats->n_hit; 257 stats_counter = &stats->n_hit;
258 ovs_flow_used(OVS_CB(skb)->flow, skb); 258 ovs_flow_used(OVS_CB(skb)->flow, skb);
@@ -435,7 +435,7 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
435 upcall->dp_ifindex = dp_ifindex; 435 upcall->dp_ifindex = dp_ifindex;
436 436
437 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); 437 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY);
438 ovs_flow_to_nlattrs(upcall_info->key, user_skb); 438 ovs_flow_to_nlattrs(upcall_info->key, upcall_info->key, user_skb);
439 nla_nest_end(user_skb, nla); 439 nla_nest_end(user_skb, nla);
440 440
441 if (upcall_info->userdata) 441 if (upcall_info->userdata)
@@ -468,7 +468,7 @@ static int flush_flows(struct datapath *dp)
468 468
469 rcu_assign_pointer(dp->table, new_table); 469 rcu_assign_pointer(dp->table, new_table);
470 470
471 ovs_flow_tbl_deferred_destroy(old_table); 471 ovs_flow_tbl_destroy(old_table, true);
472 return 0; 472 return 0;
473} 473}
474 474
@@ -611,10 +611,12 @@ static int validate_tp_port(const struct sw_flow_key *flow_key)
611static int validate_and_copy_set_tun(const struct nlattr *attr, 611static int validate_and_copy_set_tun(const struct nlattr *attr,
612 struct sw_flow_actions **sfa) 612 struct sw_flow_actions **sfa)
613{ 613{
614 struct ovs_key_ipv4_tunnel tun_key; 614 struct sw_flow_match match;
615 struct sw_flow_key key;
615 int err, start; 616 int err, start;
616 617
617 err = ovs_ipv4_tun_from_nlattr(nla_data(attr), &tun_key); 618 ovs_match_init(&match, &key, NULL);
619 err = ovs_ipv4_tun_from_nlattr(nla_data(attr), &match, false);
618 if (err) 620 if (err)
619 return err; 621 return err;
620 622
@@ -622,7 +624,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
622 if (start < 0) 624 if (start < 0)
623 return start; 625 return start;
624 626
625 err = add_action(sfa, OVS_KEY_ATTR_IPV4_TUNNEL, &tun_key, sizeof(tun_key)); 627 err = add_action(sfa, OVS_KEY_ATTR_IPV4_TUNNEL, &match.key->tun_key,
628 sizeof(match.key->tun_key));
626 add_nested_action_end(*sfa, start); 629 add_nested_action_end(*sfa, start);
627 630
628 return err; 631 return err;
@@ -857,7 +860,6 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
857 struct ethhdr *eth; 860 struct ethhdr *eth;
858 int len; 861 int len;
859 int err; 862 int err;
860 int key_len;
861 863
862 err = -EINVAL; 864 err = -EINVAL;
863 if (!a[OVS_PACKET_ATTR_PACKET] || !a[OVS_PACKET_ATTR_KEY] || 865 if (!a[OVS_PACKET_ATTR_PACKET] || !a[OVS_PACKET_ATTR_KEY] ||
@@ -890,11 +892,11 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
890 if (IS_ERR(flow)) 892 if (IS_ERR(flow))
891 goto err_kfree_skb; 893 goto err_kfree_skb;
892 894
893 err = ovs_flow_extract(packet, -1, &flow->key, &key_len); 895 err = ovs_flow_extract(packet, -1, &flow->key);
894 if (err) 896 if (err)
895 goto err_flow_free; 897 goto err_flow_free;
896 898
897 err = ovs_flow_metadata_from_nlattrs(flow, key_len, a[OVS_PACKET_ATTR_KEY]); 899 err = ovs_flow_metadata_from_nlattrs(flow, a[OVS_PACKET_ATTR_KEY]);
898 if (err) 900 if (err)
899 goto err_flow_free; 901 goto err_flow_free;
900 acts = ovs_flow_actions_alloc(nla_len(a[OVS_PACKET_ATTR_ACTIONS])); 902 acts = ovs_flow_actions_alloc(nla_len(a[OVS_PACKET_ATTR_ACTIONS]));
@@ -908,6 +910,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
908 goto err_flow_free; 910 goto err_flow_free;
909 911
910 OVS_CB(packet)->flow = flow; 912 OVS_CB(packet)->flow = flow;
913 OVS_CB(packet)->pkt_key = &flow->key;
911 packet->priority = flow->key.phy.priority; 914 packet->priority = flow->key.phy.priority;
912 packet->mark = flow->key.phy.skb_mark; 915 packet->mark = flow->key.phy.skb_mark;
913 916
@@ -922,13 +925,13 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
922 local_bh_enable(); 925 local_bh_enable();
923 rcu_read_unlock(); 926 rcu_read_unlock();
924 927
925 ovs_flow_free(flow); 928 ovs_flow_free(flow, false);
926 return err; 929 return err;
927 930
928err_unlock: 931err_unlock:
929 rcu_read_unlock(); 932 rcu_read_unlock();
930err_flow_free: 933err_flow_free:
931 ovs_flow_free(flow); 934 ovs_flow_free(flow, false);
932err_kfree_skb: 935err_kfree_skb:
933 kfree_skb(packet); 936 kfree_skb(packet);
934err: 937err:
@@ -1045,7 +1048,8 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
1045 if (!start) 1048 if (!start)
1046 return -EMSGSIZE; 1049 return -EMSGSIZE;
1047 1050
1048 err = ovs_ipv4_tun_to_nlattr(skb, nla_data(ovs_key)); 1051 err = ovs_ipv4_tun_to_nlattr(skb, nla_data(ovs_key),
1052 nla_data(ovs_key));
1049 if (err) 1053 if (err)
1050 return err; 1054 return err;
1051 nla_nest_end(skb, start); 1055 nla_nest_end(skb, start);
@@ -1093,6 +1097,7 @@ static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts)
1093{ 1097{
1094 return NLMSG_ALIGN(sizeof(struct ovs_header)) 1098 return NLMSG_ALIGN(sizeof(struct ovs_header))
1095 + nla_total_size(key_attr_size()) /* OVS_FLOW_ATTR_KEY */ 1099 + nla_total_size(key_attr_size()) /* OVS_FLOW_ATTR_KEY */
1100 + nla_total_size(key_attr_size()) /* OVS_FLOW_ATTR_MASK */
1096 + nla_total_size(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */ 1101 + nla_total_size(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */
1097 + nla_total_size(1) /* OVS_FLOW_ATTR_TCP_FLAGS */ 1102 + nla_total_size(1) /* OVS_FLOW_ATTR_TCP_FLAGS */
1098 + nla_total_size(8) /* OVS_FLOW_ATTR_USED */ 1103 + nla_total_size(8) /* OVS_FLOW_ATTR_USED */
@@ -1119,12 +1124,25 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
1119 1124
1120 ovs_header->dp_ifindex = get_dpifindex(dp); 1125 ovs_header->dp_ifindex = get_dpifindex(dp);
1121 1126
1127 /* Fill flow key. */
1122 nla = nla_nest_start(skb, OVS_FLOW_ATTR_KEY); 1128 nla = nla_nest_start(skb, OVS_FLOW_ATTR_KEY);
1123 if (!nla) 1129 if (!nla)
1124 goto nla_put_failure; 1130 goto nla_put_failure;
1125 err = ovs_flow_to_nlattrs(&flow->key, skb); 1131
1132 err = ovs_flow_to_nlattrs(&flow->unmasked_key,
1133 &flow->unmasked_key, skb);
1134 if (err)
1135 goto error;
1136 nla_nest_end(skb, nla);
1137
1138 nla = nla_nest_start(skb, OVS_FLOW_ATTR_MASK);
1139 if (!nla)
1140 goto nla_put_failure;
1141
1142 err = ovs_flow_to_nlattrs(&flow->key, &flow->mask->key, skb);
1126 if (err) 1143 if (err)
1127 goto error; 1144 goto error;
1145
1128 nla_nest_end(skb, nla); 1146 nla_nest_end(skb, nla);
1129 1147
1130 spin_lock_bh(&flow->lock); 1148 spin_lock_bh(&flow->lock);
@@ -1214,20 +1232,24 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
1214{ 1232{
1215 struct nlattr **a = info->attrs; 1233 struct nlattr **a = info->attrs;
1216 struct ovs_header *ovs_header = info->userhdr; 1234 struct ovs_header *ovs_header = info->userhdr;
1217 struct sw_flow_key key; 1235 struct sw_flow_key key, masked_key;
1218 struct sw_flow *flow; 1236 struct sw_flow *flow = NULL;
1237 struct sw_flow_mask mask;
1219 struct sk_buff *reply; 1238 struct sk_buff *reply;
1220 struct datapath *dp; 1239 struct datapath *dp;
1221 struct flow_table *table; 1240 struct flow_table *table;
1222 struct sw_flow_actions *acts = NULL; 1241 struct sw_flow_actions *acts = NULL;
1242 struct sw_flow_match match;
1223 int error; 1243 int error;
1224 int key_len;
1225 1244
1226 /* Extract key. */ 1245 /* Extract key. */
1227 error = -EINVAL; 1246 error = -EINVAL;
1228 if (!a[OVS_FLOW_ATTR_KEY]) 1247 if (!a[OVS_FLOW_ATTR_KEY])
1229 goto error; 1248 goto error;
1230 error = ovs_flow_from_nlattrs(&key, &key_len, a[OVS_FLOW_ATTR_KEY]); 1249
1250 ovs_match_init(&match, &key, &mask);
1251 error = ovs_match_from_nlattrs(&match,
1252 a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]);
1231 if (error) 1253 if (error)
1232 goto error; 1254 goto error;
1233 1255
@@ -1238,9 +1260,13 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
1238 if (IS_ERR(acts)) 1260 if (IS_ERR(acts))
1239 goto error; 1261 goto error;
1240 1262
1241 error = validate_and_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, 0, &acts); 1263 ovs_flow_key_mask(&masked_key, &key, &mask);
1242 if (error) 1264 error = validate_and_copy_actions(a[OVS_FLOW_ATTR_ACTIONS],
1265 &masked_key, 0, &acts);
1266 if (error) {
1267 OVS_NLERR("Flow actions may not be safe on all matching packets.\n");
1243 goto err_kfree; 1268 goto err_kfree;
1269 }
1244 } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) { 1270 } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) {
1245 error = -EINVAL; 1271 error = -EINVAL;
1246 goto error; 1272 goto error;
@@ -1253,8 +1279,11 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
1253 goto err_unlock_ovs; 1279 goto err_unlock_ovs;
1254 1280
1255 table = ovsl_dereference(dp->table); 1281 table = ovsl_dereference(dp->table);
1256 flow = ovs_flow_tbl_lookup(table, &key, key_len); 1282
1283 /* Check if this is a duplicate flow */
1284 flow = ovs_flow_lookup(table, &key);
1257 if (!flow) { 1285 if (!flow) {
1286 struct sw_flow_mask *mask_p;
1258 /* Bail out if we're not allowed to create a new flow. */ 1287 /* Bail out if we're not allowed to create a new flow. */
1259 error = -ENOENT; 1288 error = -ENOENT;
1260 if (info->genlhdr->cmd == OVS_FLOW_CMD_SET) 1289 if (info->genlhdr->cmd == OVS_FLOW_CMD_SET)
@@ -1267,7 +1296,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
1267 new_table = ovs_flow_tbl_expand(table); 1296 new_table = ovs_flow_tbl_expand(table);
1268 if (!IS_ERR(new_table)) { 1297 if (!IS_ERR(new_table)) {
1269 rcu_assign_pointer(dp->table, new_table); 1298 rcu_assign_pointer(dp->table, new_table);
1270 ovs_flow_tbl_deferred_destroy(table); 1299 ovs_flow_tbl_destroy(table, true);
1271 table = ovsl_dereference(dp->table); 1300 table = ovsl_dereference(dp->table);
1272 } 1301 }
1273 } 1302 }
@@ -1280,14 +1309,30 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
1280 } 1309 }
1281 clear_stats(flow); 1310 clear_stats(flow);
1282 1311
1312 flow->key = masked_key;
1313 flow->unmasked_key = key;
1314
1315 /* Make sure mask is unique in the system */
1316 mask_p = ovs_sw_flow_mask_find(table, &mask);
1317 if (!mask_p) {
1318 /* Allocate a new mask if none exsits. */
1319 mask_p = ovs_sw_flow_mask_alloc();
1320 if (!mask_p)
1321 goto err_flow_free;
1322 mask_p->key = mask.key;
1323 mask_p->range = mask.range;
1324 ovs_sw_flow_mask_insert(table, mask_p);
1325 }
1326
1327 ovs_sw_flow_mask_add_ref(mask_p);
1328 flow->mask = mask_p;
1283 rcu_assign_pointer(flow->sf_acts, acts); 1329 rcu_assign_pointer(flow->sf_acts, acts);
1284 1330
1285 /* Put flow in bucket. */ 1331 /* Put flow in bucket. */
1286 ovs_flow_tbl_insert(table, flow, &key, key_len); 1332 ovs_flow_insert(table, flow);
1287 1333
1288 reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, 1334 reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid,
1289 info->snd_seq, 1335 info->snd_seq, OVS_FLOW_CMD_NEW);
1290 OVS_FLOW_CMD_NEW);
1291 } else { 1336 } else {
1292 /* We found a matching flow. */ 1337 /* We found a matching flow. */
1293 struct sw_flow_actions *old_acts; 1338 struct sw_flow_actions *old_acts;
@@ -1303,6 +1348,13 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
1303 info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) 1348 info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL))
1304 goto err_unlock_ovs; 1349 goto err_unlock_ovs;
1305 1350
1351 /* The unmasked key has to be the same for flow updates. */
1352 error = -EINVAL;
1353 if (!ovs_flow_cmp_unmasked_key(flow, &key, match.range.end)) {
1354 OVS_NLERR("Flow modification message rejected, unmasked key does not match.\n");
1355 goto err_unlock_ovs;
1356 }
1357
1306 /* Update actions. */ 1358 /* Update actions. */
1307 old_acts = ovsl_dereference(flow->sf_acts); 1359 old_acts = ovsl_dereference(flow->sf_acts);
1308 rcu_assign_pointer(flow->sf_acts, acts); 1360 rcu_assign_pointer(flow->sf_acts, acts);
@@ -1327,6 +1379,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
1327 ovs_dp_flow_multicast_group.id, PTR_ERR(reply)); 1379 ovs_dp_flow_multicast_group.id, PTR_ERR(reply));
1328 return 0; 1380 return 0;
1329 1381
1382err_flow_free:
1383 ovs_flow_free(flow, false);
1330err_unlock_ovs: 1384err_unlock_ovs:
1331 ovs_unlock(); 1385 ovs_unlock();
1332err_kfree: 1386err_kfree:
@@ -1344,12 +1398,16 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
1344 struct sw_flow *flow; 1398 struct sw_flow *flow;
1345 struct datapath *dp; 1399 struct datapath *dp;
1346 struct flow_table *table; 1400 struct flow_table *table;
1401 struct sw_flow_match match;
1347 int err; 1402 int err;
1348 int key_len;
1349 1403
1350 if (!a[OVS_FLOW_ATTR_KEY]) 1404 if (!a[OVS_FLOW_ATTR_KEY]) {
1405 OVS_NLERR("Flow get message rejected, Key attribute missing.\n");
1351 return -EINVAL; 1406 return -EINVAL;
1352 err = ovs_flow_from_nlattrs(&key, &key_len, a[OVS_FLOW_ATTR_KEY]); 1407 }
1408
1409 ovs_match_init(&match, &key, NULL);
1410 err = ovs_match_from_nlattrs(&match, a[OVS_FLOW_ATTR_KEY], NULL);
1353 if (err) 1411 if (err)
1354 return err; 1412 return err;
1355 1413
@@ -1361,7 +1419,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
1361 } 1419 }
1362 1420
1363 table = ovsl_dereference(dp->table); 1421 table = ovsl_dereference(dp->table);
1364 flow = ovs_flow_tbl_lookup(table, &key, key_len); 1422 flow = ovs_flow_lookup_unmasked_key(table, &match);
1365 if (!flow) { 1423 if (!flow) {
1366 err = -ENOENT; 1424 err = -ENOENT;
1367 goto unlock; 1425 goto unlock;
@@ -1390,8 +1448,8 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
1390 struct sw_flow *flow; 1448 struct sw_flow *flow;
1391 struct datapath *dp; 1449 struct datapath *dp;
1392 struct flow_table *table; 1450 struct flow_table *table;
1451 struct sw_flow_match match;
1393 int err; 1452 int err;
1394 int key_len;
1395 1453
1396 ovs_lock(); 1454 ovs_lock();
1397 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); 1455 dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
@@ -1404,12 +1462,14 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
1404 err = flush_flows(dp); 1462 err = flush_flows(dp);
1405 goto unlock; 1463 goto unlock;
1406 } 1464 }
1407 err = ovs_flow_from_nlattrs(&key, &key_len, a[OVS_FLOW_ATTR_KEY]); 1465
1466 ovs_match_init(&match, &key, NULL);
1467 err = ovs_match_from_nlattrs(&match, a[OVS_FLOW_ATTR_KEY], NULL);
1408 if (err) 1468 if (err)
1409 goto unlock; 1469 goto unlock;
1410 1470
1411 table = ovsl_dereference(dp->table); 1471 table = ovsl_dereference(dp->table);
1412 flow = ovs_flow_tbl_lookup(table, &key, key_len); 1472 flow = ovs_flow_lookup_unmasked_key(table, &match);
1413 if (!flow) { 1473 if (!flow) {
1414 err = -ENOENT; 1474 err = -ENOENT;
1415 goto unlock; 1475 goto unlock;
@@ -1421,13 +1481,13 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
1421 goto unlock; 1481 goto unlock;
1422 } 1482 }
1423 1483
1424 ovs_flow_tbl_remove(table, flow); 1484 ovs_flow_remove(table, flow);
1425 1485
1426 err = ovs_flow_cmd_fill_info(flow, dp, reply, info->snd_portid, 1486 err = ovs_flow_cmd_fill_info(flow, dp, reply, info->snd_portid,
1427 info->snd_seq, 0, OVS_FLOW_CMD_DEL); 1487 info->snd_seq, 0, OVS_FLOW_CMD_DEL);
1428 BUG_ON(err < 0); 1488 BUG_ON(err < 0);
1429 1489
1430 ovs_flow_deferred_free(flow); 1490 ovs_flow_free(flow, true);
1431 ovs_unlock(); 1491 ovs_unlock();
1432 1492
1433 ovs_notify(reply, info, &ovs_dp_flow_multicast_group); 1493 ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
@@ -1457,7 +1517,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
1457 1517
1458 bucket = cb->args[0]; 1518 bucket = cb->args[0];
1459 obj = cb->args[1]; 1519 obj = cb->args[1];
1460 flow = ovs_flow_tbl_next(table, &bucket, &obj); 1520 flow = ovs_flow_dump_next(table, &bucket, &obj);
1461 if (!flow) 1521 if (!flow)
1462 break; 1522 break;
1463 1523
@@ -1680,7 +1740,7 @@ err_destroy_ports_array:
1680err_destroy_percpu: 1740err_destroy_percpu:
1681 free_percpu(dp->stats_percpu); 1741 free_percpu(dp->stats_percpu);
1682err_destroy_table: 1742err_destroy_table:
1683 ovs_flow_tbl_destroy(ovsl_dereference(dp->table)); 1743 ovs_flow_tbl_destroy(ovsl_dereference(dp->table), false);
1684err_free_dp: 1744err_free_dp:
1685 release_net(ovs_dp_get_net(dp)); 1745 release_net(ovs_dp_get_net(dp));
1686 kfree(dp); 1746 kfree(dp);
@@ -2287,7 +2347,7 @@ static void rehash_flow_table(struct work_struct *work)
2287 new_table = ovs_flow_tbl_rehash(old_table); 2347 new_table = ovs_flow_tbl_rehash(old_table);
2288 if (!IS_ERR(new_table)) { 2348 if (!IS_ERR(new_table)) {
2289 rcu_assign_pointer(dp->table, new_table); 2349 rcu_assign_pointer(dp->table, new_table);
2290 ovs_flow_tbl_deferred_destroy(old_table); 2350 ovs_flow_tbl_destroy(old_table, true);
2291 } 2351 }
2292 } 2352 }
2293 } 2353 }