[openib-general] [PATCH 00/12] ofed_1_2 - Neighbour update support

Michael S. Tsirkin mst at mellanox.co.il
Thu Feb 1 04:10:08 PST 2007


> Quoting Steve Wise <swise at opengridcomputing.com>:
> Subject: [PATCH 00/12] ofed_1_2 - Neighbour update support
> 
> 
> Michael/Vlad:
> 
> Here are the backports for snooping arp packets to generate neighbour
> update netevents.  Also included is the addr.c patch to act on all valid
> neigh update events.  If this series looks good to you then I'll push
> this up and you all can pull it from my git tree.

This patches seems to have created a reference leak on each neighbour
as a result ipoib interface could not be brought down.
It also seems that RHASU2 backport was missing code.
I pushed out the following:


commit d140398db0da0beb3172e0ccf14ef3023cafec9c
Author: Michael S. Tsirkin <mst at mellanox.co.il>
Date:   Thu Feb 1 12:21:34 2007 +0200

    Fix neighbour reference leak in netevent.c
    
    Signed-off-by: Michael S. Tsirkin <mst at mellanox.co.il>

diff --git a/kernel_addons/backport/2.6.11/include/src/netevent.c b/kernel_addons/backport/2.6.11/include/src/netevent.c
index 6a8df29..0d26662 100644
--- a/kernel_addons/backport/2.6.11/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.11/include/src/netevent.c
@@ -38,8 +38,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 
diff --git a/kernel_addons/backport/2.6.12/include/src/netevent.c b/kernel_addons/backport/2.6.12/include/src/netevent.c
index 6a8df29..0d26662 100644
--- a/kernel_addons/backport/2.6.12/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.12/include/src/netevent.c
@@ -38,8 +38,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 
diff --git a/kernel_addons/backport/2.6.13/include/src/netevent.c b/kernel_addons/backport/2.6.13/include/src/netevent.c
index 6a8df29..0d26662 100644
--- a/kernel_addons/backport/2.6.13/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.13/include/src/netevent.c
@@ -38,8 +38,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 
diff --git a/kernel_addons/backport/2.6.14/include/src/netevent.c b/kernel_addons/backport/2.6.14/include/src/netevent.c
index 188283c..17a12ff 100644
--- a/kernel_addons/backport/2.6.14/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.14/include/src/netevent.c
@@ -38,8 +38,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 
diff --git a/kernel_addons/backport/2.6.15/include/src/netevent.c b/kernel_addons/backport/2.6.15/include/src/netevent.c
index 188283c..17a12ff 100644
--- a/kernel_addons/backport/2.6.15/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.15/include/src/netevent.c
@@ -38,8 +38,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 
diff --git a/kernel_addons/backport/2.6.15_ubuntu606/include/src/netevent.c b/kernel_addons/backport/2.6.15_ubuntu606/include/src/netevent.c
index 188283c..17a12ff 100644
--- a/kernel_addons/backport/2.6.15_ubuntu606/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.15_ubuntu606/include/src/netevent.c
@@ -38,8 +38,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 
diff --git a/kernel_addons/backport/2.6.16/include/src/netevent.c b/kernel_addons/backport/2.6.16/include/src/netevent.c
index 188283c..17a12ff 100644
--- a/kernel_addons/backport/2.6.16/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.16/include/src/netevent.c
@@ -38,8 +38,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 
diff --git a/kernel_addons/backport/2.6.16_sles10/include/src/netevent.c b/kernel_addons/backport/2.6.16_sles10/include/src/netevent.c
index 188283c..17a12ff 100644
--- a/kernel_addons/backport/2.6.16_sles10/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.16_sles10/include/src/netevent.c
@@ -38,8 +38,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 
diff --git a/kernel_addons/backport/2.6.17/include/src/netevent.c b/kernel_addons/backport/2.6.17/include/src/netevent.c
index 26a0920..4c67de1 100644
--- a/kernel_addons/backport/2.6.17/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.17/include/src/netevent.c
@@ -38,8 +38,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 
diff --git a/kernel_addons/backport/2.6.5_sles9_sp3/include/src/netevent.c b/kernel_addons/backport/2.6.5_sles9_sp3/include/src/netevent.c
index 57a23ab..90fce0c 100644
--- a/kernel_addons/backport/2.6.5_sles9_sp3/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.5_sles9_sp3/include/src/netevent.c
@@ -39,8 +39,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 
diff --git a/kernel_addons/backport/2.6.9_U2/include/src/netevent.c b/kernel_addons/backport/2.6.9_U2/include/src/netevent.c
index 5ffadd1..1589300 100644
--- a/kernel_addons/backport/2.6.9_U2/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.9_U2/include/src/netevent.c
@@ -13,10 +13,59 @@
  *	Fixes:
  */
 
-#include <linux/module.h>
-#include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/notifier.h>
+#include <linux/mutex.h>
+#include <linux/if.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+
+#include <net/arp.h>
+#include <net/neighbour.h>
+#include <net/route.h>
+#include <net/netevent.h>
+
+static DEFINE_MUTEX(lock);
+static int count;
+
+static void destructor(struct sk_buff *skb)
+{
+	struct neighbour *n;
+	u8 *arp_ptr;
+	__be32 gw;
+
+	/* Pull the SPA */
+	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
+	memcpy(&gw, arp_ptr, 4);
+	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
+	if (n) {
+		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
+	return;
+}
+
+static int arp_recv(struct sk_buff *skb, struct net_device *dev,
+			 struct packet_type *pkt)
+{
+	struct arphdr *arp_hdr;
+	u16 op;
+
+	arp_hdr = (struct arphdr *) skb->nh.raw;
+	op = ntohs(arp_hdr->ar_op);
+
+	if ((op == ARPOP_REQUEST || op == ARPOP_REPLY) && !skb->destructor)
+		skb->destructor = destructor;
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static struct packet_type arp = {
+	.type = __constant_htons(ETH_P_ARP),
+	.func = arp_recv,
+	.af_packet_priv = (void *)1,
+};
 
 static struct notifier_block *netevent_notif_chain;
 
@@ -34,6 +83,12 @@ int register_netevent_notifier(struct notifier_block *nb)
 	int err;
 
 	err = notifier_chain_register(&netevent_notif_chain, nb);
+	if (!err) {
+		mutex_lock(&lock);
+		if (count++ == 0)
+			dev_add_pack(&arp);
+		mutex_unlock(&lock);
+	}
 	return err;
 }
 
@@ -49,7 +104,16 @@ int register_netevent_notifier(struct notifier_block *nb)
 
 int unregister_netevent_notifier(struct notifier_block *nb)
 {
-	return notifier_chain_unregister(&netevent_notif_chain, nb);
+	int err;
+
+	err = notifier_chain_unregister(&netevent_notif_chain, nb);
+	if (!err) {
+		mutex_lock(&lock);
+		if (--count == 0)
+			dev_remove_pack(&arp);
+		mutex_unlock(&lock);
+	}
+	return err;
 }
 
 /**
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/netevent.c b/kernel_addons/backport/2.6.9_U3/include/src/netevent.c
index 5ffadd1..1589300 100644
--- a/kernel_addons/backport/2.6.9_U3/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.9_U3/include/src/netevent.c
@@ -13,10 +13,59 @@
  *	Fixes:
  */
 
-#include <linux/module.h>
-#include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/notifier.h>
+#include <linux/mutex.h>
+#include <linux/if.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+
+#include <net/arp.h>
+#include <net/neighbour.h>
+#include <net/route.h>
+#include <net/netevent.h>
+
+static DEFINE_MUTEX(lock);
+static int count;
+
+static void destructor(struct sk_buff *skb)
+{
+	struct neighbour *n;
+	u8 *arp_ptr;
+	__be32 gw;
+
+	/* Pull the SPA */
+	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
+	memcpy(&gw, arp_ptr, 4);
+	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
+	if (n) {
+		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
+	return;
+}
+
+static int arp_recv(struct sk_buff *skb, struct net_device *dev,
+			 struct packet_type *pkt)
+{
+	struct arphdr *arp_hdr;
+	u16 op;
+
+	arp_hdr = (struct arphdr *) skb->nh.raw;
+	op = ntohs(arp_hdr->ar_op);
+
+	if ((op == ARPOP_REQUEST || op == ARPOP_REPLY) && !skb->destructor)
+		skb->destructor = destructor;
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static struct packet_type arp = {
+	.type = __constant_htons(ETH_P_ARP),
+	.func = arp_recv,
+	.af_packet_priv = (void *)1,
+};
 
 static struct notifier_block *netevent_notif_chain;
 
@@ -34,6 +83,12 @@ int register_netevent_notifier(struct notifier_block *nb)
 	int err;
 
 	err = notifier_chain_register(&netevent_notif_chain, nb);
+	if (!err) {
+		mutex_lock(&lock);
+		if (count++ == 0)
+			dev_add_pack(&arp);
+		mutex_unlock(&lock);
+	}
 	return err;
 }
 
@@ -49,7 +104,16 @@ int register_netevent_notifier(struct notifier_block *nb)
 
 int unregister_netevent_notifier(struct notifier_block *nb)
 {
-	return notifier_chain_unregister(&netevent_notif_chain, nb);
+	int err;
+
+	err = notifier_chain_unregister(&netevent_notif_chain, nb);
+	if (!err) {
+		mutex_lock(&lock);
+		if (--count == 0)
+			dev_remove_pack(&arp);
+		mutex_unlock(&lock);
+	}
+	return err;
 }
 
 /**
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/netevent.c b/kernel_addons/backport/2.6.9_U4/include/src/netevent.c
index 6a8df29..0d26662 100644
--- a/kernel_addons/backport/2.6.9_U4/include/src/netevent.c
+++ b/kernel_addons/backport/2.6.9_U4/include/src/netevent.c
@@ -38,8 +38,10 @@ static void destructor(struct sk_buff *skb)
 	arp_ptr = skb->nh.raw + sizeof(struct arphdr) + skb->dev->addr_len;
 	memcpy(&gw, arp_ptr, 4);
 	n = neigh_lookup(&arp_tbl, &gw, skb->dev);
-	if (n)
+	if (n) {
 		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+		neigh_release(n);
+	}
 	return;
 }
 

-- 
MST




More information about the general mailing list