Netdev List
 help / color / mirror / Atom feed
* checkpatch run on net/ethernet
From: matthew @ 2012-10-02 11:41 UTC (permalink / raw)
  To: linux-kernel; +Cc: netdev, davem


This is my first patch, it's just a checkpatch run. I figured I would also clean up the code as there appears to be long-since-obsoleted comments and code in there.

A fairly trivial change, but worthy of inclusion IMO all the same!

Matthew Walster

^ permalink raw reply

* [PATCH 2/2] net: ethernet: Remove obsolete comment
From: matthew @ 2012-10-02 11:41 UTC (permalink / raw)
  To: linux-kernel; +Cc: netdev, davem, Matthew Walster
In-Reply-To: <1349178105-28269-1-git-send-email-matthew@walster.org>

From: Matthew Walster <matthew@walster.org>

The deleted comment was related to code I've just removed in the previous patch.
---
 net/ethernet/eth.c |    8 --------
 1 file changed, 8 deletions(-)

diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index a9f8531..7d72108 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -170,14 +170,6 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
 			skb->pkt_type = PACKET_MULTICAST;
 	}
 
-	/*
-	 *      This ALLMULTI check should be redundant by 1.4
-	 *      so don't forget to remove it.
-	 *
-	 *      Seems, you forgot to remove it. All silly devices
-	 *      seems to set IFF_PROMISC.
-	 */
-
 	else if (unlikely(!ether_addr_equal_64bits(eth->h_dest, dev->dev_addr)))
 		skb->pkt_type = PACKET_OTHERHOST;
 
-- 
1.7.10.4

^ permalink raw reply related

* [patch] bnx2x: use strlcpy() to copy a string
From: Dan Carpenter @ 2012-10-02 11:47 UTC (permalink / raw)
  To: Eilon Greenstein; +Cc: netdev, kernel-janitors

DRV_MODULE_VERSION is smaller than the ->version buffer so the memcpy()
copies 1 byte past the end of the string.  It's not super harmful, but
it makes the static checkers complain.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index f7ed122..d5648fc 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -3052,9 +3052,8 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp)
 	struct eth_stats_info *ether_stat =
 		&bp->slowpath->drv_info_to_mcp.ether_stat;
 
-	/* leave last char as NULL */
-	memcpy(ether_stat->version, DRV_MODULE_VERSION,
-	       ETH_STAT_INFO_VERSION_LEN - 1);
+	strlcpy(ether_stat->version, DRV_MODULE_VERSION,
+		ETH_STAT_INFO_VERSION_LEN);
 
 	bp->sp_objs[0].mac_obj.get_n_elements(bp, &bp->sp_objs[0].mac_obj,
 					DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED,

^ permalink raw reply related

* Re: tg3 driver upgrade (Linux 2.6.32 -> 3.2) breaks IBM Bladecenter SoL
From: Ferenc Wagner @ 2012-10-02 12:07 UTC (permalink / raw)
  To: Michael Chan
  Cc: netdev, Matt Carlson, Grant Likely, Rob Herring, linux-kernel,
	wferi
In-Reply-To: <1349083982.5420.16.camel@LTIRV-MCHAN1.corp.ad.broadcom.com>

"Michael Chan" <mchan@broadcom.com> writes:

> On Fri, 2012-09-28 at 22:45 +0200, Ferenc Wagner wrote: 
> 
>> Upgrading the kernel on our HS20 blades resulted in their SoL (serial
>> over LAN) connection being broken.  The disconnection happens when eth0
>> (the interface involved in SoL) is brought up during the boot sequence.
>> If I later "ip link set eth0 down", then the connection is restored, but
>> "ip link set eth0 up" breaks it again on 3.2.  ethtool -a, -c, -g, -k
>> and -u show no difference; ethtool -i on the 2.6.32 kernel reports:
>> 
>> driver: tg3
>> version: 3.116
>> firmware-version: 5704s-v3.38, ASFIPMIs v2.47
>> bus-info: 0000:05:01.0
>> 
>> In the 3.2 kernel the driver version is 3.121.
>
> 2.6.32 to 3.2 is a big jump.  Can you narrow this down further?  It will
> be hard for us to find a HS20 with 5704 to test this.  Thanks.

I'm done with bisecting it: the first bad commit is:

commit dabc5c670d3f86d15ee4f42ab38ec5bd2682487d
Author: Matt Carlson <mcarlson@broadcom.com>
Date:   Thu May 19 12:12:52 2011 +0000

    tg3: Move TSO_CAPABLE assignment
    
    This patch moves the code that asserts the TSO_CAPABLE flag closer to
    where the TSO capabilities flags are set.  There isn't a good enough
    reason for the code to be separated.
    
    Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
    Reviewed-by: Michael Chan <mchan@broadcom.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

On the other hand, losing the SoL console even temporarily during boot
(as it happens with a minimal kernel before this commit) isn't nice
either.  I'll try to look after that, too, just mentioning it here...
-- 
Regards,
Feri.

^ permalink raw reply

* Re: [RFC PATCH net-next] tcp: introduce tcp_tw_interval to specifiy the time of TIME-WAIT
From: Neil Horman @ 2012-10-02 12:09 UTC (permalink / raw)
  To: Cong Wang
  Cc: netdev, David S. Miller, Alexey Kuznetsov, Patrick McHardy,
	Eric Dumazet
In-Reply-To: <1349161479.22107.17.camel@cr0>

On Tue, Oct 02, 2012 at 03:04:39PM +0800, Cong Wang wrote:
> On Fri, 2012-09-28 at 09:16 -0400, Neil Horman wrote:
> > On Fri, Sep 28, 2012 at 02:33:07PM +0800, Cong Wang wrote:
> > > On Thu, 2012-09-27 at 10:23 -0400, Neil Horman wrote:
> > > > On Thu, Sep 27, 2012 at 04:41:01PM +0800, Cong Wang wrote:
> > > > > Some customer requests this feature, as they stated:
> > > > > 
> > > > > 	"This parameter is necessary, especially for software that continually 
> > > > >         creates many ephemeral processes which open sockets, to avoid socket 
> > > > >         exhaustion. In many cases, the risk of the exhaustion can be reduced by 
> > > > >         tuning reuse interval to allow sockets to be reusable earlier.
> > > > > 
> > > > >         In commercial Unix systems, this kind of parameters, such as 
> > > > >         tcp_timewait in AIX and tcp_time_wait_interval in HP-UX, have 
> > > > >         already been available. Their implementations allow users to tune 
> > > > >         how long they keep TCP connection as TIME-WAIT state on the 
> > > > >         millisecond time scale."
> > > > > 
> > > > > We indeed have "tcp_tw_reuse" and "tcp_tw_recycle", but these tunings
> > > > > are not equivalent in that they cannot be tuned directly on the time
> > > > > scale nor in a safe way, as some combinations of tunings could still
> > > > > cause some problem in NAT. And, I think second scale is enough, we don't
> > > > > have to make it in millisecond time scale.
> > > > > 
> > > > I think I have a little difficultly seeing how this does anything other than
> > > > pay lip service to actually having sockets spend time in TIME_WAIT state.  That
> > > > is to say, while I see users using this to just make the pain stop.  If we wait
> > > > less time than it takes to be sure that a connection isn't being reused (either
> > > > by waiting two segment lifetimes, or by checking timestamps), then you might as
> > > > well not wait at all.  I see how its tempting to be able to say "Just don't wait
> > > > as long", but it seems that theres no difference between waiting half as long as
> > > > the RFC mandates, and waiting no time at all.  Neither is a good idea.
> > > 
> > > I don't think reducing TIME_WAIT is a good idea either, but there must
> > > be some reason behind as several UNIX provides a microsecond-scale
> > > tuning interface, or maybe in non-recycle mode, their RTO is much less
> > > than 2*MSL?
> > > 
> > My guess?  Cash was the reason.  I certainly wasn't there for any of those
> > developments, but a setting like this just smells to me like some customer waved
> > some cash under IBM's/HP's/Sun's nose and said, "We'd like to get our tcp
> > sockets back to CLOSED state faster, what can you do for us?"
> 
> Yeah, maybe. But it still doesn't make sense even if they are sure their
> packets are impossible to linger in their high-speed LAN for 2*MSL?
> 
No it doesn't make sense, but the universal rule is that the business people
will focus more on revenue recognition than on sound design pracice.

> > 
> > > > 
> > > > Given the problem you're trying to solve here, I'll ask the standard question in
> > > > response: How does using SO_REUSEADDR not solve the problem?  Alternatively, in
> > > > a pinch, why not reduce the tcp_max_tw_buckets sufficiently to start forcing
> > > > TIME_WAIT sockets back into CLOSED state?
> > > > 
> > > > The code looks fine, but the idea really doesn't seem like a good plan to me.
> > > > I'm sure HPUX/Solaris/AIX/etc have done this in response to customer demand, but
> > > > that doesn't make it the right solution.
> > > > 
> > > 
> > > *I think* the customer doesn't want to modify their applications, so
> > > that is why they don't use SO_REUSERADDR.
> > > 
> > Well, ok, thats a legitimate distro problem.  What its not is an upstream
> > problem.  Fixing the appilcation is the right thing to do, wether or not they
> > want to. 
> > 
> > > I didn't know tcp_max_tw_buckets can do the trick, nor the customer, so
> > > this is a side effect of tcp_max_tw_buckets? Is it documented?
> > man 7 tcp:
> > tcp_max_tw_buckets (integer; default: see below; since Linux 2.4)
> > 	The maximum number of sockets in TIME_WAIT state allowed in the
> > 	system.  This limit exists only  to  prevent  simple
> > 	denial-of-service attacks.   The  default  value of NR_FILE*2 is
> >         adjusted depending on the memory in the system.  If this number
> > 	is exceeded, the socket is closed and a warning is printed.
> > 
> 
> Hey, "a warning is printed" seems not very friendly. ;)
> 
No, its not very friendly, but the people using this are violating the RFC,
which isn't very friendly. :)

> Thanks!
> 
> 

^ permalink raw reply

* Re: GPF in ip6_dst_lookup_tail
From: Dave Jones @ 2012-10-02 13:59 UTC (permalink / raw)
  To: netdev
In-Reply-To: <20120927140323.GA1459@redhat.com>

On Thu, Sep 27, 2012 at 10:03:23AM -0400, Dave Jones wrote:

 > general protection fault: 0000 [#1] SMP 
 > Modules linked in: ipt_ULOG tun fuse binfmt_misc nfnetlink nfc caif_socket caif phonet can llc2 pppoe pppox ppp_generic slhc irda crc_ccitt rds af_key decnet rose x25 atm netrom appletalk ipx p8023 psnap p8022 llc ax25 lockd sunrpc bluetooth rfkill ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack kvm_intel kvm usb_debug crc32c_intel ghash_clmulni_intel microcode pcspkr i2c_i801 e1000e uinput i915 video i2c_algo_bit drm_kms_helper drm i2c_core
 > CPU 4 
 > Pid: 21651, comm: trinity-child4 Not tainted 3.6.0-rc7+ #55
 > RIP: 0010:[<ffffffff81628797>]  [<ffffffff81628797>] ip6_dst_lookup_tail+0x147/0x380
 > RSP: 0018:ffff8800144c3a48  EFLAGS: 00010286
 > RAX: 8000000000000011 RBX: ffff8800144c3b00 RCX: 0000000000000001
 > RDX: ffff8800144c2000 RSI: 0000000000000000 RDI: 0000000000000282
 > RBP: ffff8800144c3ae8 R08: 0000000000000014 R09: ffff8800034708c0
 > R10: ffffffff81c34a60 R11: 0000000000000000 R12: 0000000000000000
 > R13: ffff8800144c3bf0 R14: ffffffff81cd9580 R15: ffff8801052e4200
 > FS:  00007f74949af740(0000) GS:ffff880148400000(0000) knlGS:0000000000000000
 > CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
 > CR2: 00000000051f7000 CR3: 00000000a8f72000 CR4: 00000000001407e0
 > DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
 > DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
 > Process trinity-child4 (pid: 21651, threadinfo ffff8800144c2000, task ffff880003470000)
 > Stack:
 >  ffffffff81628730 ffffffff810dafbf ffff880003470000 0000000000000000
 >  ffff8800144c3aa8 0000000000000282 ffff8800144c3aa8 ffff88013d79dd40
 >  ffff8801052e4200 0000000000000003 0000000000000001 0000000000000000
 > Call Trace:
 >  [<ffffffff81628730>] ? ip6_dst_lookup_tail+0xe0/0x380
 >  [<ffffffff810dafbf>] ? lock_release_holdtime.part.26+0xf/0x180
 >  [<ffffffff81556b20>] ? sock_def_wakeup+0x1b0/0x1b0
 >  [<ffffffff81628a9b>] ip6_sk_dst_lookup_flow+0xcb/0x1b0
 >  [<ffffffff81649d8d>] udpv6_sendmsg+0x6ad/0xc40
 >  [<ffffffff81023af9>] ? native_sched_clock+0x19/0x80
 >  [<ffffffff810db438>] ? trace_hardirqs_off_caller+0x28/0xd0
 >  [<ffffffff810db4ed>] ? trace_hardirqs_off+0xd/0x10
 >  [<ffffffff815e613a>] inet_sendmsg+0x12a/0x240
 >  [<ffffffff815e6010>] ? inet_create+0x6f0/0x6f0
 >  [<ffffffff815562a1>] ? sock_update_classid+0xb1/0x390
 >  [<ffffffff81556340>] ? sock_update_classid+0x150/0x390
 >  [<ffffffff8155115c>] sock_sendmsg+0xbc/0xf0
 >  [<ffffffff810b46c9>] ? local_clock+0x99/0xc0
 >  [<ffffffff810dff4f>] ? lock_release_non_nested+0x2df/0x320
 >  [<ffffffff810dafbf>] ? lock_release_holdtime.part.26+0xf/0x180
 >  [<ffffffff81553740>] sys_sendto+0x130/0x180
 >  [<ffffffff816af8ad>] system_call_fastpath+0x1a/0x1f
 > Code: c0 74 19 80 3d 0e 4d 6d 00 00 75 10 e8 73 cb af ff 85 c0 0f 85 e3 01 00 00 0f 1f 00 48 8b 03 48 8b 80 98 00 00 00 48 85 c0 74 09 <f6> 80 6d 01 00 00 de 74 48 e8 3b db a6 ff 85 c0 74 0d 80 3d d5 
 > 
 > The disassembly points here..
 > 
 >  983         rcu_read_lock();
 >  984         rt = (struct rt6_info *) *dst;
 >  985         n = rt->n;
 >  986         if (n && !(n->nud_state & NUD_VALID)) {
 >      db2:       48 85 c0                test   %rax,%rax
 >      db5:       74 09                   je     dc0 <ip6_dst_lookup_tail+0x150>
 >      db7:       f6 80 6d 01 00 00 de    testb  $0xde,0x16d(%rax)
 >      dbe:       74 48                   je     e08 <ip6_dst_lookup_tail+0x198>
 > 
 > 'rt->n' is 0x8000000000000011, which looks like one of the garbage values trinity generates

I hit this a few more times last night.  I'm starting to doubt my theory of where
that value came from, as every instance is always 0x8000000000000011, which seems
a little too lucky.  Anyone have any idea what that number resembles ?

Working on some code to make this (and other bugs) more reproducable today..

	Dave

^ permalink raw reply

* [PATCHv4] rtlwifi: rtl8192ce: rtl8192cu: use %*phC to dump small buffers
From: Andy Shevchenko @ 2012-10-02 14:19 UTC (permalink / raw)
  To: Larry Finger, Chaoming Li, David S . Miller,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, Joe Perches
  Cc: Andy Shevchenko

The patch changes a bit trace output format in the rtl_cam_program_entry() to
print prefix and the actual data on the same line. Moreover the %*phC outputs
each byte as 2 hex digits, which is slightly different to the original %x.

Signed-off-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
ACKed-by: Larry Finger <Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
---
 drivers/net/wireless/rtlwifi/cam.c          |    7 ++-----
 drivers/net/wireless/rtlwifi/rtl8192ce/hw.c |    6 ++----
 drivers/net/wireless/rtlwifi/rtl8192cu/hw.c |    6 ++----
 3 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c
index 5b4b4d4..ca69e35 100644
--- a/drivers/net/wireless/rtlwifi/cam.c
+++ b/drivers/net/wireless/rtlwifi/cam.c
@@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
 	u32 target_content = 0;
 	u8 entry_i;
 
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-		 "key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
-		 key_cont_128[0], key_cont_128[1],
-		 key_cont_128[2], key_cont_128[3],
-		 key_cont_128[4], key_cont_128[5]);
+	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "key_cont_128: %6phC\n",
+		 key_cont_128);
 
 	for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
 		target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index 86d73b3..038c02c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -1918,10 +1918,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
 				     (ratr_index << 28);
 	rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
-		 "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
-		 ratr_index, ratr_bitmap,
-		 rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
-		 rate_mask[4]);
+		 "Rate_index:%x, ratr_val:%x, %5phC\n",
+		 ratr_index, ratr_bitmap, rate_mask);
 	rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
 
 	if (macid != 0)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 4bbb711..7d36a94 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -2169,10 +2169,8 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 				      ratr_index << 28);
 	rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
-		 "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
-		 ratr_index, ratr_bitmap,
-		 rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3],
-		 rate_mask[4]);
+		 "Rate_index:%x, ratr_val:%x, %5phC\n",
+		 ratr_index, ratr_bitmap, rate_mask);
 	rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
 }
 
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* RE: [PATCH net, 3/3] hyperv: Fix page buffer handling in rndis_filter_send_request()
From: Haiyang Zhang @ 2012-10-02 14:28 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: olaf@aepfle.de, netdev@vger.kernel.org, jasowang@redhat.com,
	linux-kernel@vger.kernel.org, devel@linuxdriverproject.org,
	davem@davemloft.net
In-Reply-To: <20121002083847.GR4587@mwanda>



> -----Original Message-----
> From: Dan Carpenter [mailto:dan.carpenter@oracle.com]
> Sent: Tuesday, October 02, 2012 4:39 AM
> To: Haiyang Zhang
> Cc: davem@davemloft.net; netdev@vger.kernel.org; olaf@aepfle.de;
> jasowang@redhat.com; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org
> Subject: Re: [PATCH net, 3/3] hyperv: Fix page buffer handling in
> rndis_filter_send_request()
> 
> On Mon, Oct 01, 2012 at 03:30:57PM -0700, Haiyang Zhang wrote:
> > Add another page buffer if the request message crossed page boundary.
> >
> 
> What are the user visible effects of this bug fix?  Please put that
> in the commit message.

Will do.

Thanks,
- Haiyang

^ permalink raw reply

* Re: tg3 driver upgrade (Linux 2.6.32 -> 3.2) breaks IBM Bladecenter SoL
From: Michael Chan @ 2012-10-02 15:03 UTC (permalink / raw)
  To: Ferenc Wagner
  Cc: netdev, Matt Carlson, Grant Likely, Rob Herring, linux-kernel
In-Reply-To: <87a9w5dqle.fsf@lant.ki.iif.hu>

On Tue, 2012-10-02 at 14:07 +0200, Ferenc Wagner wrote:
> I'm done with bisecting it: the first bad commit is:
> 
> commit dabc5c670d3f86d15ee4f42ab38ec5bd2682487d
> Author: Matt Carlson <mcarlson@broadcom.com>
> Date:   Thu May 19 12:12:52 2011 +0000
> 
>     tg3: Move TSO_CAPABLE assignment
>     
>     This patch moves the code that asserts the TSO_CAPABLE flag closer
> to
>     where the TSO capabilities flags are set.  There isn't a good
> enough
>     reason for the code to be separated.
>     
>     Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
>     Reviewed-by: Michael Chan <mchan@broadcom.com>
>     Signed-off-by: David S. Miller <davem@davemloft.net>

Thanks, I'll look into this.
> 
> On the other hand, losing the SoL console even temporarily during boot
> (as it happens with a minimal kernel before this commit) isn't nice
> either.  I'll try to look after that, too, just mentioning it here... 

This is expected as the driver has to reset the link and you'll lose SoL
for a few seconds until link comes back up.  We can look into an
enhancement to not touch the link if it is already in a good state when
the driver comes up.

^ permalink raw reply

* [PATCH net-next,4/6] hyperv: Remove extra allocated space for recv_pkt_list elements
From: Haiyang Zhang @ 2012-10-02 15:30 UTC (permalink / raw)
  To: davem, netdev; +Cc: haiyangz, kys, olaf, jasowang, linux-kernel, devel
In-Reply-To: <1349191824-14001-1-git-send-email-haiyangz@microsoft.com>

The receive code path doesn't use the page buffer, so remove the
extra allocated space here.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>

---
 drivers/net/hyperv/hyperv_net.h |    2 --
 drivers/net/hyperv/netvsc.c     |    4 +---
 2 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 95ceb35..d58f28c 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -465,8 +465,6 @@ struct nvsp_message {
 
 #define NETVSC_RECEIVE_BUFFER_ID		0xcafe
 
-#define NETVSC_RECEIVE_SG_COUNT			1
-
 /* Preallocated receive packets */
 #define NETVSC_RECEIVE_PACKETLIST_COUNT		256
 
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 4a1a5f5..d9c4c03 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -904,9 +904,7 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
 	INIT_LIST_HEAD(&net_device->recv_pkt_list);
 
 	for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
-		packet = kzalloc(sizeof(struct hv_netvsc_packet) +
-				 (NETVSC_RECEIVE_SG_COUNT *
-				  sizeof(struct hv_page_buffer)), GFP_KERNEL);
+		packet = kzalloc(sizeof(struct hv_netvsc_packet), GFP_KERNEL);
 		if (!packet)
 			break;
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH net-next,6/6] hyperv: Add buffer for extended info after the RNDIS response message.
From: Haiyang Zhang @ 2012-10-02 15:30 UTC (permalink / raw)
  To: davem, netdev; +Cc: haiyangz, kys, olaf, jasowang, linux-kernel, devel
In-Reply-To: <1349191824-14001-1-git-send-email-haiyangz@microsoft.com>

In some response messages, there may be some extended info after the
message.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>

---
 drivers/net/hyperv/rndis_filter.c |   22 ++++++++++++----------
 1 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index e7e12cf..928148c 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -32,16 +32,19 @@
 #include "hyperv_net.h"
 
 
+#define RNDIS_EXT_LEN 100
 struct rndis_request {
 	struct list_head list_ent;
 	struct completion  wait_event;
 
+	struct rndis_message response_msg;
 	/*
-	 * FIXME: We assumed a fixed size response here. If we do ever need to
-	 * handle a bigger response, we can either define a max response
-	 * message or add a response buffer variable above this field
+	 * The buffer for extended info after the RNDIS response message. It's
+	 * referenced based on the data offset in the RNDIS message. Its size
+	 * is enough for current needs, and should be sufficient for the near
+	 * future.
 	 */
-	struct rndis_message response_msg;
+	u8 response_ext[RNDIS_EXT_LEN];
 
 	/* Simplify allocation by having a netvsc packet inline */
 	struct hv_netvsc_packet	pkt;
@@ -50,12 +53,10 @@ struct rndis_request {
 
 	struct rndis_message request_msg;
 	/*
-	 * The buffer for the extended info after the RNDIS message. It's
-	 * referenced based on the data offset in the RNDIS message. Its size
-	 * is enough for current needs, and should be sufficient for the near
-	 * future.
+	 * The buffer for the extended info after the RNDIS request message.
+	 * It is referenced and sized in a similar way as response_ext.
 	 */
-	u8 ext[100];
+	u8 request_ext[RNDIS_EXT_LEN];
 };
 
 static void rndis_filter_send_completion(void *ctx);
@@ -274,7 +275,8 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
 	spin_unlock_irqrestore(&dev->request_lock, flags);
 
 	if (found) {
-		if (resp->msg_len <= sizeof(struct rndis_message)) {
+		if (resp->msg_len <=
+		    sizeof(struct rndis_message) + RNDIS_EXT_LEN) {
 			memcpy(&request->response_msg, resp,
 			       resp->msg_len);
 		} else {
-- 
1.7.4.1

^ permalink raw reply related

* Re: [PATCHv2 net-next] vxlan: put UDP socket in correct namespace
From: Eric W. Biederman @ 2012-10-02 15:18 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20121001214921.78d9ed72@nehalam.linuxnetplumber.net>

Stephen Hemminger <shemminger@vyatta.com> writes:

> Move vxlan UDP socket to correct network namespace
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

Looks good from here.

Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>

> ---
> v2 need to change sock_release to sk_release_kernel
>
> --- a/drivers/net/vxlan.c	2012-10-01 17:18:30.776513263 -0700
> +++ b/drivers/net/vxlan.c	2012-10-01 21:47:40.435979178 -0700
> @@ -1136,6 +1136,9 @@ static __net_init int vxlan_init_net(str
>  		pr_debug("UDP socket create failed\n");
>  		return rc;
>  	}
> +	/* Put in proper namespace */
> +	sk = vn->sock->sk;
> +	sk_change_net(sk, net);
>  
>  	vxlan_addr.sin_port = htons(vxlan_port);
>  
> @@ -1144,13 +1147,12 @@ static __net_init int vxlan_init_net(str
>  	if (rc < 0) {
>  		pr_debug("bind for UDP socket %pI4:%u (%d)\n",
>  			 &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc);
> -		sock_release(vn->sock);
> +		sk_release_kernel(sk);
>  		vn->sock = NULL;
>  		return rc;
>  	}
>  
>  	/* Disable multicast loopback */
> -	sk = vn->sock->sk;
>  	inet_sk(sk)->mc_loop = 0;
>  
>  	/* Mark socket as an encapsulation socket. */
> @@ -1169,7 +1171,7 @@ static __net_exit void vxlan_exit_net(st
>  	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
>  
>  	if (vn->sock) {
> -		sock_release(vn->sock);
> +		sk_release_kernel(vn->sock->sk);
>  		vn->sock = NULL;
>  	}
>  }
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH net-next,1/6] hyperv: Fix the max_xfer_size in RNDIS initialization
From: Haiyang Zhang @ 2012-10-02 15:30 UTC (permalink / raw)
  To: davem, netdev; +Cc: haiyangz, kys, olaf, jasowang, linux-kernel, devel

According to RNDIS specs, Windows sets this size to
0x4000. I use the same value here.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>

---
 drivers/net/hyperv/rndis_filter.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 06f8601..1337b64 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -684,8 +684,7 @@ static int rndis_filter_init_device(struct rndis_device *dev)
 	init = &request->request_msg.msg.init_req;
 	init->major_ver = RNDIS_MAJOR_VERSION;
 	init->minor_ver = RNDIS_MINOR_VERSION;
-	/* FIXME: Use 1536 - rounded ethernet frame size */
-	init->max_xfer_size = 2048;
+	init->max_xfer_size = 0x4000;
 
 	dev->state = RNDIS_DEV_INITIALIZING;
 
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH net-next,2/6] hyperv: Fix the missing return value in rndis_filter_set_packet_filter()
From: Haiyang Zhang @ 2012-10-02 15:30 UTC (permalink / raw)
  To: davem, netdev; +Cc: haiyangz, kys, olaf, jasowang, linux-kernel, devel
In-Reply-To: <1349191824-14001-1-git-send-email-haiyangz@microsoft.com>

Return ETIMEDOUT when the reply message is not received in time.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>

---
 drivers/net/hyperv/rndis_filter.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 1337b64..617eb2e 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -647,6 +647,7 @@ int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
 	if (t == 0) {
 		netdev_err(ndev,
 			"timeout before we got a set response...\n");
+		ret = -ETIMEDOUT;
 		/*
 		 * We can't deallocate the request since we may still receive a
 		 * send completion for it.
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH net-next, 3/6] hyperv: Fix page buffer handling in rndis_filter_send_request()
From: Haiyang Zhang @ 2012-10-02 15:30 UTC (permalink / raw)
  To: davem, netdev; +Cc: olaf, jasowang, linux-kernel, devel, haiyangz
In-Reply-To: <1349191824-14001-1-git-send-email-haiyangz@microsoft.com>

To prevent possible data corruption in RNDIS requests, add another
page buffer if the request message crossed page boundary.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>

---
 drivers/net/hyperv/rndis_filter.c |   15 ++++++++++++++-
 1 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 617eb2e..f25f41e 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -45,7 +45,8 @@ struct rndis_request {
 
 	/* Simplify allocation by having a netvsc packet inline */
 	struct hv_netvsc_packet	pkt;
-	struct hv_page_buffer buf;
+	/* Set 2 pages for rndis requests crossing page boundary */
+	struct hv_page_buffer buf[2];
 
 	struct rndis_message request_msg;
 	/*
@@ -227,6 +228,18 @@ static int rndis_filter_send_request(struct rndis_device *dev,
 	packet->page_buf[0].offset =
 		(unsigned long)&req->request_msg & (PAGE_SIZE - 1);
 
+	/* Add one page_buf when request_msg crossing page boundary */
+	if (packet->page_buf[0].offset + packet->page_buf[0].len > PAGE_SIZE) {
+		packet->page_buf_cnt++;
+		packet->page_buf[0].len = PAGE_SIZE -
+			packet->page_buf[0].offset;
+		packet->page_buf[1].pfn = virt_to_phys((void *)&req->request_msg
+			+ packet->page_buf[0].len) >> PAGE_SHIFT;
+		packet->page_buf[1].offset = 0;
+		packet->page_buf[1].len = req->request_msg.msg_len -
+			packet->page_buf[0].len;
+	}
+
 	packet->completion.send.send_completion_ctx = req;/* packet; */
 	packet->completion.send.send_completion =
 		rndis_filter_send_request_completion;
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH net-next,5/6] hyperv: Report actual status in receive completion packet
From: Haiyang Zhang @ 2012-10-02 15:30 UTC (permalink / raw)
  To: davem, netdev; +Cc: haiyangz, kys, olaf, jasowang, linux-kernel, devel
In-Reply-To: <1349191824-14001-1-git-send-email-haiyangz@microsoft.com>

The existing code always reports NVSP_STAT_SUCCESS. This patch adds the
mechanism to report failure when it happens.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>

---
 drivers/net/hyperv/hyperv_net.h   |    2 ++
 drivers/net/hyperv/netvsc.c       |   18 ++++++++++++------
 drivers/net/hyperv/netvsc_drv.c   |    2 ++
 drivers/net/hyperv/rndis_filter.c |   19 ++++++++++++++-----
 4 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index d58f28c..5fd6f46 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -35,6 +35,7 @@ struct hv_netvsc_packet;
 /* Represent the xfer page packet which contains 1 or more netvsc packet */
 struct xferpage_packet {
 	struct list_head list_ent;
+	u32 status;
 
 	/* # of netvsc packets this xfer packet contains */
 	u32 count;
@@ -47,6 +48,7 @@ struct xferpage_packet {
 struct hv_netvsc_packet {
 	/* Bookkeeping stuff */
 	struct list_head list_ent;
+	u32 status;
 
 	struct hv_device *device;
 	bool is_data_pkt;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index d9c4c03..1cd7748 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -558,7 +558,7 @@ int netvsc_send(struct hv_device *device,
 }
 
 static void netvsc_send_recv_completion(struct hv_device *device,
-					u64 transaction_id)
+					u64 transaction_id, u32 status)
 {
 	struct nvsp_message recvcompMessage;
 	int retries = 0;
@@ -571,9 +571,7 @@ static void netvsc_send_recv_completion(struct hv_device *device,
 	recvcompMessage.hdr.msg_type =
 				NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
 
-	/* FIXME: Pass in the status */
-	recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status =
-		NVSP_STAT_SUCCESS;
+	recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = status;
 
 retry_send_cmplt:
 	/* Send the completion */
@@ -613,6 +611,7 @@ static void netvsc_receive_completion(void *context)
 	bool fsend_receive_comp = false;
 	unsigned long flags;
 	struct net_device *ndev;
+	u32 status = NVSP_STAT_NONE;
 
 	/*
 	 * Even though it seems logical to do a GetOutboundNetDevice() here to
@@ -627,6 +626,9 @@ static void netvsc_receive_completion(void *context)
 	/* Overloading use of the lock. */
 	spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
 
+	if (packet->status != NVSP_STAT_SUCCESS)
+		packet->xfer_page_pkt->status = NVSP_STAT_FAIL;
+
 	packet->xfer_page_pkt->count--;
 
 	/*
@@ -636,6 +638,7 @@ static void netvsc_receive_completion(void *context)
 	if (packet->xfer_page_pkt->count == 0) {
 		fsend_receive_comp = true;
 		transaction_id = packet->completion.recv.recv_completion_tid;
+		status = packet->xfer_page_pkt->status;
 		list_add_tail(&packet->xfer_page_pkt->list_ent,
 			      &net_device->recv_pkt_list);
 
@@ -647,7 +650,7 @@ static void netvsc_receive_completion(void *context)
 
 	/* Send a receive completion for the xfer page packet */
 	if (fsend_receive_comp)
-		netvsc_send_recv_completion(device, transaction_id);
+		netvsc_send_recv_completion(device, transaction_id, status);
 
 }
 
@@ -736,7 +739,8 @@ static void netvsc_receive(struct hv_device *device,
 				       flags);
 
 		netvsc_send_recv_completion(device,
-					    vmxferpage_packet->d.trans_id);
+					    vmxferpage_packet->d.trans_id,
+					    NVSP_STAT_FAIL);
 
 		return;
 	}
@@ -744,6 +748,7 @@ static void netvsc_receive(struct hv_device *device,
 	/* Remove the 1st packet to represent the xfer page packet itself */
 	xferpage_packet = (struct xferpage_packet *)listHead.next;
 	list_del(&xferpage_packet->list_ent);
+	xferpage_packet->status = NVSP_STAT_SUCCESS;
 
 	/* This is how much we can satisfy */
 	xferpage_packet->count = count - 1;
@@ -760,6 +765,7 @@ static void netvsc_receive(struct hv_device *device,
 		list_del(&netvsc_packet->list_ent);
 
 		/* Initialize the netvsc packet */
+		netvsc_packet->status = NVSP_STAT_SUCCESS;
 		netvsc_packet->xfer_page_pkt = xferpage_packet;
 		netvsc_packet->completion.recv.recv_completion =
 					netvsc_receive_completion;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index e91111a..f825a62 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -265,6 +265,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
 	if (!net) {
 		netdev_err(net, "got receive callback but net device"
 			" not initialized yet\n");
+		packet->status = NVSP_STAT_FAIL;
 		return 0;
 	}
 
@@ -272,6 +273,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
 	skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen);
 	if (unlikely(!skb)) {
 		++net->stats.rx_dropped;
+		packet->status = NVSP_STAT_FAIL;
 		return 0;
 	}
 
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index f25f41e..e7e12cf 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -411,9 +411,12 @@ int rndis_filter_receive(struct hv_device *dev,
 	struct rndis_device *rndis_dev;
 	struct rndis_message *rndis_msg;
 	struct net_device *ndev;
+	int ret = 0;
 
-	if (!net_dev)
-		return -EINVAL;
+	if (!net_dev) {
+		ret = -EINVAL;
+		goto exit;
+	}
 
 	ndev = net_dev->ndev;
 
@@ -421,14 +424,16 @@ int rndis_filter_receive(struct hv_device *dev,
 	if (!net_dev->extension) {
 		netdev_err(ndev, "got rndis message but no rndis device - "
 			  "dropping this message!\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto exit;
 	}
 
 	rndis_dev = (struct rndis_device *)net_dev->extension;
 	if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
 		netdev_err(ndev, "got rndis message but rndis device "
 			   "uninitialized...dropping this message!\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto exit;
 	}
 
 	rndis_msg = pkt->data;
@@ -460,7 +465,11 @@ int rndis_filter_receive(struct hv_device *dev,
 		break;
 	}
 
-	return 0;
+exit:
+	if (ret != 0)
+		pkt->status = NVSP_STAT_FAIL;
+
+	return ret;
 }
 
 static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
-- 
1.7.4.1

^ permalink raw reply related

* Re: Possible networking regression in 3.6.0
From: Eric Dumazet @ 2012-10-02 15:35 UTC (permalink / raw)
  To: David Miller; +Cc: davej, chris2553, netdev, gpiez
In-Reply-To: <1349121884.12401.721.camel@edumazet-glaptop>

On Mon, 2012-10-01 at 22:04 +0200, Eric Dumazet wrote:
> On Mon, 2012-10-01 at 16:01 -0400, David Miller wrote:

> > If you can find a way to more reliably trigger the case, that would
> > help us immensely.
> 
> I am building a KMEMCHECK kernel, as a last try before my night ;)

This was a total disaster. KMEMCHECK dies horribly on my machine

David, shouldnt we use a nh_rth_forward instead of a nh_rth_input in
__mkroute_input() ?

(And change rt_cache_route() as well ?)

I am testing a patch right now.

^ permalink raw reply

* Re: Possible networking regression in 3.6.0
From: Eric Dumazet @ 2012-10-02 15:48 UTC (permalink / raw)
  To: David Miller; +Cc: chris2553, netdev, gpiez, Dave Jones
In-Reply-To: <1349192133.12401.768.camel@edumazet-glaptop>

From: Eric Dumazet <edumazet@google.com>

On Tue, 2012-10-02 at 17:35 +0200, Eric Dumazet wrote:
> On Mon, 2012-10-01 at 22:04 +0200, Eric Dumazet wrote:
> > On Mon, 2012-10-01 at 16:01 -0400, David Miller wrote:
> 
> > > If you can find a way to more reliably trigger the case, that would
> > > help us immensely.
> > 
> > I am building a KMEMCHECK kernel, as a last try before my night ;)
> 
> This was a total disaster. KMEMCHECK dies horribly on my machine
> 
> David, shouldnt we use a nh_rth_forward instead of a nh_rth_input in
> __mkroute_input() ?
> 
> (And change rt_cache_route() as well ?)
> 
> I am testing a patch right now.

Yeah, this patch seems to fix the bug for me.

[PATCH] ipv4: properly cache forward routes

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.

Add a separate cache (nh_rth_forward) to solve the problem.

Many thanks to Chris Clayton for his patience and help.

Reported-by: Chris Clayton <chris2553@googlemail.com>
Bisected-by: Chris Clayton <chris2553@googlemail.com>
Reported-by: Dave Jones <davej@redhat.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/net/ip_fib.h     |    1 +
 net/ipv4/fib_semantics.c |    1 +
 net/ipv4/route.c         |   16 ++++++++--------
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 926142e..ce7ffe9 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -85,6 +85,7 @@ struct fib_nh {
 	int			nh_saddr_genid;
 	struct rtable __rcu * __percpu *nh_pcpu_rth_output;
 	struct rtable __rcu	*nh_rth_input;
+	struct rtable __rcu	*nh_rth_forward;
 	struct fnhe_hash_bucket	*nh_exceptions;
 };
 
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 3509065..45b5d1d 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -208,6 +208,7 @@ static void free_fib_info_rcu(struct rcu_head *head)
 			free_nh_exceptions(nexthop_nh);
 		rt_fibinfo_free_cpus(nexthop_nh->nh_pcpu_rth_output);
 		rt_fibinfo_free(&nexthop_nh->nh_rth_input);
+		rt_fibinfo_free(&nexthop_nh->nh_rth_forward);
 	} endfor_nexthops(fi);
 
 	release_net(fi->fib_net);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index ff62206..50898d6 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1193,14 +1193,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
 	return ret;
 }
 
-static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt)
+static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt, struct rtable **p)
 {
-	struct rtable *orig, *prev, **p;
+	struct rtable *orig, *prev;
 	bool ret = true;
 
-	if (rt_is_input_route(rt)) {
-		p = (struct rtable **)&nh->nh_rth_input;
-	} else {
+	if (!p) {
 		if (!nh->nh_pcpu_rth_output)
 			goto nocache;
 		p = (struct rtable **)__this_cpu_ptr(nh->nh_pcpu_rth_output);
@@ -1290,7 +1288,7 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
 		if (unlikely(fnhe))
 			cached = rt_bind_exception(rt, fnhe, daddr);
 		else if (!(rt->dst.flags & DST_NOCACHE))
-			cached = rt_cache_route(nh, rt);
+			cached = rt_cache_route(nh, rt, NULL);
 	}
 	if (unlikely(!cached))
 		rt_add_uncached_list(rt);
@@ -1462,7 +1460,7 @@ static int __mkroute_input(struct sk_buff *skb,
 	do_cache = false;
 	if (res->fi) {
 		if (!itag) {
-			rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+			rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_forward);
 			if (rt_cache_valid(rth)) {
 				skb_dst_set_noref(skb, &rth->dst);
 				goto out;
@@ -1493,6 +1491,8 @@ static int __mkroute_input(struct sk_buff *skb,
 
 	rt_set_nexthop(rth, daddr, res, NULL, res->fi, res->type, itag);
 	skb_dst_set(skb, &rth->dst);
+	if (do_cache)
+		rt_cache_route(&FIB_RES_NH(*res), rth, &FIB_RES_NH(*res).nh_rth_forward);
 out:
 	err = 0;
  cleanup:
@@ -1663,7 +1663,7 @@ local_input:
 		rth->rt_flags 	&= ~RTCF_LOCAL;
 	}
 	if (do_cache)
-		rt_cache_route(&FIB_RES_NH(res), rth);
+		rt_cache_route(&FIB_RES_NH(res), rth, &FIB_RES_NH(res).nh_rth_input);
 	skb_dst_set(skb, &rth->dst);
 	err = 0;
 	goto out;

^ permalink raw reply related

* Re: network namespace and kernel bind issue
From: Stephen Hemminger @ 2012-10-02 15:51 UTC (permalink / raw)
  To: Julian Anastasov, James Chapman; +Cc: Eric W. Biederman, netdev
In-Reply-To: <alpine.LFD.2.00.1210020910010.1642@ja.ssi.bg>

On Tue, 2 Oct 2012 09:15:46 +0300 (EEST)
Julian Anastasov <ja@ssi.bg> wrote:

> 
> 	Hello,
> 
> On Mon, 1 Oct 2012, Stephen Hemminger wrote:
> 
> > The problem was vxlan wasn't doing sk_change_net on the created socket.
> > 
> > I'm testing that fix.
> > 
> > The long term fix is to change sock_create_kern() to take a 'struct net'
> > argument. This would avoid the trap of having to change the namespace.
> > Also several places using __sock_create() could use it.
> > 
> > L2TP still looks to have several namespace related issues.
> 
> 	There should be also .netnsok = true in l2tp_nl_family
> as final step.
> 
> Regards
> 
> --
> Julian Anastasov <ja@ssi.bg>

There are actually lots more net namespace issues in L2TP.
For example session and tunnel counts are global, not per namespace.

^ permalink raw reply

* Re: Possible networking regression in 3.6.0
From: Dave Jones @ 2012-10-02 15:57 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, chris2553, netdev, gpiez
In-Reply-To: <1349192919.12401.778.camel@edumazet-glaptop>

On Tue, Oct 02, 2012 at 05:48:39PM +0200, Eric Dumazet wrote:
 > From: Eric Dumazet <edumazet@google.com>
 > 
 > On Tue, 2012-10-02 at 17:35 +0200, Eric Dumazet wrote:
 > > On Mon, 2012-10-01 at 22:04 +0200, Eric Dumazet wrote:
 > > > On Mon, 2012-10-01 at 16:01 -0400, David Miller wrote:
 > > 
 > > > > If you can find a way to more reliably trigger the case, that would
 > > > > help us immensely.
 > > > 
 > > > I am building a KMEMCHECK kernel, as a last try before my night ;)
 > > 
 > > This was a total disaster. KMEMCHECK dies horribly on my machine
 > > 
 > > David, shouldnt we use a nh_rth_forward instead of a nh_rth_input in
 > > __mkroute_input() ?
 > > 
 > > (And change rt_cache_route() as well ?)
 > > 
 > > I am testing a patch right now.
 > 
 > Yeah, this patch seems to fix the bug for me.

Good work! Any idea why it didn't happen on every build for me ?

>From your description, this should have failed every time ?

	Dave

^ permalink raw reply

* [PATCH net-next v6 0/1] Add support of ECMPv6
From: Nicolas Dichtel @ 2012-10-02 16:02 UTC (permalink / raw)
  To: joe; +Cc: bernat, netdev, yoshfuji, davem
In-Reply-To: <1349110077.7740.23.camel@joe-AO722>

Here is a proposal to add the support of ECMPv6. The previous patch
from Vincent against iproute2 can be used, but a little other patch is needed
too, see http://patchwork.ozlabs.org/patch/183277/

If the kernel patch is approved, I can submit formally the patch for
iproute2.

Here is an example of a command to add an ECMP route:
$ ip -6 route add 3ffe:304:124:2306::/64 \
	nexthop via fe80::230:1bff:feb4:e05c dev eth0 \
	nexthop via fe80::230:1bff:feb4:dd4f dev eth0

But note that this command is a shortcut and previous patches are not
mandatory to set ECMP routes. The following commands can be used too:
$ ip -6 route add 3ffe:304:124:2306::/64 via fe80::230:1bff:feb4:dd4f dev
eth0
$ ip -6 route append 3ffe:304:124:2306::/64 via fe80::230:1bff:feb4:e05c dev
eth0

Here is an example of a dump:
$ ip -6 route | grep 3ffe:304:124:2306::/64
3ffe:304:124:2306::/64 via fe80::230:1bff:feb4:dd4f dev eth0  metric 1024
3ffe:304:124:2306::/64 via fe80::230:1bff:feb4:e05c dev eth0  metric 1024

v6: be more verbose in commitlog
    add some helpers in ip6_fib.h to avoid to have too many ifdef block in the
    code
    invert fc_mp_len and fc_mp in struct fib6_config to avoid a hole on 64bits
    arch

v5: to minimize the patch and ease its integration, remove roundrobin and random
    algorithms for route selection. It will be possible to add new algorithms
    through rt6_info_hashfn() when the basic support of ECMP is integrated.

v4: remove compilation options to choose multipath algorithm for next hop
    selection. Now the choice can be done at run time via
    /proc/sys/net/ipv6/route/multipath_algorithm

v3: rebase after updating net-next

v2: rename CONFIG_IPV6_MULTIPATH_ROUTE to CONFIG_IPV6_MULTIPATH_HASH
    use flowlabel in the hash function
    add reference to RFC
    fix a small identation issue
    remove "If unsure, say N." from the help of CONFIG_IPV6_MULTIPATH

Comments are welcome.

Regards,
Nicolas

^ permalink raw reply

* [PATCH net-next v6 1/1] ipv6: add support of equal cost multipath (ECMP)
From: Nicolas Dichtel @ 2012-10-02 16:02 UTC (permalink / raw)
  To: joe; +Cc: bernat, netdev, yoshfuji, davem, Nicolas Dichtel
In-Reply-To: <1349193767-3992-1-git-send-email-nicolas.dichtel@6wind.com>

Each nexthop is added like a single route in the routing table. All routes
that have the same metric/weight and destination but not the same gateway
are considering as ECMP routes. They are linked together, through a list called
rt6i_siblings.

ECMP routes can be added in one shot, with RTA_MULTIPATH attribute or one after
the other (in both case, the flag NLM_F_EXCL should not be set).

The patch is based on a previous work from
Luc Saillard <luc.saillard@6wind.com>.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/net/ip6_fib.h |  50 +++++++++++++++
 net/ipv6/Kconfig      |  10 +++
 net/ipv6/ip6_fib.c    |  71 +++++++++++++++++++++
 net/ipv6/route.c      | 169 +++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 297 insertions(+), 3 deletions(-)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 8a2a203..2712572 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -47,6 +47,8 @@ struct fib6_config {
 	unsigned long	fc_expires;
 	struct nlattr	*fc_mx;
 	int		fc_mx_len;
+	int		fc_mp_len;
+	struct nlattr	*fc_mp;
 
 	struct nl_info	fc_nlinfo;
 };
@@ -98,6 +100,15 @@ struct rt6_info {
 	struct fib6_node		*rt6i_node;
 
 	struct in6_addr			rt6i_gateway;
+#ifdef CONFIG_IPV6_MULTIPATH
+	/*
+	 * siblings is a list of rt6_info that have the the same metric/weight,
+	 * destination, but not the same gateway. nsiblings is just a cache
+	 * to speed up lookup.
+	 */
+	unsigned int			rt6i_nsiblings;
+	struct list_head		rt6i_siblings;
+#endif
 
 	atomic_t			rt6i_ref;
 
@@ -318,4 +329,43 @@ static inline void              fib6_rules_cleanup(void)
 	return ;
 }
 #endif
+
+#ifdef CONFIG_IPV6_MULTIPATH
+static inline unsigned int ipv6_multipath_get_nsiblings(const struct rt6_info *rt)
+{
+	return rt->rt6i_nsiblings;
+}
+static inline void ipv6_multipath_reset_nsiblings(struct rt6_info *rt)
+{
+	rt->rt6i_nsiblings = 0;
+}
+static inline void ipv6_multipath_inc_nsiblings(struct rt6_info *rt)
+{
+	rt->rt6i_nsiblings++;
+}
+static inline void ipv6_multipath_dec_nsiblings(struct rt6_info *rt)
+{
+	rt->rt6i_nsiblings--;
+}
+#else
+static inline unsigned int ipv6_multipath_get_nsiblings(const struct rt6_info *rt)
+{
+	return 0;
+}
+static inline void ipv6_multipath_reset_nsiblings(struct rt6_info *rt)
+{
+}
+static inline void ipv6_multipath_inc_nsiblings(struct rt6_info *rt)
+{
+}
+static inline void ipv6_multipath_dec_nsiblings(struct rt6_info *rt)
+{
+}
+static inline struct rt6_info *rt6_multipath_select(struct net *net,
+						    struct rt6_info *rt,
+						    struct flowi6 *fl6)
+{
+	return rt;
+}
+#endif
 #endif
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 4f7fe72..fc2f3cb 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -266,4 +266,14 @@ config IPV6_PIMSM_V2
 	  Support for IPv6 PIM multicast routing protocol PIM-SMv2.
 	  If unsure, say N.
 
+config IPV6_MULTIPATH
+	bool "IPv6: equal cost multipath for IPv6 routing"
+	depends on IPV6
+	default y
+	---help---
+	  Enable this option to support ECMP for IPv6.
+
+	  The algorithm used for route selection is based on a hash of packet
+	  header (recommanded by RFC4311) and flowlabel (RFC6438).
+
 endif # IPV6
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 24995a9..ef4faf8 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -672,6 +672,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 			    iter->rt6i_idev == rt->rt6i_idev &&
 			    ipv6_addr_equal(&iter->rt6i_gateway,
 					    &rt->rt6i_gateway)) {
+				if (ipv6_multipath_get_nsiblings(rt))
+					ipv6_multipath_reset_nsiblings(rt);
 				if (!(iter->rt6i_flags & RTF_EXPIRES))
 					return -EEXIST;
 				if (!(rt->rt6i_flags & RTF_EXPIRES))
@@ -680,6 +682,21 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 					rt6_set_expires(iter, rt->dst.expires);
 				return -EEXIST;
 			}
+			/* If we have the same destination and the same metric,
+			 * but not the same gateway, then the route we try to
+			 * add is sibling to this route, increment our counter
+			 * of siblings, and later we will add our route to the
+			 * list.
+			 * Only static routes (which don't have flag
+			 * RTF_EXPIRES) are used for ECMPv6.
+			 *
+			 * To avoid long list, we only had siblings if the
+			 * route have a gateway.
+			 */
+			if (rt->rt6i_flags & RTF_GATEWAY &&
+			    !(rt->rt6i_flags & RTF_EXPIRES) &&
+			    !(iter->rt6i_flags & RTF_EXPIRES))
+				ipv6_multipath_inc_nsiblings(rt);
 		}
 
 		if (iter->rt6i_metric > rt->rt6i_metric)
@@ -692,6 +709,45 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 	if (ins == &fn->leaf)
 		fn->rr_ptr = NULL;
 
+#ifdef CONFIG_IPV6_MULTIPATH
+	/* Link this route to others same route. */
+	if (ipv6_multipath_get_nsiblings(rt)) {
+		unsigned int rt6i_nsiblings;
+		struct rt6_info *sibling, *temp_sibling;
+
+		/* Find the first route that have the same metric */
+		sibling = fn->leaf;
+		while (sibling) {
+			if (sibling->rt6i_metric == rt->rt6i_metric) {
+				list_add_tail(&rt->rt6i_siblings,
+					      &sibling->rt6i_siblings);
+				break;
+			}
+			sibling = sibling->dst.rt6_next;
+		}
+		/* For each sibling in the list, increment the counter of
+		 * siblings. We can check if all the counter are equal.
+		 */
+		rt6i_nsiblings = 0;
+		list_for_each_entry_safe(sibling, temp_sibling,
+					 &rt->rt6i_siblings,
+					 rt6i_siblings) {
+			ipv6_multipath_inc_nsiblings(sibling);
+			if (unlikely(ipv6_multipath_get_nsiblings(sibling) !=
+				     ipv6_multipath_get_nsiblings(rt))) {
+				pr_err("Wrong number of siblings for route %p (%d)\n",
+				       sibling, ipv6_multipath_get_nsiblings(sibling));
+			}
+			rt6i_nsiblings++;
+		}
+		if (unlikely(rt6i_nsiblings !=
+			     ipv6_multipath_get_nsiblings(rt))) {
+			pr_err("Wrong number of siblings for route %p. I have %d routes, but count %d siblings\n",
+			       rt, rt6i_nsiblings,
+			       ipv6_multipath_get_nsiblings(rt));
+		}
+	}
+#endif
 	/*
 	 *	insert node
 	 */
@@ -1193,6 +1249,21 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
 	if (fn->rr_ptr == rt)
 		fn->rr_ptr = NULL;
 
+#ifdef CONFIG_IPV6_MULTIPATH
+	/* Remove this entry from other siblings */
+	if (ipv6_multipath_get_nsiblings(rt)) {
+		struct rt6_info *sibling, *next_sibling;
+
+		/* For each siblings, decrement the counter of siblings */
+		list_for_each_entry_safe(sibling, next_sibling,
+					 &rt->rt6i_siblings, rt6i_siblings) {
+			ipv6_multipath_dec_nsiblings(sibling);
+		}
+		ipv6_multipath_reset_nsiblings(rt);
+		list_del_init(&rt->rt6i_siblings);
+	}
+#endif
+
 	/* Adjust walkers */
 	read_lock(&fib6_walker_lock);
 	FOR_WALKERS(w) {
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index d1ddbc6..4c42b9e 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -57,6 +57,9 @@
 #include <net/xfrm.h>
 #include <net/netevent.h>
 #include <net/netlink.h>
+#ifdef CONFIG_IPV6_MULTIPATH
+#include <net/nexthop.h>
+#endif
 
 #include <asm/uaccess.h>
 
@@ -289,6 +292,10 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
 		memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
 		rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
 		rt->rt6i_genid = rt_genid(net);
+#ifdef CONFIG_IPV6_MULTIPATH
+		INIT_LIST_HEAD(&rt->rt6i_siblings);
+#endif
+		ipv6_multipath_reset_nsiblings(rt);
 	}
 	return rt;
 }
@@ -385,6 +392,92 @@ static bool rt6_need_strict(const struct in6_addr *daddr)
 		(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
 }
 
+#ifdef CONFIG_IPV6_MULTIPATH
+/*
+ *	Multipath route selection.
+ */
+
+/*
+ * Hash based function using packet header and flowlabel.
+ * Adapted from fib_info_hashfn()
+ */
+static int rt6_info_hash_nhsfn(unsigned int candidate_count,
+			       const struct flowi6 *fl6)
+{
+	unsigned int val = fl6->flowi6_proto;
+
+	val ^= fl6->daddr.s6_addr32[0];
+	val ^= fl6->daddr.s6_addr32[1];
+	val ^= fl6->daddr.s6_addr32[2];
+	val ^= fl6->daddr.s6_addr32[3];
+
+	val ^= fl6->saddr.s6_addr32[0];
+	val ^= fl6->saddr.s6_addr32[1];
+	val ^= fl6->saddr.s6_addr32[2];
+	val ^= fl6->saddr.s6_addr32[3];
+
+	/* Work only if this not encapsulated */
+	switch (fl6->flowi6_proto) {
+	case IPPROTO_UDP:
+	case IPPROTO_TCP:
+	case IPPROTO_SCTP:
+		val ^= fl6->fl6_sport;
+		val ^= fl6->fl6_dport;
+		break;
+
+	case IPPROTO_ICMPV6:
+		val ^= fl6->fl6_icmp_type;
+		val ^= fl6->fl6_icmp_code;
+		break;
+	}
+	/* RFC6438 recommands to use flowlabel */
+	val ^= fl6->flowlabel;
+
+	/* Perhaps, we need to tune, this function? */
+	val = val ^ (val >> 7) ^ (val >> 12);
+	return val % candidate_count;
+}
+
+/*
+ * This function returns an index used to select a route between any siblings.
+ *
+ * Note: fl6 can be NULL
+ */
+static unsigned int rt6_info_hashfn(struct net *net,
+				    const struct rt6_info *rt,
+				    const struct flowi6 *fl6)
+{
+	int candidate_count = ipv6_multipath_get_nsiblings(rt) + 1;
+
+	if (fl6 == NULL)
+		return 0;
+	return rt6_info_hash_nhsfn(candidate_count, fl6);
+}
+
+static struct rt6_info *rt6_multipath_select(struct net *net,
+					     struct rt6_info *match,
+					     struct flowi6 *fl6)
+{
+	struct rt6_info *sibling, *next_sibling;
+	int route_choosen;
+
+	route_choosen = rt6_info_hashfn(net, match, fl6);
+	/* Don't change the route, if route_choosen == 0
+	 * (siblings does not include ourself)
+	 */
+	if (route_choosen)
+		list_for_each_entry_safe(sibling, next_sibling,
+				&match->rt6i_siblings, rt6i_siblings) {
+			route_choosen--;
+			if (route_choosen == 0) {
+				match = sibling;
+				break;
+			}
+		}
+	return match;
+}
+#endif /* CONFIG_IPV6_MULTIPATH */
+
 /*
  *	Route lookup. Any table->tb6_lock is implied.
  */
@@ -702,6 +795,8 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 restart:
 	rt = fn->leaf;
 	rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
+	if (ipv6_multipath_get_nsiblings(rt) && fl6->flowi6_oif == 0)
+		rt = rt6_multipath_select(net, rt, fl6);
 	BACKTRACK(net, &fl6->saddr);
 out:
 	dst_use(&rt->dst, jiffies);
@@ -863,7 +958,8 @@ restart_2:
 
 restart:
 	rt = rt6_select(fn, oif, strict | reachable);
-
+	if (ipv6_multipath_get_nsiblings(rt) && oif == 0)
+		rt = rt6_multipath_select(net, rt, fl6);
 	BACKTRACK(net, &fl6->saddr);
 	if (rt == net->ipv6.ip6_null_entry ||
 	    rt->rt6i_flags & RTF_CACHE)
@@ -2248,6 +2344,9 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
 	[RTA_IIF]		= { .type = NLA_U32 },
 	[RTA_PRIORITY]          = { .type = NLA_U32 },
 	[RTA_METRICS]           = { .type = NLA_NESTED },
+#ifdef CONFIG_IPV6_MULTIPATH
+	[RTA_MULTIPATH]		= { .len = sizeof(struct rtnexthop) },
+#endif
 };
 
 static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -2325,11 +2424,69 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
 	if (tb[RTA_TABLE])
 		cfg->fc_table = nla_get_u32(tb[RTA_TABLE]);
 
+	if (tb[RTA_MULTIPATH]) {
+		cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
+		cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
+	}
+
 	err = 0;
 errout:
 	return err;
 }
 
+static int ip6_route_multipath(struct fib6_config *cfg, int add)
+{
+#ifdef CONFIG_IPV6_MULTIPATH
+	struct fib6_config r_cfg;
+	struct rtnexthop *rtnh;
+	int remaining;
+	int attrlen;
+	int err = 0, last_err = 0;
+
+beginning:
+	rtnh = (struct rtnexthop *)cfg->fc_mp;
+	remaining = cfg->fc_mp_len;
+
+	/* Parse a Multipath Entry */
+	while (rtnh_ok(rtnh, remaining)) {
+		memcpy(&r_cfg, cfg, sizeof(*cfg));
+		if (rtnh->rtnh_ifindex)
+			r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
+
+		attrlen = rtnh_attrlen(rtnh);
+		if (attrlen > 0) {
+			struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
+
+			nla = nla_find(attrs, attrlen, RTA_GATEWAY);
+			if (nla) {
+				nla_memcpy(&r_cfg.fc_gateway, nla, 16);
+				r_cfg.fc_flags |= RTF_GATEWAY;
+			}
+		}
+		err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg);
+		if (err) {
+			last_err = err;
+			/* If we are trying to remove a route, do not stop the
+			 * loop when ip6_route_del() fails (because next hop is
+			 * already gone), we should try to remove all next hops.
+			 */
+			if (add) {
+				/* If add fails, we should try to delete all
+				 * next hops that have been already added.
+				 */
+				add = 0;
+				goto beginning;
+			}
+		}
+		rtnh = rtnh_next(rtnh, &remaining);
+	}
+
+	return last_err;
+#else
+	return -ENOSYS;
+#endif /* CONFIG_IPV6_MULTIPATH */
+}
+
 static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
 	struct fib6_config cfg;
@@ -2339,7 +2496,10 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
 	if (err < 0)
 		return err;
 
-	return ip6_route_del(&cfg);
+	if (cfg.fc_mp)
+		return ip6_route_multipath(&cfg, 0);
+	else
+		return ip6_route_del(&cfg);
 }
 
 static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
@@ -2351,7 +2511,10 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
 	if (err < 0)
 		return err;
 
-	return ip6_route_add(&cfg);
+	if (cfg.fc_mp)
+		return ip6_route_multipath(&cfg, 1);
+	else
+		return ip6_route_add(&cfg);
 }
 
 static inline size_t rt6_nlmsg_size(void)
-- 
1.7.12

^ permalink raw reply related

* Re: Possible networking regression in 3.6.0
From: Eric Dumazet @ 2012-10-02 16:06 UTC (permalink / raw)
  To: Dave Jones; +Cc: David Miller, chris2553, netdev, gpiez
In-Reply-To: <20121002155738.GA20331@redhat.com>

On Tue, 2012-10-02 at 11:57 -0400, Dave Jones wrote:

> 
> Good work! Any idea why it didn't happen on every build for me ?
> 
> From your description, this should have failed every time ?

Well, it seems that as long as you had forwarded packets and a route not
yet cached in nh_rth_input, we were using a brand new route (and correct
one)

But as soon as a locally generated traffic did cache a route in
nh_rth_input, forwarded packets immediately were using this cache and
were delivered (and dropped) to local host.

Maybe my patch is not the good fix, but at least its a step in
understanding the problem.

Thanks

^ permalink raw reply

* Re: [PATCH net-next v6 1/1] ipv6: add support of equal cost multipath (ECMP)
From: Nicolas Dichtel @ 2012-10-02 16:06 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: joe, bernat, netdev, yoshfuji, davem
In-Reply-To: <1349193767-3992-2-git-send-email-nicolas.dichtel@6wind.com>

Le 02/10/2012 18:02, Nicolas Dichtel a écrit :
> Each nexthop is added like a single route in the routing table. All routes
> that have the same metric/weight and destination but not the same gateway
> are considering as ECMP routes. They are linked together, through a list called
> rt6i_siblings.
>
> ECMP routes can be added in one shot, with RTA_MULTIPATH attribute or one after
> the other (in both case, the flag NLM_F_EXCL should not be set).
>
> The patch is based on a previous work from
> Luc Saillard <luc.saillard@6wind.com>.
>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
I forget to run checkpatch.pl, some lines are over 80 columns. I will fix it in 
the v7 with other comments (if any).

^ permalink raw reply

* Re: [PATCH net-next v6 1/1] ipv6: add support of equal cost multipath (ECMP)
From: Eric Dumazet @ 2012-10-02 16:14 UTC (permalink / raw)
  To: nicolas.dichtel; +Cc: joe, bernat, netdev, yoshfuji, davem
In-Reply-To: <506B1104.7030908@6wind.com>

On Tue, 2012-10-02 at 18:06 +0200, Nicolas Dichtel wrote:

> I forget to run checkpatch.pl, some lines are over 80 columns. I will fix it in 
> the v7 with other comments (if any).
> --

Yep, please reorder :

@@ -98,6 +100,15 @@ struct rt6_info {
        struct fib6_node                *rt6i_node;
 
        struct in6_addr                 rt6i_gateway;
+#ifdef CONFIG_IPV6_MULTIPATH
+       /*
+        * siblings is a list of rt6_info that have the the same metric/weight,
+        * destination, but not the same gateway. nsiblings is just a cache
+        * to speed up lookup.
+        */
+       unsigned int                    rt6i_nsiblings;
+       struct list_head                rt6i_siblings;
+#endif
 
        atomic_t                        rt6i_ref;
 
@@ -318,4 +329,43 @@ static inline void              fib6_rules_cleanup(void)
        return ;
 }

to :

@@ -98,6 +100,15 @@ struct rt6_info {
        struct fib6_node                *rt6i_node;
 
        struct in6_addr                 rt6i_gateway;
+#ifdef CONFIG_IPV6_MULTIPATH
+       /*
+        * siblings is a list of rt6_info that have the the same metric/weight,
+        * destination, but not the same gateway. nsiblings is just a cache
+        * to speed up lookup.
+        */
+       struct list_head                rt6i_siblings;
+       unsigned int                    rt6i_nsiblings;
+#endif
 
        atomic_t                        rt6i_ref;
 
@@ -318,4 +329,43 @@ static inline void              fib6_rules_cleanup(void)
        return ;
 }

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox