2 * Copyright (c) 2007-2012 Nicira, Inc.
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
6 * License as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 #include <linux/netdevice.h>
20 #include <net/genetlink.h>
21 #include <net/netns/generic.h>
24 #include "vport-internal_dev.h"
25 #include "vport-netdev.h"
27 static void dp_detach_port_notify(struct vport
*vport
)
29 struct sk_buff
*notify
;
33 notify
= ovs_vport_cmd_build_info(vport
, 0, 0,
35 ovs_dp_detach_port(vport
);
37 netlink_set_err(ovs_dp_get_net(dp
)->genl_sock
, 0,
38 ovs_dp_vport_multicast_group
.id
,
43 genlmsg_multicast_netns(ovs_dp_get_net(dp
), notify
, 0,
44 ovs_dp_vport_multicast_group
.id
,
48 void ovs_dp_notify_wq(struct work_struct
*work
)
50 struct ovs_net
*ovs_net
= container_of(work
, struct ovs_net
, dp_notify_work
);
54 list_for_each_entry(dp
, &ovs_net
->dps
, list_node
) {
57 for (i
= 0; i
< DP_VPORT_HASH_BUCKETS
; i
++) {
61 hlist_for_each_entry_safe(vport
, n
, &dp
->ports
[i
], dp_hash_node
) {
62 struct netdev_vport
*netdev_vport
;
64 if (vport
->ops
->type
!= OVS_VPORT_TYPE_NETDEV
)
67 netdev_vport
= netdev_vport_priv(vport
);
68 if (!(netdev_vport
->dev
->priv_flags
& IFF_OVS_DATAPATH
))
69 dp_detach_port_notify(vport
);
76 static int dp_device_event(struct notifier_block
*unused
, unsigned long event
,
79 struct ovs_net
*ovs_net
;
80 struct net_device
*dev
= netdev_notifier_info_to_dev(ptr
);
81 struct vport
*vport
= NULL
;
83 if (!ovs_is_internal_dev(dev
))
84 vport
= ovs_netdev_get_vport(dev
);
89 if (event
== NETDEV_UNREGISTER
) {
90 /* upper_dev_unlink and decrement promisc immediately */
91 ovs_netdev_detach_dev(vport
);
93 /* schedule vport destroy, dev_put and genl notification */
94 ovs_net
= net_generic(dev_net(dev
), ovs_net_id
);
95 queue_work(system_wq
, &ovs_net
->dp_notify_work
);
101 struct notifier_block ovs_dp_device_notifier
= {
102 .notifier_call
= dp_device_event