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