1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2007-2012 Nicira, Inc.
6 #include <linux/netdevice.h>
7 #include <net/genetlink.h>
8 #include <net/netns/generic.h>
11 #include "vport-internal_dev.h"
12 #include "vport-netdev.h"
14 static void dp_detach_port_notify(struct vport
*vport
)
16 struct sk_buff
*notify
;
20 notify
= ovs_vport_cmd_build_info(vport
, ovs_dp_get_net(dp
),
21 0, 0, OVS_VPORT_CMD_DEL
);
22 ovs_dp_detach_port(vport
);
24 genl_set_err(&dp_vport_genl_family
, ovs_dp_get_net(dp
), 0,
29 genlmsg_multicast_netns(&dp_vport_genl_family
,
30 ovs_dp_get_net(dp
), notify
, 0,
34 void ovs_dp_notify_wq(struct work_struct
*work
)
36 struct ovs_net
*ovs_net
= container_of(work
, struct ovs_net
, dp_notify_work
);
40 list_for_each_entry(dp
, &ovs_net
->dps
, list_node
) {
43 for (i
= 0; i
< DP_VPORT_HASH_BUCKETS
; i
++) {
47 hlist_for_each_entry_safe(vport
, n
, &dp
->ports
[i
], dp_hash_node
) {
48 if (vport
->ops
->type
== OVS_VPORT_TYPE_INTERNAL
)
51 if (!(netif_is_ovs_port(vport
->dev
)))
52 dp_detach_port_notify(vport
);
59 static int dp_device_event(struct notifier_block
*unused
, unsigned long event
,
62 struct ovs_net
*ovs_net
;
63 struct net_device
*dev
= netdev_notifier_info_to_dev(ptr
);
64 struct vport
*vport
= NULL
;
66 if (!ovs_is_internal_dev(dev
))
67 vport
= ovs_netdev_get_vport(dev
);
72 if (event
== NETDEV_UNREGISTER
) {
73 /* upper_dev_unlink and decrement promisc immediately */
74 ovs_netdev_detach_dev(vport
);
76 /* schedule vport destroy, dev_put and genl notification */
77 ovs_net
= net_generic(dev_net(dev
), ovs_net_id
);
78 queue_work(system_wq
, &ovs_net
->dp_notify_work
);
84 struct notifier_block ovs_dp_device_notifier
= {
85 .notifier_call
= dp_device_event