Blame view
net/openvswitch/dp_notify.c
2.67 KB
ccb1352e7
|
1 |
/* |
caf2ee14b
|
2 |
* Copyright (c) 2007-2012 Nicira, Inc. |
ccb1352e7
|
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
* * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA */ #include <linux/netdevice.h> #include <net/genetlink.h> |
8e4e1713e
|
21 |
#include <net/netns/generic.h> |
ccb1352e7
|
22 23 24 25 |
#include "datapath.h" #include "vport-internal_dev.h" #include "vport-netdev.h" |
8e4e1713e
|
26 27 28 29 30 31 32 33 34 35 |
static void dp_detach_port_notify(struct vport *vport) { struct sk_buff *notify; struct datapath *dp; dp = vport->dp; notify = ovs_vport_cmd_build_info(vport, 0, 0, OVS_VPORT_CMD_DEL); ovs_dp_detach_port(vport); if (IS_ERR(notify)) { |
68eb55031
|
36 |
genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0, |
2a94fe48f
|
37 |
0, PTR_ERR(notify)); |
8e4e1713e
|
38 39 |
return; } |
68eb55031
|
40 41 |
genlmsg_multicast_netns(&dp_vport_genl_family, ovs_dp_get_net(dp), notify, 0, |
2a94fe48f
|
42 |
0, GFP_KERNEL); |
8e4e1713e
|
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
} void ovs_dp_notify_wq(struct work_struct *work) { struct ovs_net *ovs_net = container_of(work, struct ovs_net, dp_notify_work); struct datapath *dp; ovs_lock(); list_for_each_entry(dp, &ovs_net->dps, list_node) { int i; for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) { struct vport *vport; struct hlist_node *n; hlist_for_each_entry_safe(vport, n, &dp->ports[i], dp_hash_node) { struct netdev_vport *netdev_vport; if (vport->ops->type != OVS_VPORT_TYPE_NETDEV) continue; netdev_vport = netdev_vport_priv(vport); |
b07c26511
|
65 |
if (!(netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH)) |
8e4e1713e
|
66 67 68 69 70 71 |
dp_detach_port_notify(vport); } } } ovs_unlock(); } |
ccb1352e7
|
72 73 74 |
static int dp_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { |
8e4e1713e
|
75 |
struct ovs_net *ovs_net; |
351638e7d
|
76 |
struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
8e4e1713e
|
77 |
struct vport *vport = NULL; |
ccb1352e7
|
78 |
|
8e4e1713e
|
79 |
if (!ovs_is_internal_dev(dev)) |
ccb1352e7
|
80 81 82 83 |
vport = ovs_netdev_get_vport(dev); if (!vport) return NOTIFY_DONE; |
8e4e1713e
|
84 |
if (event == NETDEV_UNREGISTER) { |
b07c26511
|
85 86 87 88 |
/* upper_dev_unlink and decrement promisc immediately */ ovs_netdev_detach_dev(vport); /* schedule vport destroy, dev_put and genl notification */ |
8e4e1713e
|
89 90 |
ovs_net = net_generic(dev_net(dev), ovs_net_id); queue_work(system_wq, &ovs_net->dp_notify_work); |
ccb1352e7
|
91 92 93 94 95 96 97 98 |
} return NOTIFY_DONE; } struct notifier_block ovs_dp_device_notifier = { .notifier_call = dp_device_event }; |