diff options
Diffstat (limited to 'net/openvswitch')
| -rw-r--r-- | net/openvswitch/datapath.c | 45 | ||||
| -rw-r--r-- | net/openvswitch/flow_netlink.c | 8 | ||||
| -rw-r--r-- | net/openvswitch/vport.h | 2 |
3 files changed, 52 insertions, 3 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index ae5e77cdc0ca..5bae7243c577 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -2194,14 +2194,55 @@ static int __net_init ovs_init_net(struct net *net) | |||
| 2194 | return 0; | 2194 | return 0; |
| 2195 | } | 2195 | } |
| 2196 | 2196 | ||
| 2197 | static void __net_exit ovs_exit_net(struct net *net) | 2197 | static void __net_exit list_vports_from_net(struct net *net, struct net *dnet, |
| 2198 | struct list_head *head) | ||
| 2198 | { | 2199 | { |
| 2199 | struct datapath *dp, *dp_next; | ||
| 2200 | struct ovs_net *ovs_net = net_generic(net, ovs_net_id); | 2200 | struct ovs_net *ovs_net = net_generic(net, ovs_net_id); |
| 2201 | struct datapath *dp; | ||
| 2202 | |||
| 2203 | list_for_each_entry(dp, &ovs_net->dps, list_node) { | ||
| 2204 | int i; | ||
| 2205 | |||
| 2206 | for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) { | ||
| 2207 | struct vport *vport; | ||
| 2208 | |||
| 2209 | hlist_for_each_entry(vport, &dp->ports[i], dp_hash_node) { | ||
| 2210 | struct netdev_vport *netdev_vport; | ||
| 2211 | |||
| 2212 | if (vport->ops->type != OVS_VPORT_TYPE_INTERNAL) | ||
| 2213 | continue; | ||
| 2214 | |||
| 2215 | netdev_vport = netdev_vport_priv(vport); | ||
| 2216 | if (dev_net(netdev_vport->dev) == dnet) | ||
| 2217 | list_add(&vport->detach_list, head); | ||
| 2218 | } | ||
| 2219 | } | ||
| 2220 | } | ||
| 2221 | } | ||
| 2222 | |||
| 2223 | static void __net_exit ovs_exit_net(struct net *dnet) | ||
| 2224 | { | ||
| 2225 | struct datapath *dp, *dp_next; | ||
| 2226 | struct ovs_net *ovs_net = net_generic(dnet, ovs_net_id); | ||
| 2227 | struct vport *vport, *vport_next; | ||
| 2228 | struct net *net; | ||
| 2229 | LIST_HEAD(head); | ||
| 2201 | 2230 | ||
| 2202 | ovs_lock(); | 2231 | ovs_lock(); |
| 2203 | list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node) | 2232 | list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node) |
| 2204 | __dp_destroy(dp); | 2233 | __dp_destroy(dp); |
| 2234 | |||
| 2235 | rtnl_lock(); | ||
| 2236 | for_each_net(net) | ||
| 2237 | list_vports_from_net(net, dnet, &head); | ||
| 2238 | rtnl_unlock(); | ||
| 2239 | |||
| 2240 | /* Detach all vports from given namespace. */ | ||
| 2241 | list_for_each_entry_safe(vport, vport_next, &head, detach_list) { | ||
| 2242 | list_del(&vport->detach_list); | ||
| 2243 | ovs_dp_detach_port(vport); | ||
| 2244 | } | ||
| 2245 | |||
| 2205 | ovs_unlock(); | 2246 | ovs_unlock(); |
| 2206 | 2247 | ||
| 2207 | cancel_work_sync(&ovs_net->dp_notify_work); | 2248 | cancel_work_sync(&ovs_net->dp_notify_work); |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 216f20b90aa5..22b18c145c92 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
| @@ -2253,14 +2253,20 @@ static int masked_set_action_to_set_action_attr(const struct nlattr *a, | |||
| 2253 | struct sk_buff *skb) | 2253 | struct sk_buff *skb) |
| 2254 | { | 2254 | { |
| 2255 | const struct nlattr *ovs_key = nla_data(a); | 2255 | const struct nlattr *ovs_key = nla_data(a); |
| 2256 | struct nlattr *nla; | ||
| 2256 | size_t key_len = nla_len(ovs_key) / 2; | 2257 | size_t key_len = nla_len(ovs_key) / 2; |
| 2257 | 2258 | ||
| 2258 | /* Revert the conversion we did from a non-masked set action to | 2259 | /* Revert the conversion we did from a non-masked set action to |
| 2259 | * masked set action. | 2260 | * masked set action. |
| 2260 | */ | 2261 | */ |
| 2261 | if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a) - key_len, ovs_key)) | 2262 | nla = nla_nest_start(skb, OVS_ACTION_ATTR_SET); |
| 2263 | if (!nla) | ||
| 2262 | return -EMSGSIZE; | 2264 | return -EMSGSIZE; |
| 2263 | 2265 | ||
| 2266 | if (nla_put(skb, nla_type(ovs_key), key_len, nla_data(ovs_key))) | ||
| 2267 | return -EMSGSIZE; | ||
| 2268 | |||
| 2269 | nla_nest_end(skb, nla); | ||
| 2264 | return 0; | 2270 | return 0; |
| 2265 | } | 2271 | } |
| 2266 | 2272 | ||
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index f8ae295fb001..bc85331a6c60 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h | |||
| @@ -103,6 +103,7 @@ struct vport_portids { | |||
| 103 | * @ops: Class structure. | 103 | * @ops: Class structure. |
| 104 | * @percpu_stats: Points to per-CPU statistics used and maintained by vport | 104 | * @percpu_stats: Points to per-CPU statistics used and maintained by vport |
| 105 | * @err_stats: Points to error statistics used and maintained by vport | 105 | * @err_stats: Points to error statistics used and maintained by vport |
| 106 | * @detach_list: list used for detaching vport in net-exit call. | ||
| 106 | */ | 107 | */ |
| 107 | struct vport { | 108 | struct vport { |
| 108 | struct rcu_head rcu; | 109 | struct rcu_head rcu; |
| @@ -117,6 +118,7 @@ struct vport { | |||
| 117 | struct pcpu_sw_netstats __percpu *percpu_stats; | 118 | struct pcpu_sw_netstats __percpu *percpu_stats; |
| 118 | 119 | ||
| 119 | struct vport_err_stats err_stats; | 120 | struct vport_err_stats err_stats; |
| 121 | struct list_head detach_list; | ||
| 120 | }; | 122 | }; |
| 121 | 123 | ||
| 122 | /** | 124 | /** |
