Please queue up the following networking bug fixes for
3.6-stable

Thanks!
>From 0f805a4315b509718ad3000e6cd6012573289409 Mon Sep 17 00:00:00 2001
From: Eric Dumazet <[email protected]>
Date: Thu, 4 Oct 2012 01:25:26 +0000
Subject: [PATCH 1/5] ipv4: add a fib_type to fib_info

[ Upstream commit f4ef85bbda96324785097356336bc79cdd37db0a ]

commit d2d68ba9fe8 (ipv4: Cache input routes in fib_info nexthops.)
introduced a regression for forwarding.

This was hard to reproduce but the symptom was that packets were
delivered to local host instead of being forwarded.

David suggested to add fib_type to fib_info so that we dont
inadvertently share same fib_info for different purposes.

With help from Julian Anastasov who provided very helpful
hints, reproduced here :

<quote>
        Can it be a problem related to fib_info reuse
from different routes. For example, when local IP address
is created for subnet we have:

broadcast 192.168.0.255 dev DEV  proto kernel  scope link  src
192.168.0.1
192.168.0.0/24 dev DEV  proto kernel  scope link  src 192.168.0.1
local 192.168.0.1 dev DEV  proto kernel  scope host  src 192.168.0.1

        The "dev DEV  proto kernel  scope link  src 192.168.0.1" is
a reused fib_info structure where we put cached routes.
The result can be same fib_info for 192.168.0.255 and
192.168.0.0/24. RTN_BROADCAST is cached only for input
routes. Incoming broadcast to 192.168.0.255 can be cached
and can cause problems for traffic forwarded to 192.168.0.0/24.
So, this patch should solve the problem because it
separates the broadcast from unicast traffic.

        And the ip_route_input_slow caching will work for
local and broadcast input routes (above routes 1 and 3) just
because they differ in scope and use different fib_info.

</quote>

Many thanks to Chris Clayton for his patience and help.

Reported-by: Chris Clayton <[email protected]>
Bisected-by: Chris Clayton <[email protected]>
Reported-by: Dave Jones <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
Cc: Julian Anastasov <[email protected]>
Tested-by: Chris Clayton <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
---
 include/net/ip_fib.h     | 1 +
 net/ipv4/fib_semantics.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 926142e..9497be1 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -102,6 +102,7 @@ struct fib_info {
        unsigned char           fib_dead;
        unsigned char           fib_protocol;
        unsigned char           fib_scope;
+       unsigned char           fib_type;
        __be32                  fib_prefsrc;
        u32                     fib_priority;
        u32                     *fib_metrics;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index da80dc1..a747100 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -314,6 +314,7 @@ static struct fib_info *fib_find_info(const struct fib_info 
*nfi)
                    nfi->fib_scope == fi->fib_scope &&
                    nfi->fib_prefsrc == fi->fib_prefsrc &&
                    nfi->fib_priority == fi->fib_priority &&
+                   nfi->fib_type == fi->fib_type &&
                    memcmp(nfi->fib_metrics, fi->fib_metrics,
                           sizeof(u32) * RTAX_MAX) == 0 &&
                    ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 &&
@@ -833,6 +834,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
        fi->fib_flags = cfg->fc_flags;
        fi->fib_priority = cfg->fc_priority;
        fi->fib_prefsrc = cfg->fc_prefsrc;
+       fi->fib_type = cfg->fc_type;
 
        fi->fib_nhs = nhs;
        change_nexthops(fi) {
-- 
1.7.11.4


>From 9d6bd5f3d98404a9e6509f2c32d1f047029dae8f Mon Sep 17 00:00:00 2001
From: Antonio Quartulli <[email protected]>
Date: Tue, 2 Oct 2012 06:14:17 +0000
Subject: [PATCH 2/5] 8021q: fix mac_len recomputation in vlan_untag()

[ Upstream commit 5316cf9a5197eb80b2800e1acadde287924ca975 ]

skb_reset_mac_len() relies on the value of the skb->network_header pointer,
therefore we must wait for such pointer to be recalculated before computing
the new mac_len value.

Signed-off-by: Antonio Quartulli <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
---
 net/8021q/vlan_core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 8ca533c..830059d 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -105,7 +105,6 @@ static struct sk_buff *vlan_reorder_header(struct sk_buff 
*skb)
                return NULL;
        memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN);
        skb->mac_header += VLAN_HLEN;
-       skb_reset_mac_len(skb);
        return skb;
 }
 
@@ -139,6 +138,8 @@ struct sk_buff *vlan_untag(struct sk_buff *skb)
 
        skb_reset_network_header(skb);
        skb_reset_transport_header(skb);
+       skb_reset_mac_len(skb);
+
        return skb;
 
 err_free:
-- 
1.7.11.4


>From 78fd2204e8bd37393c19b9cbe937540a6e558c09 Mon Sep 17 00:00:00 2001
From: Gao feng <[email protected]>
Date: Wed, 19 Sep 2012 19:25:34 +0000
Subject: [PATCH 3/5] ipv6: release reference of ip6_null_entry's dst entry in
 __ip6_del_rt

[ Upstream commit 6825a26c2dc21eb4f8df9c06d3786ddec97cf53b ]

as we hold dst_entry before we call __ip6_del_rt,
so we should alse call dst_release not only return
-ENOENT when the rt6_info is ip6_null_entry.

and we already hold the dst entry, so I think it's
safe to call dst_release out of the write-read lock.

Signed-off-by: Gao feng <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
---
 net/ipv6/route.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 854e401..46eff42 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1589,17 +1589,18 @@ static int __ip6_del_rt(struct rt6_info *rt, struct 
nl_info *info)
        struct fib6_table *table;
        struct net *net = dev_net(rt->dst.dev);
 
-       if (rt == net->ipv6.ip6_null_entry)
-               return -ENOENT;
+       if (rt == net->ipv6.ip6_null_entry) {
+               err = -ENOENT;
+               goto out;
+       }
 
        table = rt->rt6i_table;
        write_lock_bh(&table->tb6_lock);
-
        err = fib6_del(rt, info);
-       dst_release(&rt->dst);
-
        write_unlock_bh(&table->tb6_lock);
 
+out:
+       dst_release(&rt->dst);
        return err;
 }
 
-- 
1.7.11.4


>From dccdd11a3449d39d0e3fdf376f13cf2eabab41b8 Mon Sep 17 00:00:00 2001
From: htbegin <[email protected]>
Date: Mon, 1 Oct 2012 16:42:43 +0000
Subject: [PATCH 4/5] net: ethernet: davinci_cpdma: decrease the desc count
 when cleaning up the remaining packets

[ Upstream commit ffb5ba90017505a19e238e986e6d33f09e4df765 ]

chan->count is used by rx channel. If the desc count is not updated by
the clean up loop in cpdma_chan_stop, the value written to the rxfree
register in cpdma_chan_start will be incorrect.

Signed-off-by: Tao Hou <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
---
 drivers/net/ethernet/ti/davinci_cpdma.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c 
b/drivers/net/ethernet/ti/davinci_cpdma.c
index d15c888..4995673 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -863,6 +863,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
 
                next_dma = desc_read(desc, hw_next);
                chan->head = desc_from_phys(pool, next_dma);
+               chan->count--;
                chan->stats.teardown_dequeue++;
 
                /* issue callback without locks held */
-- 
1.7.11.4


>From be5bbaad23547fa5551691b6185641004d206967 Mon Sep 17 00:00:00 2001
From: Nicolas Dichtel <[email protected]>
Date: Wed, 26 Sep 2012 00:04:55 +0000
Subject: [PATCH 5/5] ipv6: del unreachable route when an addr is deleted on
 lo

[ Upstream commit 64c6d08e6490fb18cea09bb03686c149946bd818 ]

When an address is added on loopback (ip -6 a a 2002::1/128 dev lo), two routes
are added:
 - one in the local table:
    local 2002::1 via :: dev lo  proto none  metric 0
 - one the in main table (for the prefix):
    unreachable 2002::1 dev lo  proto kernel  metric 256  error -101

When the address is deleted, the route inserted in the main table remains
because we use rt6_lookup(), which returns NULL when dst->error is set, which
is the case here! Thus, it is better to use ip6_route_lookup() to avoid this
kind of filter.

Signed-off-by: Nicolas Dichtel <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
---
 net/ipv6/addrconf.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 6bc85f7..ea3e9af 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -788,10 +788,16 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
                struct in6_addr prefix;
                struct rt6_info *rt;
                struct net *net = dev_net(ifp->idev->dev);
+               struct flowi6 fl6 = {};
+
                ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
-               rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1);
+               fl6.flowi6_oif = ifp->idev->dev->ifindex;
+               fl6.daddr = prefix;
+               rt = (struct rt6_info *)ip6_route_lookup(net, &fl6,
+                                                        RT6_LOOKUP_F_IFACE);
 
-               if (rt && addrconf_is_prefix_route(rt)) {
+               if (rt != net->ipv6.ip6_null_entry &&
+                   addrconf_is_prefix_route(rt)) {
                        if (onlink == 0) {
                                ip6_del_rt(rt);
                                rt = NULL;
-- 
1.7.11.4

Reply via email to