diff options
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r-- | net/openvswitch/datapath.c | 140 |
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) | |||
611 | static int validate_and_copy_set_tun(const struct nlattr *attr, | 611 | static 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 | ||
928 | err_unlock: | 931 | err_unlock: |
929 | rcu_read_unlock(); | 932 | rcu_read_unlock(); |
930 | err_flow_free: | 933 | err_flow_free: |
931 | ovs_flow_free(flow); | 934 | ovs_flow_free(flow, false); |
932 | err_kfree_skb: | 935 | err_kfree_skb: |
933 | kfree_skb(packet); | 936 | kfree_skb(packet); |
934 | err: | 937 | err: |
@@ -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 | ||
1382 | err_flow_free: | ||
1383 | ovs_flow_free(flow, false); | ||
1330 | err_unlock_ovs: | 1384 | err_unlock_ovs: |
1331 | ovs_unlock(); | 1385 | ovs_unlock(); |
1332 | err_kfree: | 1386 | err_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: | |||
1680 | err_destroy_percpu: | 1740 | err_destroy_percpu: |
1681 | free_percpu(dp->stats_percpu); | 1741 | free_percpu(dp->stats_percpu); |
1682 | err_destroy_table: | 1742 | err_destroy_table: |
1683 | ovs_flow_tbl_destroy(ovsl_dereference(dp->table)); | 1743 | ovs_flow_tbl_destroy(ovsl_dereference(dp->table), false); |
1684 | err_free_dp: | 1744 | err_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 | } |