1ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross/*
2caf2ee14bbc2c6bd73cf0decf576007e0239a482Raju Subramanian * Copyright (c) 2007-2012 Nicira, Inc.
3ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross *
4ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * This program is free software; you can redistribute it and/or
5ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * modify it under the terms of version 2 of the GNU General Public
6ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * License as published by the Free Software Foundation.
7ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross *
8ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * This program is distributed in the hope that it will be useful, but
9ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * WITHOUT ANY WARRANTY; without even the implied warranty of
10ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * General Public License for more details.
12ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross *
13ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * You should have received a copy of the GNU General Public License
14ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * along with this program; if not, write to the Free Software
15ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross * 02110-1301, USA
17ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross */
18ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross
19ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross#include <linux/netdevice.h>
20ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross#include <net/genetlink.h>
218e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar#include <net/netns/generic.h>
22ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross
23ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross#include "datapath.h"
24ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross#include "vport-internal_dev.h"
25ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross#include "vport-netdev.h"
26ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross
278e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelarstatic void dp_detach_port_notify(struct vport *vport)
288e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar{
298e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	struct sk_buff *notify;
308e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	struct datapath *dp;
318e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar
328e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	dp = vport->dp;
338e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	notify = ovs_vport_cmd_build_info(vport, 0, 0,
348e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar					  OVS_VPORT_CMD_DEL);
358e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	ovs_dp_detach_port(vport);
368e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	if (IS_ERR(notify)) {
3768eb55031da7c967d954e5f9415cd05f4abdb692Johannes Berg		genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0,
382a94fe48f32ccf7321450a2cc07f2b724a444e5bJohannes Berg			     0, PTR_ERR(notify));
398e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar		return;
408e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	}
418e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar
4268eb55031da7c967d954e5f9415cd05f4abdb692Johannes Berg	genlmsg_multicast_netns(&dp_vport_genl_family,
4368eb55031da7c967d954e5f9415cd05f4abdb692Johannes Berg				ovs_dp_get_net(dp), notify, 0,
442a94fe48f32ccf7321450a2cc07f2b724a444e5bJohannes Berg				0, GFP_KERNEL);
458e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar}
468e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar
478e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelarvoid ovs_dp_notify_wq(struct work_struct *work)
488e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar{
498e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	struct ovs_net *ovs_net = container_of(work, struct ovs_net, dp_notify_work);
508e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	struct datapath *dp;
518e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar
528e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	ovs_lock();
538e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	list_for_each_entry(dp, &ovs_net->dps, list_node) {
548e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar		int i;
558e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar
568e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar		for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
578e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar			struct vport *vport;
588e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar			struct hlist_node *n;
598e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar
608e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar			hlist_for_each_entry_safe(vport, n, &dp->ports[i], dp_hash_node) {
618e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar				struct netdev_vport *netdev_vport;
628e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar
638e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar				if (vport->ops->type != OVS_VPORT_TYPE_NETDEV)
648e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar					continue;
658e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar
668e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar				netdev_vport = netdev_vport_priv(vport);
67b07c26511e94ab856f3700c56d582c0da36d5b4dAlexei Starovoitov				if (!(netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH))
688e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar					dp_detach_port_notify(vport);
698e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar			}
708e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar		}
718e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	}
728e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	ovs_unlock();
738e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar}
748e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar
75ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Grossstatic int dp_device_event(struct notifier_block *unused, unsigned long event,
76ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross			   void *ptr)
77ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross{
788e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	struct ovs_net *ovs_net;
79351638e7deeed2ec8ce451b53d33921b3da68f83Jiri Pirko	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
808e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	struct vport *vport = NULL;
81ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross
828e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	if (!ovs_is_internal_dev(dev))
83ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross		vport = ovs_netdev_get_vport(dev);
84ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross
85ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross	if (!vport)
86ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross		return NOTIFY_DONE;
87ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross
888e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar	if (event == NETDEV_UNREGISTER) {
89b07c26511e94ab856f3700c56d582c0da36d5b4dAlexei Starovoitov		/* upper_dev_unlink and decrement promisc immediately */
90b07c26511e94ab856f3700c56d582c0da36d5b4dAlexei Starovoitov		ovs_netdev_detach_dev(vport);
91b07c26511e94ab856f3700c56d582c0da36d5b4dAlexei Starovoitov
92b07c26511e94ab856f3700c56d582c0da36d5b4dAlexei Starovoitov		/* schedule vport destroy, dev_put and genl notification */
938e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar		ovs_net = net_generic(dev_net(dev), ovs_net_id);
948e4e1713e4978447c5f799aa668dcc6d2cb0dee9Pravin B Shelar		queue_work(system_wq, &ovs_net->dp_notify_work);
95ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross	}
96ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross
97ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross	return NOTIFY_DONE;
98ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross}
99ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross
100ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Grossstruct notifier_block ovs_dp_device_notifier = {
101ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross	.notifier_call = dp_device_event
102ccb1352e76cff0524e7ccb2074826a092dd13016Jesse Gross};
103