Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2349

kernel-2.6.18-238.el5.src.rpm

From: Andy Gospodarek <gospo@redhat.com>
Date: Thu, 23 Oct 2008 08:04:50 -0400
Subject: [net] allow rcv on inactive slaves if listener exists
Message-id: 20081023120450.GA16265@gospo.rdu.redhat.com
O-Subject: [RHEL5.3 PATCH] net: allow receive on active slaves if there is a listener
Bugzilla: 448144
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: David Miller <davem@redhat.com>

There are complaints that one cannot capture all frames on inactive
slaves.  The stack drops frames that are basically considered duplicates
(or unnecessary), but this change should allow someone who has registered
to get them to get them before they are dropped.  As I was testing one
solution for RHEL I discovered this was already done upstream, so it
seemed better to use that solution.

To get there I backported the following upstream commits:

commit cc9bd5cebc0825e0fabc0186ab85806a0891104f
Author: Joe Eykholt <jre@nuovasystems.com>
Date:   Wed Jul 2 18:22:00 2008 -0700

    net/core: Uninline skb_bond().

commit 0d7a3681232f545c6a59f77e60f7667673ef0e93
Author: Joe Eykholt <jre@nuovasystems.com>
Date:   Wed Jul 2 18:22:01 2008 -0700

    net/core: Allow certain receives on inactive slave.

commit f982307f22db96201e41540295f24e8dcc10c78f
Author: Joe Eykholt <jre@nuovasystems.com>
Date:   Wed Jul 2 18:22:02 2008 -0700

    net/core: Allow receive on active slaves.

This has been verified by myself and the customer and will resolve RHBZ
448144.

diff --git a/net/core/dev.c b/net/core/dev.c
index a63500a..c9a36a4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1674,21 +1674,6 @@ int netif_rx_ni(struct sk_buff *skb)
 
 EXPORT_SYMBOL(netif_rx_ni);
 
-static inline struct net_device *skb_bond(struct sk_buff *skb)
-{
-	struct net_device *dev = skb->dev;
-
-	if (dev->master) {
-		if (skb_bond_should_drop(skb)) {
-			kfree_skb(skb);
-			return NULL;
-		}
-		skb->dev = dev->master;
-	}
-
-	return dev;
-}
-
 static void net_tx_action(struct softirq_action *h)
 {
 	struct softnet_data *sd = &__get_cpu_var(softnet_data);
@@ -1813,6 +1798,7 @@ int netif_receive_skb(struct sk_buff *skb)
 {
 	struct packet_type *ptype, *pt_prev;
 	struct net_device *orig_dev;
+	struct net_device *null_or_orig;
 	int ret = NET_RX_DROP;
 	unsigned short type;
 
@@ -1826,10 +1812,14 @@ int netif_receive_skb(struct sk_buff *skb)
 	if (!skb->input_dev)
 		skb->input_dev = skb->dev;
 
-	orig_dev = skb_bond(skb);
-
-	if (!orig_dev)
-		return NET_RX_DROP;
+	null_or_orig = NULL;
+	orig_dev = skb->dev;
+	if (orig_dev->master) {
+		if (skb_bond_should_drop(skb))
+			null_or_orig = orig_dev; /* deliver only exact match */
+		else
+			skb->dev = orig_dev->master;
+	}
 
 	__get_cpu_var(netdev_rx_stat).total++;
 
@@ -1861,7 +1851,8 @@ int netif_receive_skb(struct sk_buff *skb)
 #endif
 
 	list_for_each_entry_rcu(ptype, &ptype_all, list) {
-		if (!ptype->dev || ptype->dev == skb->dev) {
+		if (ptype->dev == null_or_orig || ptype->dev == skb->dev ||
+		    ptype->dev == orig_dev) {
 			if (pt_prev) 
 				ret = deliver_skb(skb, pt_prev, orig_dev);
 			pt_prev = ptype;
@@ -1895,7 +1886,8 @@ ncls:
 	type = skb->protocol;
 	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
 		if (ptype->type == type &&
-		    (!ptype->dev || ptype->dev == skb->dev)) {
+		    (ptype->dev == null_or_orig || ptype->dev == skb->dev ||
+		     ptype->dev == orig_dev)) {
 			if (pt_prev) 
 				ret = deliver_skb(skb, pt_prev, orig_dev);
 			pt_prev = ptype;