From 19c64e8691ab643cc9ce4c612895b7b7a4196324 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Sun, 20 Dec 2015 17:05:24 -0800 Subject: [PATCH] datapath: stt: Fix device list management. STT receive can accept packet on device which is not UP state. Following patch fixes this issue by introducing another list of devices which contains only devices in up state. This list can be used for searching stt devices on packet receive. Signed-off-by: Pravin B Shelar Acked-by: Jesse Gross --- datapath/linux/compat/stt.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/datapath/linux/compat/stt.c b/datapath/linux/compat/stt.c index 8e001125b..85ddbe7ca 100644 --- a/datapath/linux/compat/stt.c +++ b/datapath/linux/compat/stt.c @@ -62,6 +62,7 @@ struct stt_dev { struct net_device *dev; struct net *net; struct list_head next; + struct list_head up_next; struct socket *sock; __be16 dst_port; }; @@ -150,6 +151,7 @@ struct frag_skb_cb { /* per-network namespace private data for this module */ struct stt_net { struct list_head stt_list; + struct list_head stt_up_list; /* Devices which are in IFF_UP state. */ int n_tunnels; }; @@ -167,12 +169,12 @@ 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_up_dev(struct net *net, __be16 port) { struct stt_net *sn = net_generic(net, stt_net_id); struct stt_dev *stt_dev; - list_for_each_entry_rcu(stt_dev, &sn->stt_list, next) { + list_for_each_entry_rcu(stt_dev, &sn->stt_up_list, up_next) { if (stt_dev->dst_port == port) return stt_dev; } @@ -1481,7 +1483,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_up_dev(dev_net(skb->dev), tcp_hdr(skb)->dest); if (!stt_dev) return NF_ACCEPT; @@ -1646,6 +1648,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); @@ -1655,6 +1658,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->up_next, &sn->stt_up_list); return 0; } @@ -1663,6 +1667,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->up_next); tcp_sock_release(stt_dev->sock); stt_dev->sock = NULL; stt_cleanup(net); @@ -1772,7 +1777,7 @@ static int stt_configure(struct net *net, struct net_device *dev, if (err) return err; - list_add_rcu(&stt->next, &sn->stt_list); + list_add(&stt->next, &sn->stt_list); return 0; } @@ -1791,7 +1796,7 @@ static void stt_dellink(struct net_device *dev, struct list_head *head) { struct stt_dev *stt = netdev_priv(dev); - list_del_rcu(&stt->next); + list_del(&stt->next); unregister_netdevice_queue(dev, head); } @@ -1853,6 +1858,7 @@ static int stt_init_net(struct net *net) struct stt_net *sn = net_generic(net, stt_net_id); INIT_LIST_HEAD(&sn->stt_list); + INIT_LIST_HEAD(&sn->stt_up_list); return 0; } -- 2.20.1