diff options
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r-- | net/openvswitch/datapath.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index df4692826ead..e9a48baf8551 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -55,6 +55,7 @@ | |||
55 | 55 | ||
56 | #include "datapath.h" | 56 | #include "datapath.h" |
57 | #include "flow.h" | 57 | #include "flow.h" |
58 | #include "flow_table.h" | ||
58 | #include "flow_netlink.h" | 59 | #include "flow_netlink.h" |
59 | #include "vport-internal_dev.h" | 60 | #include "vport-internal_dev.h" |
60 | #include "vport-netdev.h" | 61 | #include "vport-netdev.h" |
@@ -160,7 +161,6 @@ static void destroy_dp_rcu(struct rcu_head *rcu) | |||
160 | { | 161 | { |
161 | struct datapath *dp = container_of(rcu, struct datapath, rcu); | 162 | struct datapath *dp = container_of(rcu, struct datapath, rcu); |
162 | 163 | ||
163 | ovs_flow_tbl_destroy(&dp->table); | ||
164 | free_percpu(dp->stats_percpu); | 164 | free_percpu(dp->stats_percpu); |
165 | release_net(ovs_dp_get_net(dp)); | 165 | release_net(ovs_dp_get_net(dp)); |
166 | kfree(dp->ports); | 166 | kfree(dp->ports); |
@@ -466,6 +466,14 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
466 | 466 | ||
467 | skb_zerocopy(user_skb, skb, skb->len, hlen); | 467 | skb_zerocopy(user_skb, skb, skb->len, hlen); |
468 | 468 | ||
469 | /* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */ | ||
470 | if (!(dp->user_features & OVS_DP_F_UNALIGNED)) { | ||
471 | size_t plen = NLA_ALIGN(user_skb->len) - user_skb->len; | ||
472 | |||
473 | if (plen > 0) | ||
474 | memset(skb_put(user_skb, plen), 0, plen); | ||
475 | } | ||
476 | |||
469 | ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len; | 477 | ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len; |
470 | 478 | ||
471 | err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); | 479 | err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); |
@@ -852,11 +860,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
852 | goto err_unlock_ovs; | 860 | goto err_unlock_ovs; |
853 | 861 | ||
854 | /* The unmasked key has to be the same for flow updates. */ | 862 | /* The unmasked key has to be the same for flow updates. */ |
855 | error = -EINVAL; | 863 | if (!ovs_flow_cmp_unmasked_key(flow, &match)) |
856 | if (!ovs_flow_cmp_unmasked_key(flow, &match)) { | ||
857 | OVS_NLERR("Flow modification message rejected, unmasked key does not match.\n"); | ||
858 | goto err_unlock_ovs; | 864 | goto err_unlock_ovs; |
859 | } | ||
860 | 865 | ||
861 | /* Update actions. */ | 866 | /* Update actions. */ |
862 | old_acts = ovsl_dereference(flow->sf_acts); | 867 | old_acts = ovsl_dereference(flow->sf_acts); |
@@ -1079,6 +1084,7 @@ static size_t ovs_dp_cmd_msg_size(void) | |||
1079 | msgsize += nla_total_size(IFNAMSIZ); | 1084 | msgsize += nla_total_size(IFNAMSIZ); |
1080 | msgsize += nla_total_size(sizeof(struct ovs_dp_stats)); | 1085 | msgsize += nla_total_size(sizeof(struct ovs_dp_stats)); |
1081 | msgsize += nla_total_size(sizeof(struct ovs_dp_megaflow_stats)); | 1086 | msgsize += nla_total_size(sizeof(struct ovs_dp_megaflow_stats)); |
1087 | msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */ | ||
1082 | 1088 | ||
1083 | return msgsize; | 1089 | return msgsize; |
1084 | } | 1090 | } |
@@ -1279,7 +1285,7 @@ err_destroy_ports_array: | |||
1279 | err_destroy_percpu: | 1285 | err_destroy_percpu: |
1280 | free_percpu(dp->stats_percpu); | 1286 | free_percpu(dp->stats_percpu); |
1281 | err_destroy_table: | 1287 | err_destroy_table: |
1282 | ovs_flow_tbl_destroy(&dp->table); | 1288 | ovs_flow_tbl_destroy(&dp->table, false); |
1283 | err_free_dp: | 1289 | err_free_dp: |
1284 | release_net(ovs_dp_get_net(dp)); | 1290 | release_net(ovs_dp_get_net(dp)); |
1285 | kfree(dp); | 1291 | kfree(dp); |
@@ -1306,10 +1312,13 @@ static void __dp_destroy(struct datapath *dp) | |||
1306 | list_del_rcu(&dp->list_node); | 1312 | list_del_rcu(&dp->list_node); |
1307 | 1313 | ||
1308 | /* OVSP_LOCAL is datapath internal port. We need to make sure that | 1314 | /* OVSP_LOCAL is datapath internal port. We need to make sure that |
1309 | * all port in datapath are destroyed first before freeing datapath. | 1315 | * all ports in datapath are destroyed first before freeing datapath. |
1310 | */ | 1316 | */ |
1311 | ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL)); | 1317 | ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL)); |
1312 | 1318 | ||
1319 | /* RCU destroy the flow table */ | ||
1320 | ovs_flow_tbl_destroy(&dp->table, true); | ||
1321 | |||
1313 | call_rcu(&dp->rcu, destroy_dp_rcu); | 1322 | call_rcu(&dp->rcu, destroy_dp_rcu); |
1314 | } | 1323 | } |
1315 | 1324 | ||