~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to datapath/dp_notify.c

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#include "vport-internal_dev.h"
24
24
#include "vport-netdev.h"
25
25
 
 
26
static void dp_detach_port_notify(struct vport *vport)
 
27
{
 
28
        struct sk_buff *notify;
 
29
        struct datapath *dp;
 
30
 
 
31
        dp = vport->dp;
 
32
        notify = ovs_vport_cmd_build_info(vport, 0, 0,
 
33
                                          OVS_VPORT_CMD_DEL);
 
34
        ovs_dp_detach_port(vport);
 
35
        if (IS_ERR(notify)) {
 
36
                netlink_set_err(GENL_SOCK(ovs_dp_get_net(dp)), 0,
 
37
                                ovs_dp_vport_multicast_group.id,
 
38
                                PTR_ERR(notify));
 
39
                return;
 
40
        }
 
41
 
 
42
        genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
 
43
                                ovs_dp_vport_multicast_group.id,
 
44
                                GFP_KERNEL);
 
45
}
 
46
 
 
47
void ovs_dp_notify_wq(struct work_struct *work)
 
48
{
 
49
        struct ovs_net *ovs_net = container_of(work, struct ovs_net, dp_notify_work);
 
50
        struct datapath *dp;
 
51
 
 
52
        ovs_lock();
 
53
        list_for_each_entry(dp, &ovs_net->dps, list_node) {
 
54
                int i;
 
55
 
 
56
                for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
 
57
                        struct vport *vport;
 
58
                        struct hlist_node *n;
 
59
 
 
60
                        hlist_for_each_entry_safe(vport, n, &dp->ports[i], dp_hash_node) {
 
61
                                struct netdev_vport *netdev_vport;
 
62
 
 
63
                                if (vport->ops->type != OVS_VPORT_TYPE_NETDEV)
 
64
                                        continue;
 
65
 
 
66
                                netdev_vport = netdev_vport_priv(vport);
 
67
                                if (netdev_vport->dev->reg_state == NETREG_UNREGISTERED ||
 
68
                                    netdev_vport->dev->reg_state == NETREG_UNREGISTERING)
 
69
                                        dp_detach_port_notify(vport);
 
70
                        }
 
71
                }
 
72
        }
 
73
        ovs_unlock();
 
74
}
 
75
 
26
76
static int dp_device_event(struct notifier_block *unused, unsigned long event,
27
77
                           void *ptr)
28
78
{
 
79
        struct ovs_net *ovs_net;
29
80
        struct net_device *dev = ptr;
30
 
        struct vport *vport;
 
81
        struct vport *vport = NULL;
31
82
 
32
 
        if (ovs_is_internal_dev(dev))
33
 
                vport = ovs_internal_dev_get_vport(dev);
34
 
        else
 
83
        if (!ovs_is_internal_dev(dev))
35
84
                vport = ovs_netdev_get_vport(dev);
36
85
 
37
86
        if (!vport)
38
87
                return NOTIFY_DONE;
39
88
 
40
 
        switch (event) {
41
 
        case NETDEV_UNREGISTER:
42
 
                if (!ovs_is_internal_dev(dev)) {
43
 
                        struct sk_buff *notify;
44
 
                        struct datapath *dp = vport->dp;
45
 
 
46
 
                        notify = ovs_vport_cmd_build_info(vport, 0, 0,
47
 
                                                          OVS_VPORT_CMD_DEL);
48
 
                        ovs_dp_detach_port(vport);
49
 
                        if (IS_ERR(notify)) {
50
 
                                netlink_set_err(GENL_SOCK(ovs_dp_get_net(dp)), 0,
51
 
                                                ovs_dp_vport_multicast_group.id,
52
 
                                                PTR_ERR(notify));
53
 
                                break;
54
 
                        }
55
 
 
56
 
                        genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
57
 
                                                ovs_dp_vport_multicast_group.id,
58
 
                                                GFP_KERNEL);
59
 
                }
60
 
                break;
61
 
 
 
89
        if (event == NETDEV_UNREGISTER) {
 
90
                ovs_net = net_generic(dev_net(dev), ovs_net_id);
 
91
                queue_work(&ovs_net->dp_notify_work);
62
92
        }
63
93
 
64
94
        return NOTIFY_DONE;