[ovs-dev] [PATCH] datapath: stt: Fix device list management.

Pravin B Shelar pshelar at nicira.com
Sun Dec 20 06:21:24 UTC 2015


Keep devices in UP state in stt-list. So that devices in UP state
would be searched on a packet receive in STT. This way devices in
DOWN state would not accept any packets.

Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
 datapath/linux/compat/stt.c | 73 ++++++++++++++++++++++-----------------------
 1 file changed, 36 insertions(+), 37 deletions(-)

diff --git a/datapath/linux/compat/stt.c b/datapath/linux/compat/stt.c
index 1500a76..1e2c26a 100644
--- a/datapath/linux/compat/stt.c
+++ b/datapath/linux/compat/stt.c
@@ -157,6 +157,7 @@ static int stt_net_id;
 
 static struct stt_percpu __percpu *stt_percpu_data __read_mostly;
 static u32 frag_hash_seed __read_mostly;
+static struct rtnl_link_ops stt_link_ops;
 
 /* Protects sock-hash and refcounts. */
 static DEFINE_MUTEX(stt_mutex);
@@ -167,7 +168,7 @@ static DEFINE_PER_CPU(u32, pkt_seq_counter);
 static void clean_percpu(struct work_struct *work);
 static DECLARE_DELAYED_WORK(clean_percpu_wq, clean_percpu);
 
-static struct stt_dev *stt_find_sock(struct net *net, __be16 port)
+static struct stt_dev *stt_find_dev(struct net *net, __be16 port)
 {
 	struct stt_net *sn = net_generic(net, stt_net_id);
 	struct stt_dev *stt_dev;
@@ -1481,7 +1482,7 @@ static unsigned int nf_ip_hook(FIRST_PARAM, struct sk_buff *skb, LAST_PARAM)
 
 	skb_set_transport_header(skb, ip_hdr_len);
 
-	stt_dev = stt_find_sock(dev_net(skb->dev), tcp_hdr(skb)->dest);
+	stt_dev = stt_find_dev(dev_net(skb->dev), tcp_hdr(skb)->dest);
 	if (!stt_dev)
 		return NF_ACCEPT;
 
@@ -1644,6 +1645,7 @@ static int stt_open(struct net_device *dev)
 {
 	struct stt_dev *stt = netdev_priv(dev);
 	struct net *net = stt->net;
+	struct stt_net *sn = net_generic(net, stt_net_id);
 	int err;
 
 	err = stt_start(net);
@@ -1653,6 +1655,7 @@ static int stt_open(struct net_device *dev)
 	err = tcp_sock_create4(net, stt->dst_port, &stt->sock);
 	if (err)
 		return err;
+	list_add_rcu(&stt->next, &sn->stt_list);
 	return 0;
 }
 
@@ -1661,6 +1664,7 @@ static int stt_stop(struct net_device *dev)
 	struct stt_dev *stt_dev = netdev_priv(dev);
 	struct net *net = stt_dev->net;
 
+	list_del_rcu(&stt_dev->next);
 	tcp_sock_release(stt_dev->sock);
 	stt_dev->sock = NULL;
 	stt_cleanup(net);
@@ -1739,38 +1743,37 @@ static int stt_validate(struct nlattr *tb[], struct nlattr *data[])
 	return 0;
 }
 
-static struct stt_dev *find_dev(struct net *net, __be16 dst_port)
-{
-	struct stt_net *sn = net_generic(net, stt_net_id);
-	struct stt_dev *dev;
-
-	list_for_each_entry(dev, &sn->stt_list, next) {
-		if (dev->dst_port == dst_port)
-			return dev;
-	}
-	return NULL;
-}
-
 static int stt_configure(struct net *net, struct net_device *dev,
 			  __be16 dst_port)
 {
-	struct stt_net *sn = net_generic(net, stt_net_id);
 	struct stt_dev *stt = netdev_priv(dev);
+	struct net *tnet;
 	int err;
 
+	/* stt-net device list does not contain all stt devices. Use
+	 * networking stack device list to check all stt devices.
+	 */
+	for_each_net(tnet) {
+		struct net_device *tdev, *aux;
+
+		for_each_netdev_safe(tnet, tdev, aux) {
+			if (tdev->rtnl_link_ops == &stt_link_ops) {
+				struct stt_dev *tstt = netdev_priv(tdev);
+
+				if (net_eq(tstt->net, net) &&
+				    tstt->dst_port == dst_port)
+					return -EBUSY;
+			}
+		}
+	}
+
 	stt->net = net;
 	stt->dev = dev;
-
 	stt->dst_port = dst_port;
 
-	if (find_dev(net, dst_port))
-		return -EBUSY;
-
 	err = register_netdevice(dev);
 	if (err)
 		return err;
-
-	list_add_rcu(&stt->next, &sn->stt_list);
 	return 0;
 }
 
@@ -1787,9 +1790,6 @@ static int stt_newlink(struct net *net, struct net_device *dev,
 
 static void stt_dellink(struct net_device *dev, struct list_head *head)
 {
-	struct stt_dev *stt = netdev_priv(dev);
-
-	list_del_rcu(&stt->next);
 	unregister_netdevice_queue(dev, head);
 }
 
@@ -1856,24 +1856,23 @@ static int stt_init_net(struct net *net)
 
 static void stt_exit_net(struct net *net)
 {
-	struct stt_net *sn = net_generic(net, stt_net_id);
-	struct stt_dev *stt, *next;
-	struct net_device *dev, *aux;
+	struct net *tnet;
 	LIST_HEAD(list);
 
 	rtnl_lock();
 
-	/* gather any stt devices that were moved into this ns */
-	for_each_netdev_safe(net, dev, aux)
-		if (dev->rtnl_link_ops == &stt_link_ops)
-			unregister_netdevice_queue(dev, &list);
+	for_each_net(tnet) {
+		struct net_device *tdev, *aux;
 
-	list_for_each_entry_safe(stt, next, &sn->stt_list, next) {
-		/* If stt->dev is in the same netns, it was already added
-		 * to the stt by the previous loop.
-		 */
-		if (!net_eq(dev_net(stt->dev), net))
-			unregister_netdevice_queue(stt->dev, &list);
+		for_each_netdev_safe(tnet, tdev, aux) {
+			if (tdev->rtnl_link_ops == &stt_link_ops) {
+				struct stt_dev *tstt = netdev_priv(tdev);
+
+				if (net_eq(tstt->net, net) ||
+				    net_eq(dev_net(tstt->dev), net))
+					unregister_netdevice_queue(tdev, &list);
+			}
+		}
 	}
 
 	/* unregister the devices gathered above */
-- 
1.8.3.1




More information about the dev mailing list