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 <pshe...@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

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to