[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