Netdev List
 help / color / mirror / Atom feed
* Re: [REGRESSION next-20170426] Commit 09515ef5ddad ("of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices") causes oops in mvneta
From: Sricharan R @ 2017-04-27 13:35 UTC (permalink / raw)
  To: Ralph Sennhauser
  Cc: Rafael J. Wysocki, Joerg Roedel, Bjorn Helgaas, linux-acpi,
	linux-kernel, linux-pci, Thomas Petazzoni, netdev
In-Reply-To: <20170426181508.687b52af@gmail.com>

Hi,

On 4/26/2017 9:45 PM, Ralph Sennhauser wrote:
> Hi Sricharan R,
> 
> Commit 09515ef5ddad ("of/acpi: Configure dma operations at probe time
> for platform/amba/pci bus devices") causes a kernel panic as in the log
> below on an armada-385. Reverting the commit fixes the issue.
> 
> Regards
> Ralph

Somehow not getting a obvious clue on whats going wrong with the logs
below. From the log and looking in to dts, the drivers seems to the one for
"marvell,armada-370-neta". Issue looks the data from the dma has gone bad
and subsequently referring the wrong data has resulted in the crash.
Looks like the dma_masks is the one going wrong.
Can i get some logs from mvneta_probe, about dev->dma_mask,
dev->coherent_dma_mask and dev->dma_ops with and without the patch
to see whats the difference ?

Regards,
 Sricharan

> 
> ---
> 
> [   18.288244] [c06d8480] *pgd=0061941e(bad)
> [   18.292271] Internal error: Oops: 80d [#1] SMP ARM
> [   18.297080] Modules linked in:
> [   18.471175] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G           O    4.11.0-rc8-next-20170426 #3
> [   18.479909] Hardware name: Marvell Armada 380/385 (Device Tree)
> [   18.485850] task: c0a07000 task.stack: c0a00000
> [   18.490401] PC is at __memzero+0x40/0x80
> [   18.494336] LR is at 0x0
> [   18.496878] pc : [<c0317920>]    lr : [<00000000>]    psr: 00000113
> [   18.496878] sp : c0a01d0c  ip : 00000000  fp : c0a01d34
> [   18.508402] r10: df43f800  r9 : df43f800  r8 : 00000001
> [   18.513645] r7 : c06d7e40  r6 : 000007c0  r5 : c06d8480  r4 : de14aa80
> [   18.520196] r3 : 00000000  r2 : 00000000  r1 : ffffffe4  r0 : c06d8480
> [   18.526750] Flags: nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
> [   18.533912] Control: 10c5387d  Table: 16f0004a  DAC: 00000051
> [   18.539679] Process swapper/0 (pid: 0, stack limit = 0xc0a00210)
> [   18.545708] Stack: (0xc0a01d0c to 0xc0a02000)
> [   18.550082] 1d00:                            c04caef0 c06d7e40 00000700 0cc04000 00000001
> [   18.558292] 1d20: df691810 df43f800 c0a01d4c c0a01d38 c04caf20 c04cae7c e1b1d000 df5bd980
> [   18.566503] 1d40: c0a01dc4 c0a01d50 c043d3d8 c04caf14 df41e494 00000000 1e652500 c0601460
> [   18.574714] 1d60: dfbd8880 c0a04680 c06d7e40 00000000 dfbd8888 00000000 00000000 00000188
> [   18.582924] 1d80: 1e652500 dfbd8880 00000040 00000100 df43fc80 00000001 00000000 dfbd8888
> [   18.591134] 1da0: c043cfd4 00000040 0000012c ffff91f5 c0a02d00 c0a01de8 c0a01e24 c0a01dc8
> [   18.599345] 1dc0: c04db2d4 c043cfe0 c015d81c c06db4d4 c0a04990 c0a04990 c0a302b2 1f267000
> [   18.607555] 1de0: c096ab40 dfbd1b40 c0a01de8 c0a01de8 c0a01df0 c0a01df0 c0a01e1c 00000000
> [   18.615766] 1e00: c0a0208c c0a00000 00000100 00000003 c0a02080 40000003 c0a01e84 c0a01e28
> [   18.623977] 1e20: c0122e9c c04db0cc c0a01e54 00000101 c0a01e4c 00200102 c0a02d00 ffff91f5
> [   18.632187] 1e40: 0000000a c06025b4 c0a31740 c09632a8 c0a02080 c0a01e28 c0169788 c0968420
> [   18.640397] 1e60: 00000000 00000000 00000001 df408000 e0803100 c0a01f58 c0a01e94 c0a01e88
> [   18.648607] 1e80: c01232d0 c0122d84 c0a01ebc c0a01e98 c015d6e4 c012322c c0a169c0 c0a03fac
> [   18.656818] 1ea0: e080210c c0a01ee8 e0802100 e0803100 c0a01ee4 c0a01ec0 c01014a4 c015d688
> [   18.665029] 1ec0: c01085b0 60000013 ffffffff c0a01f1c 00000000 c0a00000 c0a01f44 c0a01ee8
> [   18.673240] 1ee0: c010c86c c0101460 00000001 00000000 00000000 c0118e40 c0a00000 c0a03cf8
> [   18.681451] 1f00: c0a03cac c09696f8 00000000 00000000 c0a01f58 c0a01f44 c0a01f48 c0a01f38
> [   18.689661] 1f20: c01085ac c01085b0 60000013 ffffffff 00000051 00000000 c0a01f54 c0a01f48
> [   18.697871] 1f40: c05e3634 c010857c c0a01f8c c0a01f58 c0153458 c05e3618 c0a03c80 c0a0f30a
> [   18.706082] 1f60: c0a30c00 000000bd c0a30c00 c0a03c80 ffffffff c0a30c00 c0833a28 dfffcb40
> [   18.714292] 1f80: c0a01f9c c0a01f90 c0153718 c01532c0 c0a01fac c0a01fa0 c05dd758 c0153704
> [   18.722503] 1fa0: c0a01ff4 c0a01fb0 c0800d68 c05dd6e8 ffffffff ffffffff 00000000 c08006f8
> [   18.730713] 1fc0: 00000000 c0833a28 00000000 c0a30e94 c0a03c9c c0833a24 c0a081e8 0000406a
> [   18.738923] 1fe0: 414fc091 00000000 00000000 c0a01ff8 0000807c c08009b4 00000000 00000000
> [   18.747132] Backtrace:
> [   18.749591] [<c04cae70>] (__build_skb) from [<c04caf20>] (build_skb+0x18/0x6c)
> [   18.756843]  r9:df43f800 r8:df691810 r7:00000001 r6:0cc04000 r5:00000700 r4:c06d7e40
> [   18.764618] [<c04caf08>] (build_skb) from [<c043d3d8>] (mvneta_poll+0x404/0xc18)
> [   18.772042]  r5:df5bd980 r4:e1b1d000
> [   18.775632] [<c043cfd4>] (mvneta_poll) from [<c04db2d4>] (net_rx_action+0x214/0x308)
> [   18.783406]  r10:c0a01de8 r9:c0a02d00 r8:ffff91f5 r7:0000012c r6:00000040 r5:c043cfd4
> [   18.791266]  r4:dfbd8888
> [   18.793810] [<c04db0c0>] (net_rx_action) from [<c0122e9c>] (__do_softirq+0x124/0x248)
> [   18.801672]  r10:40000003 r9:c0a02080 r8:00000003 r7:00000100 r6:c0a00000 r5:c0a0208c
> [   18.809531]  r4:00000000
> [   18.812074] [<c0122d78>] (__do_softirq) from [<c01232d0>] (irq_exit+0xb0/0xe4)
> [   18.819325]  r10:c0a01f58 r9:e0803100 r8:df408000 r7:00000001 r6:00000000 r5:00000000
> [   18.827184]  r4:c0968420
> [   18.829729] [<c0123220>] (irq_exit) from [<c015d6e4>] (__handle_domain_irq+0x68/0xbc)
> [   18.837591] [<c015d67c>] (__handle_domain_irq) from [<c01014a4>] (gic_handle_irq+0x50/0x94)
> [   18.845976]  r9:e0803100 r8:e0802100 r7:c0a01ee8 r6:e080210c r5:c0a03fac r4:c0a169c0
> [   18.853749] [<c0101454>] (gic_handle_irq) from [<c010c86c>] (__irq_svc+0x6c/0x90)
> [   18.861261] Exception stack(0xc0a01ee8 to 0xc0a01f30)
> [   18.866332] 1ee0:                   00000001 00000000 00000000 c0118e40 c0a00000 c0a03cf8
> [   18.874543] 1f00: c0a03cac c09696f8 00000000 00000000 c0a01f58 c0a01f44 c0a01f48 c0a01f38
> [   18.882753] 1f20: c01085ac c01085b0 60000013 ffffffff
> [   18.887823]  r9:c0a00000 r8:00000000 r7:c0a01f1c r6:ffffffff r5:60000013 r4:c01085b0
> [   18.895601] [<c0108570>] (arch_cpu_idle) from [<c05e3634>] (default_idle_call+0x28/0x34)
> [   18.903727] [<c05e360c>] (default_idle_call) from [<c0153458>] (do_idle+0x1a4/0x1d0)
> [   18.911503] [<c01532b4>] (do_idle) from [<c0153718>] (cpu_startup_entry+0x20/0x24)
> [   18.919103]  r10:dfffcb40 r9:c0833a28 r8:c0a30c00 r7:ffffffff r6:c0a03c80 r5:c0a30c00
> [   18.926962]  r4:000000bd
> [   18.929508] [<c01536f8>] (cpu_startup_entry) from [<c05dd758>] (rest_init+0x7c/0x80)
> [   18.937284] [<c05dd6dc>] (rest_init) from [<c0800d68>] (start_kernel+0x3c0/0x3cc)
> [   18.944796] [<c08009a8>] (start_kernel) from [<0000807c>] (0x807c)
> [   18.951001] Code: a8a0500c cafffff9 08bd8000 e3110020 (18a0500c)
> [   18.957119] ---[ end trace 4e5c1e66e49610b0 ]---
> [   18.961753] Kernel panic - not syncing: Fatal exception in interrupt
> [   18.968133] CPU1: stopping
> [   18.970852] CPU: 1 PID: 0 Comm: swapper/1 Tainted: G      D    O    4.11.0-rc8-next-20170426 #3
> [   18.979585] Hardware name: Marvell Armada 380/385 (Device Tree)
> [   18.985527] Backtrace:
> [   18.987986] [<c010ba4c>] (dump_backtrace) from [<c010bd20>] (show_stack+0x18/0x1c)
> [   18.995586]  r7:df467f28 r6:60000193 r5:c0a165b0 r4:00000000
> [   19.001268] [<c010bd08>] (show_stack) from [<c031883c>] (dump_stack+0x94/0xa8)
> [   19.008520] [<c03187a8>] (dump_stack) from [<c010ecec>] (handle_IPI+0x178/0x198)
> [   19.015945]  r7:df467f28 r6:00000000 r5:00000001 r4:c0a30ef0
> [   19.021627] [<c010eb74>] (handle_IPI) from [<c01014e4>] (gic_handle_irq+0x90/0x94)
> [   19.029227]  r7:df467f28 r6:e080210c r5:c0a03fac r4:c0a169c0
> [   19.034908] [<c0101454>] (gic_handle_irq) from [<c010c86c>] (__irq_svc+0x6c/0x90)
> [   19.042419] Exception stack(0xdf467f28 to 0xdf467f70)
> [   19.047490] 7f20:                   00000001 00000000 00000000 c0118e40 df466000 c0a03cf8
> [   19.055701] 7f40: c0a03cac c09696f8 00000000 00000000 df467f98 df467f84 df467f88 df467f78
> [   19.063911] 7f60: c01085ac c01085b0 60000013 ffffffff
> [   19.068982]  r9:df466000 r8:00000000 r7:df467f5c r6:ffffffff r5:60000013 r4:c01085b0
> [   19.076758] [<c0108570>] (arch_cpu_idle) from [<c05e3634>] (default_idle_call+0x28/0x34)
> [   19.084882] [<c05e360c>] (default_idle_call) from [<c0153458>] (do_idle+0x1a4/0x1d0)
> [   19.092657] [<c01532b4>] (do_idle) from [<c0153718>] (cpu_startup_entry+0x20/0x24)
> [   19.100258]  r10:00000000 r9:414fc091 r8:0000406a r7:c0a30f00 r6:10c0387d r5:00000001
> [   19.108118]  r4:00000087
> [   19.110661] [<c01536f8>] (cpu_startup_entry) from [<c010e918>] (secondary_start_kernel+0x150/0x15c)
> [   19.119743] [<c010e7c8>] (secondary_start_kernel) from [<0010162c>] (0x10162c)
> [   19.126993]  r5:00000051 r4:1f45c06a
> [   19.130583] Rebooting in 3 seconds..
> 
> ---
> 
> git bisect start
> # bad: [e0a8aa40bd2c7d973b6520293f3fd86dcbca847b] Add linux-next specific files for 20170426
> git bisect bad e0a8aa40bd2c7d973b6520293f3fd86dcbca847b
> # good: [c1ae3cfa0e89fa1a7ecc4c99031f5e9ae99d9201] Linux 4.11-rc1
> git bisect good c1ae3cfa0e89fa1a7ecc4c99031f5e9ae99d9201
> # good: [221c3c382a529418d3a2acc58f53101103f6ff13] Merge remote-tracking branch 'l2-mtd/master'
> git bisect good 221c3c382a529418d3a2acc58f53101103f6ff13
> # bad: [ffcefbbe2f8c0af5f22af921afd2756baceddd74] Merge remote-tracking branch 'spi/for-next'
> git bisect bad ffcefbbe2f8c0af5f22af921afd2756baceddd74
> # good: [c2e7f82d336a451ebb904b8bf9a5a558cf16c39b] drm: mali-dp: Check the mclk rate and allow up/down scaling
> git bisect good c2e7f82d336a451ebb904b8bf9a5a558cf16c39b
> # good: [03b600f368cfa6f94e9622dda82e60f55b5e6224] Merge remote-tracking branch 'block/for-next'
> git bisect good 03b600f368cfa6f94e9622dda82e60f55b5e6224
> # good: [8b1e05cbcdfc59496eff5870cb6b6ab964ecc733] Merge remote-tracking branch 'battery/for-next'
> git bisect good 8b1e05cbcdfc59496eff5870cb6b6ab964ecc733
> # good: [e765d496d3adb3d69bd8c53df6fd3f3b77e5b1d2] Merge remote-tracking branch 'watchdog/master'
> git bisect good e765d496d3adb3d69bd8c53df6fd3f3b77e5b1d2
> # bad: [858eed97e369df7af0993463f355aa9755227136] Merge remote-tracking branch 'audit/next'
> git bisect bad 858eed97e369df7af0993463f355aa9755227136
> # bad: [efc2195bcc35eebf06805806eb525893f3b9ab5c] Merge branches 'arm/exynos', 'arm/omap', 'arm/rockchip', 'arm/mediatek', 'arm/smmu', 'arm/core', 'x86/vt-d', 'x86/amd' and 'core' into next
> git bisect bad efc2195bcc35eebf06805806eb525893f3b9ab5c
> # bad: [316ca8804ea84a782d5ba2163711ebb22116ff5a] ACPI/IORT: Remove linker section for IORT entries probing
> git bisect bad 316ca8804ea84a782d5ba2163711ebb22116ff5a
> # good: [d7b0558230e444f29488fcee0b0b561015d16f8a] iommu/of: Prepare for deferred IOMMU configuration
> git bisect good d7b0558230e444f29488fcee0b0b561015d16f8a
> # bad: [09515ef5ddad71c7820e5e428da418b709feeb26] of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices
> git bisect bad 09515ef5ddad71c7820e5e428da418b709feeb26
> # good: [1d9029d440e40b276c0691caed1de10c42d96bef] ACPI/IORT: Add function to check SMMUs drivers presence
> git bisect good 1d9029d440e40b276c0691caed1de10c42d96bef
> # good: [efc8551a276faab19d85079da02c5fb602b0dcbe] of: device: Fix overflow of coherent_dma_mask
> git bisect good efc8551a276faab19d85079da02c5fb602b0dcbe
> # first bad commit: [09515ef5ddad71c7820e5e428da418b709feeb26] of/acpi:
> Configure dma operations at probe time for platform/amba/pci bus devices
> 

-- 
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

^ permalink raw reply

* Re: [RFC net-next 0/2] Introduce bpf_prog ID and iteration
From: Hannes Frederic Sowa @ 2017-04-27 13:36 UTC (permalink / raw)
  To: Martin KaFai Lau, netdev; +Cc: Daniel Borkmann, Alexei Starovoitov, kernel-team
In-Reply-To: <20170427062449.80290-1-kafai@fb.com>

On 27.04.2017 08:24, Martin KaFai Lau wrote:
> This patchset introduces the bpf_prog ID and a new bpf cmd to
> iterate all bpf_prog in the system.
> 
> It is still incomplete.  The idea can be extended to bpf_map.
> 
> Martin KaFai Lau (2):
>   bpf: Introduce bpf_prog ID
>   bpf: Test for bpf_prog ID and BPF_PROG_GET_NEXT_ID

Thanks Martin, I like the approach.

I think the progid is also much more suitable to be used in kallsyms
because it handles collisions correctly and let's correctly walk the
chain (for example imaging loading two identical programs but install
them at different hooks, kallsysms doesn't allow to find out which
program is installed where).

It would help a lot if you could pass the prog_id back during program
creation, otherwise it will be kind of difficult to get a hold on which
program is where. ;)

Thanks,
Hannes

^ permalink raw reply

* [PATCH v1 1/3] bnx2x: Replace custom scnprintf()
From: Andy Shevchenko @ 2017-04-27 13:36 UTC (permalink / raw)
  To: Yuval Mintz, Ariel Elior, everest-linux-l2, David S . Miller,
	netdev
  Cc: Andy Shevchenko

From: Andy Shevchenko <andy.shevchenko@gmail.com>

Use scnprintf() when printing version instead of custom open coded variants.

Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 79 +++---------------------
 1 file changed, 9 insertions(+), 70 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index b209b7f6093e..2acc4f081818 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -6163,94 +6163,33 @@ static void bnx2x_link_int_ack(struct link_params *params,
 
 static int bnx2x_format_ver(u32 num, u8 *str, u16 *len)
 {
-	u8 *str_ptr = str;
-	u32 mask = 0xf0000000;
-	u8 shift = 8*4;
-	u8 digit;
-	u8 remove_leading_zeros = 1;
+	u16 ret;
+
 	if (*len < 10) {
 		/* Need more than 10chars for this format */
-		*str_ptr = '\0';
+		*str = '\0';
 		(*len)--;
 		return -EINVAL;
 	}
-	while (shift > 0) {
 
-		shift -= 4;
-		digit = ((num & mask) >> shift);
-		if (digit == 0 && remove_leading_zeros) {
-			*str_ptr = '0';
-		} else {
-			if (digit < 0xa)
-				*str_ptr = digit + '0';
-			else
-				*str_ptr = digit - 0xa + 'a';
-
-			remove_leading_zeros = 0;
-			str_ptr++;
-			(*len)--;
-		}
-		mask = mask >> 4;
-		if (shift == 4*4) {
-			if (remove_leading_zeros) {
-				str_ptr++;
-				(*len)--;
-			}
-			*str_ptr = '.';
-			str_ptr++;
-			(*len)--;
-			remove_leading_zeros = 1;
-		}
-	}
-	if (remove_leading_zeros)
-		(*len)--;
+	ret = scnprintf(str, *len, "%hx.%hx", num >> 16, num);
+	*len -= ret;
 	return 0;
 }
 
 static int bnx2x_3_seq_format_ver(u32 num, u8 *str, u16 *len)
 {
-	u8 *str_ptr = str;
-	u32 mask = 0x00f00000;
-	u8 shift = 8*3;
-	u8 digit;
-	u8 remove_leading_zeros = 1;
+	u16 ret;
 
 	if (*len < 10) {
 		/* Need more than 10chars for this format */
-		*str_ptr = '\0';
+		*str = '\0';
 		(*len)--;
 		return -EINVAL;
 	}
 
-	while (shift > 0) {
-		shift -= 4;
-		digit = ((num & mask) >> shift);
-		if (digit == 0 && remove_leading_zeros) {
-			*str_ptr = '0';
-		} else {
-			if (digit < 0xa)
-				*str_ptr = digit + '0';
-			else
-				*str_ptr = digit - 0xa + 'a';
-
-			remove_leading_zeros = 0;
-			str_ptr++;
-			(*len)--;
-		}
-		mask = mask >> 4;
-		if ((shift == 4*4) || (shift == 4*2)) {
-			if (remove_leading_zeros) {
-				str_ptr++;
-				(*len)--;
-			}
-			*str_ptr = '.';
-			str_ptr++;
-			(*len)--;
-			remove_leading_zeros = 1;
-		}
-	}
-	if (remove_leading_zeros)
-		(*len)--;
+	ret = scnprintf(str, *len, "%hhx.%hhx.%hhx", num >> 16, num >> 8, num);
+	*len -= ret;
 	return 0;
 }
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH v1 3/3] bnx2x: Get rid of useless temporary variable
From: Andy Shevchenko @ 2017-04-27 13:37 UTC (permalink / raw)
  To: Yuval Mintz, Ariel Elior, everest-linux-l2, David S . Miller,
	netdev
  Cc: Andy Shevchenko
In-Reply-To: <20170427133701.72701-1-andriy.shevchenko@linux.intel.com>

From: Andy Shevchenko <andy.shevchenko@gmail.com>

Replace pattern

 int status;
 ...
 status = func(...);
 return status;

by

 return func(...);

No functional change intented.

Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 6d11a958200f..7dd83d0ef0a0 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -10618,22 +10618,19 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
 
 static int bnx2x_8485x_format_ver(u32 raw_ver, u8 *str, u16 *len)
 {
-	int status = 0;
 	u32 num;
 
 	num = ((raw_ver & 0xF80) >> 7) << 16 | ((raw_ver & 0x7F) << 8) |
 	      ((raw_ver & 0xF000) >> 12);
-	status = bnx2x_3_seq_format_ver(num, str, len);
-	return status;
+	return bnx2x_3_seq_format_ver(num, str, len);
 }
 
 static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
 {
-	int status = 0;
 	u32 spirom_ver;
+
 	spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
-	status = bnx2x_format_ver(spirom_ver, str, len);
-	return status;
+	return bnx2x_format_ver(spirom_ver, str, len);
 }
 
 static void bnx2x_8481_hw_reset(struct bnx2x_phy *phy,
@@ -12484,13 +12481,12 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
 static int bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
 			      u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
 {
-	int status = 0;
 	phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
 	if (phy_index == INT_PHY)
 		return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
-	status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, shmem2_base,
+
+	return bnx2x_populate_ext_phy(bp, phy_index, shmem_base, shmem2_base,
 					port, phy);
-	return status;
 }
 
 static void bnx2x_phy_def_cfg(struct link_params *params,
-- 
2.11.0

^ permalink raw reply related

* [PATCH v1 2/3] bnx2x: Reuse bnx2x_null_format_ver()
From: Andy Shevchenko @ 2017-04-27 13:37 UTC (permalink / raw)
  To: Yuval Mintz, Ariel Elior, everest-linux-l2, David S . Miller,
	netdev
  Cc: Andy Shevchenko
In-Reply-To: <20170427133701.72701-1-andriy.shevchenko@linux.intel.com>

From: Andy Shevchenko <andy.shevchenko@gmail.com>

Reuse bnx2x_null_format_ver() in functions where it's appropriated
instead of open coded variant.

Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 2acc4f081818..6d11a958200f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -6161,14 +6161,20 @@ static void bnx2x_link_int_ack(struct link_params *params,
 	}
 }
 
+static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+{
+	str[0] = '\0';
+	(*len)--;
+	return 0;
+}
+
 static int bnx2x_format_ver(u32 num, u8 *str, u16 *len)
 {
 	u16 ret;
 
 	if (*len < 10) {
 		/* Need more than 10chars for this format */
-		*str = '\0';
-		(*len)--;
+		bnx2x_null_format_ver(num, str, len);
 		return -EINVAL;
 	}
 
@@ -6183,8 +6189,7 @@ static int bnx2x_3_seq_format_ver(u32 num, u8 *str, u16 *len)
 
 	if (*len < 10) {
 		/* Need more than 10chars for this format */
-		*str = '\0';
-		(*len)--;
+		bnx2x_null_format_ver(num, str, len);
 		return -EINVAL;
 	}
 
@@ -6193,13 +6198,6 @@ static int bnx2x_3_seq_format_ver(u32 num, u8 *str, u16 *len)
 	return 0;
 }
 
-static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
-{
-	str[0] = '\0';
-	(*len)--;
-	return 0;
-}
-
 int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 *version,
 				 u16 len)
 {
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH net-next] net: bridge: Fix improper taking over HW learned FDB
From: Nikolay Aleksandrov @ 2017-04-27 13:40 UTC (permalink / raw)
  To: Arkadi Sharshevsky, netdev; +Cc: davem, stephen, bridge, Ido Schimmel
In-Reply-To: <1493280485-37845-1-git-send-email-arkadis@mellanox.com>

On 27/04/17 11:08, Arkadi Sharshevsky wrote:
> Commit 7e26bf45e4cb ("net: bridge: allow SW learn to take over HW fdb
> entries") added the ability to "take over an entry which was previously
> learned via HW when it shows up from a SW port".
> 
> However, if an entry was learned via HW and then a control packet
> (e.g., ARP request) was trapped to the CPU, the bridge driver will
> update the entry and remove the externally learned flag, although the
> entry is still present in HW. Instead, only clear the externally learned
> flag in case of roaming.
> 
> Fixes: 7e26bf45e4cb ("net: bridge: allow SW learn to take over HW fdb entries")
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> Signed-off-by: Arkadi Sharashevsky <arkadis@mellanox.com>
> Cc: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
> ---
>  net/bridge/br_fdb.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
> index 5a40a87..ab0c7cc 100644
> --- a/net/bridge/br_fdb.c
> +++ b/net/bridge/br_fdb.c
> @@ -589,14 +589,14 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
>  			if (unlikely(source != fdb->dst)) {
>  				fdb->dst = source;
>  				fdb_modified = true;
> +				/* Take over HW learned entry */
> +				if (unlikely(fdb->added_by_external_learn))
> +					fdb->added_by_external_learn = 0;
>  			}
>  			if (now != fdb->updated)
>  				fdb->updated = now;
>  			if (unlikely(added_by_user))
>  				fdb->added_by_user = 1;
> -			/* Take over HW learned entry */
> -			if (unlikely(fdb->added_by_external_learn))
> -				fdb->added_by_external_learn = 0;
>  			if (unlikely(fdb_modified))
>  				fdb_notify(br, fdb, RTM_NEWNEIGH);
>  		}
> 

Wait, this won't apply to latest net-next due to my patch that added
fdb_modified when changing the ext learned flag. I think you'll have to
respin on top of latest net-next.

^ permalink raw reply

* [PATCH rdma-next] IB/mlx5: Enable IPoIB acceleration
From: Leon Romanovsky @ 2017-04-27 14:01 UTC (permalink / raw)
  To: Doug Ledford
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA, Erez Shitrit, Saeed Mahameed,
	Arnd Bergmann, David S . Miller, netdev-u79uwXL29TY76Z2rM5mHXA

From: Erez Shitrit <erezsh-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Enable mlx5 IPoIB acceleration by declaring
mlx5_ib_{alloc,free}_rdma_netdev and assigning the mlx5
IPoIB rdma_netdev callbacks.

In addition, this patch brings in sync mlx5's IPoIB parts for net and IB
trees. As a precaution, we disabled IPoIB acceleration by default (in
the mlx5_core Kconfig file).

Signed-off-by: Saeed Mahameed <saeedm-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Signed-off-by: Erez Shitrit <erezsh-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Signed-off-by: Leon Romanovsky <leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Hi Doug,

This is connection patch between IPoIB mlx5_core and mlx5_ib parts.

The patch itself is based on merge between your's k.o/for-4.12-rdma-netdevice
commit cc47dd684ee04f9f49f081002a74ef1ba9d14cc8 and David's master
commit b1513c35317c106a1588f3ab32f6888f0e2afd71 , because there was patch
from Stephen exactly in that area:
http://marc.info/?l=linux-netdev&m=149288674816288&w=2

Are you OK with this base?
Or do you prefer patch which will be based on your's branch, which will fail
in merge tests (linux-next) between yours and Dave's tree?

Thanks

Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Cc: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
Cc: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
 drivers/infiniband/hw/mlx5/main.c               | 22 +++++++++++++
 drivers/net/ethernet/mellanox/mlx5/core/Kconfig |  2 +-
 drivers/net/ethernet/mellanox/mlx5/core/ipoib.c | 44 +++++++++++++++----------
 drivers/net/ethernet/mellanox/mlx5/core/ipoib.h |  2 ++
 include/linux/mlx5/driver.h                     | 19 +++++++++++
 5 files changed, 70 insertions(+), 19 deletions(-)

diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 9f3ba320ce70..d45772da0963 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -3530,6 +3530,26 @@ static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
 	return num_counters;
 }

+static struct net_device*
+mlx5_ib_alloc_rdma_netdev(struct ib_device *hca,
+			  u8 port_num,
+			  enum rdma_netdev_t type,
+			  const char *name,
+			  unsigned char name_assign_type,
+			  void (*setup)(struct net_device *))
+{
+	if (type != RDMA_NETDEV_IPOIB)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	return mlx5_rdma_netdev_alloc(to_mdev(hca)->mdev, hca,
+				      name, setup);
+}
+
+static void mlx5_ib_free_rdma_netdev(struct net_device *netdev)
+{
+	return mlx5_rdma_netdev_free(netdev);
+}
+
 static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
 {
 	struct mlx5_ib_dev *dev;
@@ -3660,6 +3680,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
 	dev->ib_dev.check_mr_status	= mlx5_ib_check_mr_status;
 	dev->ib_dev.get_port_immutable  = mlx5_port_immutable;
 	dev->ib_dev.get_dev_fw_str      = get_dev_fw_str;
+	dev->ib_dev.alloc_rdma_netdev	= mlx5_ib_alloc_rdma_netdev;
+	dev->ib_dev.free_rdma_netdev	= mlx5_ib_free_rdma_netdev;
 	if (mlx5_core_is_pf(mdev)) {
 		dev->ib_dev.get_vf_config	= mlx5_ib_get_vf_config;
 		dev->ib_dev.set_vf_link_state	= mlx5_ib_set_vf_link_state;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
index a84b652f9b54..fc52d742b7f7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
@@ -35,6 +35,6 @@ config MLX5_CORE_EN_DCB
 config MLX5_CORE_IPOIB
 	bool "Mellanox Technologies ConnectX-4 IPoIB offloads support"
 	depends on MLX5_CORE_EN
-	default y
+	default n
 	---help---
 	  MLX5 IPoIB offloads & acceleration support.
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c
index 3c84e36af018..019c230da498 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c
@@ -30,6 +30,7 @@
  * SOFTWARE.
  */

+#include <rdma/ib_verbs.h>
 #include <linux/mlx5/fs.h>
 #include "en.h"
 #include "ipoib.h"
@@ -359,10 +360,10 @@ static int mlx5i_close(struct net_device *netdev)
 	return 0;
 }

-#ifdef notusedyet
 /* IPoIB RDMA netdev callbacks */
 static int mlx5i_attach_mcast(struct net_device *netdev, struct ib_device *hca,
-			      union ib_gid *gid, u16 lid, int set_qkey)
+			      union ib_gid *gid, u16 lid, int set_qkey,
+			      u32 qkey)
 {
 	struct mlx5e_priv    *epriv = mlx5i_epriv(netdev);
 	struct mlx5_core_dev *mdev  = epriv->mdev;
@@ -375,6 +376,12 @@ static int mlx5i_attach_mcast(struct net_device *netdev, struct ib_device *hca,
 		mlx5_core_warn(mdev, "failed attaching QPN 0x%x, MGID %pI6\n",
 			       ipriv->qp.qpn, gid->raw);

+	if (set_qkey) {
+		mlx5_core_dbg(mdev, "%s setting qkey 0x%x\n",
+			      netdev->name, qkey);
+		ipriv->qkey = qkey;
+	}
+
 	return err;
 }

@@ -397,15 +404,15 @@ static int mlx5i_detach_mcast(struct net_device *netdev, struct ib_device *hca,
 }

 static int mlx5i_xmit(struct net_device *dev, struct sk_buff *skb,
-	       struct ib_ah *address, u32 dqpn, u32 dqkey)
+		      struct ib_ah *address, u32 dqpn)
 {
 	struct mlx5e_priv *epriv = mlx5i_epriv(dev);
 	struct mlx5e_txqsq *sq   = epriv->txq2sq[skb_get_queue_mapping(skb)];
 	struct mlx5_ib_ah *mah   = to_mah(address);
+	struct mlx5i_priv *ipriv = epriv->ppriv;

-	return mlx5i_sq_xmit(sq, skb, &mah->av, dqpn, dqkey);
+	return mlx5i_sq_xmit(sq, skb, &mah->av, dqpn, ipriv->qkey);
 }
-#endif

 static int mlx5i_check_required_hca_cap(struct mlx5_core_dev *mdev)
 {
@@ -414,22 +421,23 @@ static int mlx5i_check_required_hca_cap(struct mlx5_core_dev *mdev)

 	if (!MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) {
 		mlx5_core_warn(mdev, "IPoIB enhanced offloads are not supported\n");
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 	}

 	return 0;
 }

-static struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
-						 struct ib_device *ibdev,
-						 const char *name,
-						 void (*setup)(struct net_device *))
+struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
+					  struct ib_device *ibdev,
+					  const char *name,
+					  void (*setup)(struct net_device *))
 {
 	const struct mlx5e_profile *profile = &mlx5i_nic_profile;
 	int nch = profile->max_nch(mdev);
 	struct net_device *netdev;
 	struct mlx5i_priv *ipriv;
 	struct mlx5e_priv *epriv;
+	struct rdma_netdev *rn;
 	int err;

 	if (mlx5i_check_required_hca_cap(mdev)) {
@@ -464,13 +472,13 @@ static struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
 	mlx5e_attach_netdev(epriv);
 	netif_carrier_off(netdev);

-	/* TODO: set rdma_netdev func pointers
-	 * rn = &ipriv->rn;
-	 * rn->hca  = ibdev;
-	 * rn->send = mlx5i_xmit;
-	 * rn->attach_mcast = mlx5i_attach_mcast;
-	 * rn->detach_mcast = mlx5i_detach_mcast;
-	 */
+	/* set rdma_netdev func pointers */
+	rn = &ipriv->rn;
+	rn->hca  = ibdev;
+	rn->send = mlx5i_xmit;
+	rn->attach_mcast = mlx5i_attach_mcast;
+	rn->detach_mcast = mlx5i_detach_mcast;
+
 	return netdev;

 err_free_netdev:
@@ -482,7 +490,7 @@ static struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
 }
 EXPORT_SYMBOL(mlx5_rdma_netdev_alloc);

-static void mlx5_rdma_netdev_free(struct net_device *netdev)
+void mlx5_rdma_netdev_free(struct net_device *netdev)
 {
 	struct mlx5e_priv          *priv    = mlx5i_epriv(netdev);
 	const struct mlx5e_profile *profile = priv->profile;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.h b/drivers/net/ethernet/mellanox/mlx5/core/ipoib.h
index bae0a5cbc8ad..213191a78464 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib.h
@@ -40,7 +40,9 @@

 /* ipoib rdma netdev's private data structure */
 struct mlx5i_priv {
+	struct rdma_netdev rn; /* keep this first */
 	struct mlx5_core_qp qp;
+	u32    qkey;
 	char  *mlx5e_priv[0];
 };

diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index f50864626230..a3bd07608cc6 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -1101,6 +1101,25 @@ struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev);
 struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev);
 void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up);

+#ifndef CONFIG_MLX5_CORE_IPOIB
+static inline
+struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
+					  struct ib_device *ibdev,
+					  const char *name,
+					  void (*setup)(struct net_device *))
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void mlx5_rdma_netdev_free(struct net_device *netdev) {}
+#else
+struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
+					  struct ib_device *ibdev,
+					  const char *name,
+					  void (*setup)(struct net_device *));
+void mlx5_rdma_netdev_free(struct net_device *netdev);
+#endif /* CONFIG_MLX5_CORE_IPOIB */
+
 struct mlx5_profile {
 	u64	mask;
 	u8	log_max_qp;
--
2.12.2

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" 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-next] tcp: tcp_rack_reo_timeout() must update tp->tcp_mstamp
From: Neal Cardwell @ 2017-04-27 14:10 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev, Soheil Hassas Yeganeh, Yuchung Cheng
In-Reply-To: <1493266255.6453.103.camel@edumazet-glaptop3.roam.corp.google.com>

On Thu, Apr 27, 2017 at 12:10 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> I wrongly assumed tp->tcp_mstamp was up to date at the time
> tcp_rack_reo_timeout() was called.
>
> It is not true, since we only update tcp->tcp_mstamp when receiving
> a packet (as initially done in commit 69e996c58a35 ("tcp: add
> tp->tcp_mstamp field")
>
> tcp_rack_reo_timeout() being called by a timer and not an incoming
> packet, we need to refresh tp->tcp_mstamp
>
> Fixes: 7c1c7308592f ("tcp: do not pass timestamp to tcp_rack_detect_loss()")
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Soheil Hassas Yeganeh <soheil@google.com>
> Cc: Neal Cardwell <ncardwell@google.com>
> Cc: Yuchung Cheng <ycheng@google.com>

Acked-by: Neal Cardwell <ncardwell@google.com>

Thanks!

neal

^ permalink raw reply

* [PATCH net] net: hns: fix ethtool_get_strings overflow in hns driver
From: Timmy Li @ 2017-04-27 14:18 UTC (permalink / raw)
  To: davem, huangdaode, lipeng321, yisen.zhuang, salil.mehta,
	yankejian
  Cc: mbrugger, netdev, linux-kernel, linuxarm, Timmy Li

hns_get_sset_count() returns HNS_NET_STATS_CNT and the data space allocated
is not enough for ethtool_get_strings(), which will cause random memory
corruption.

When SLAB and DEBUG_SLAB are both enabled, memory corruptions like the
the following can be observed without this patch:
[   43.115200] Slab corruption (Not tainted): Acpi-ParseExt start=ffff801fb0b69030, len=80
[   43.115206] Redzone: 0x9f911029d006462/0x5f78745f31657070.
[   43.115208] Last user: [<5f7272655f746b70>](0x5f7272655f746b70)
[   43.115214] 010: 70 70 65 31 5f 74 78 5f 70 6b 74 00 6b 6b 6b 6b  ppe1_tx_pkt.kkkk
[   43.115217] 030: 70 70 65 31 5f 74 78 5f 70 6b 74 5f 6f 6b 00 6b  ppe1_tx_pkt_ok.k
[   43.115218] Next obj: start=ffff801fb0b69098, len=80
[   43.115220] Redzone: 0x706d655f6f666966/0x9f911029d74e35b.
[   43.115229] Last user: [<ffff0000084b11b0>](acpi_os_release_object+0x28/0x38)
[   43.115231] 000: 74 79 00 6b 6b 6b 6b 6b 70 70 65 31 5f 74 78 5f  ty.kkkkkppe1_tx_
[   43.115232] 010: 70 6b 74 5f 65 72 72 5f 63 73 75 6d 5f 66 61 69  pkt_err_csum_fai

Signed-off-by: Timmy Li <lixiaoping3@huawei.com>
---
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c  | 2 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c   | 2 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c   | 2 +-
 drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
index 3382441..7faeb5b 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
@@ -672,7 +672,7 @@ static void hns_gmac_get_strings(u32 stringset, u8 *data)
 
 static int hns_gmac_get_sset_count(int stringset)
 {
-	if (stringset == ETH_SS_STATS)
+	if ((stringset == ETH_SS_STATS) || (stringset == ETH_SS_PRIV_FLAGS))
 		return ARRAY_SIZE(g_gmac_stats_string);
 
 	return 0;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
index 6ea8722..e3e8772 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
@@ -422,7 +422,7 @@ void hns_ppe_update_stats(struct hns_ppe_cb *ppe_cb)
 
 int hns_ppe_get_sset_count(int stringset)
 {
-	if (stringset == ETH_SS_STATS)
+	if ((stringset == ETH_SS_STATS) || (stringset == ETH_SS_PRIV_FLAGS))
 		return ETH_PPE_STATIC_NUM;
 	return 0;
 }
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
index f0ed80d6..01a0a03 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
@@ -799,7 +799,7 @@ void hns_rcb_get_stats(struct hnae_queue *queue, u64 *data)
  */
 int hns_rcb_get_ring_sset_count(int stringset)
 {
-	if (stringset == ETH_SS_STATS)
+	if ((stringset == ETH_SS_STATS) || (stringset == ETH_SS_PRIV_FLAGS))
 		return HNS_RING_STATIC_REG_NUM;
 
 	return 0;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
index aae830a..f10b25c 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
@@ -793,7 +793,7 @@ static void hns_xgmac_get_strings(u32 stringset, u8 *data)
  */
 static int hns_xgmac_get_sset_count(int stringset)
 {
-	if (stringset == ETH_SS_STATS)
+	if ((stringset == ETH_SS_STATS) || (stringset == ETH_SS_PRIV_FLAGS))
 		return ARRAY_SIZE(g_xgmac_stats_string);
 
 	return 0;
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next] can: fix build error without CONFIG_PROC_FS
From: Arnd Bergmann @ 2017-04-27 14:21 UTC (permalink / raw)
  To: Oliver Hartkopp, Marc Kleine-Budde, David S. Miller
  Cc: Arnd Bergmann, Thomas Gleixner, Cong Wang, Mario Kicherer,
	Eric Dumazet, linux-can, netdev, linux-kernel

The procfs dir entry was added inside of an #ifdef, causing a build error
when we try to access it without CONFIG_PROC_FS set:

net/can/bcm.c:1541:14: error: 'struct netns_can' has no member named 'bcmproc_dir'
net/can/bcm.c: In function 'bcm_connect':
net/can/bcm.c:1601:14: error: 'struct netns_can' has no member named 'bcmproc_dir'
net/can/bcm.c: In function 'canbcm_pernet_init':
net/can/bcm.c:1696:11: error: 'struct netns_can' has no member named 'bcmproc_dir'
net/can/bcm.c: In function 'canbcm_pernet_exit':
net/can/bcm.c:1707:15: error: 'struct netns_can' has no member named 'bcmproc_dir'

This adds the same #ifdef around all users of the pointer. Alternatively
we could move the pointer outside of the #ifdef.

Fixes: 384317ef4187 ("can: network namespace support for CAN_BCM protocol")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 net/can/bcm.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/net/can/bcm.c b/net/can/bcm.c
index 0e855917b7e1..e6d9df27400b 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -1538,8 +1538,10 @@ static int bcm_release(struct socket *sock)
 	}
 
 	/* remove procfs entry */
+#ifdef CONFIG_PROC_FS
 	if (net->can.bcmproc_dir && bo->bcm_proc_read)
 		remove_proc_entry(bo->procname, net->can.bcmproc_dir);
+#endif
 
 	/* remove device reference */
 	if (bo->bound) {
@@ -1597,7 +1599,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
 		/* no interface reference for ifindex = 0 ('any' CAN device) */
 		bo->ifindex = 0;
 	}
-
+#ifdef CONFIG_PROC_FS
 	if (net->can.bcmproc_dir) {
 		/* unique socket address as filename */
 		sprintf(bo->procname, "%lu", sock_i_ino(sk));
@@ -1609,6 +1611,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
 			goto fail;
 		}
 	}
+#endif
 
 	bo->bound = 1;
 
@@ -1691,22 +1694,23 @@ static const struct can_proto bcm_can_proto = {
 
 static int canbcm_pernet_init(struct net *net)
 {
+#ifdef CONFIG_PROC_FS
 	/* create /proc/net/can-bcm directory */
-	if (IS_ENABLED(CONFIG_PROC_FS)) {
-		net->can.bcmproc_dir =
-			proc_net_mkdir(net, "can-bcm", net->proc_net);
-	}
+	net->can.bcmproc_dir = proc_net_mkdir(net, "can-bcm", net->proc_net);
+#endif
 
 	return 0;
 }
 
 static void canbcm_pernet_exit(struct net *net)
 {
+#ifdef CONFIG_PROC_FS
 	/* remove /proc/net/can-bcm directory */
 	if (IS_ENABLED(CONFIG_PROC_FS)) {
 		if (net->can.bcmproc_dir)
 			remove_proc_entry("can-bcm", net->proc_net);
 	}
+#endif
 }
 
 static struct pernet_operations canbcm_pernet_ops __read_mostly = {
-- 
2.9.0


^ permalink raw reply related

* Re: [PATCH net-next] can: fix build error without CONFIG_PROC_FS
From: Marc Kleine-Budde @ 2017-04-27 14:29 UTC (permalink / raw)
  To: Arnd Bergmann, Oliver Hartkopp, David S. Miller
  Cc: Thomas Gleixner, Cong Wang, Mario Kicherer, Eric Dumazet,
	linux-can, netdev, linux-kernel
In-Reply-To: <20170427142146.3107957-1-arnd@arndb.de>


[-- Attachment #1.1: Type: text/plain, Size: 1409 bytes --]

Hello Arnd,

On 04/27/2017 04:21 PM, Arnd Bergmann wrote:
> The procfs dir entry was added inside of an #ifdef, causing a build error
> when we try to access it without CONFIG_PROC_FS set:
> 
> net/can/bcm.c:1541:14: error: 'struct netns_can' has no member named 'bcmproc_dir'
> net/can/bcm.c: In function 'bcm_connect':
> net/can/bcm.c:1601:14: error: 'struct netns_can' has no member named 'bcmproc_dir'
> net/can/bcm.c: In function 'canbcm_pernet_init':
> net/can/bcm.c:1696:11: error: 'struct netns_can' has no member named 'bcmproc_dir'
> net/can/bcm.c: In function 'canbcm_pernet_exit':
> net/can/bcm.c:1707:15: error: 'struct netns_can' has no member named 'bcmproc_dir'
> 
> This adds the same #ifdef around all users of the pointer. Alternatively
> we could move the pointer outside of the #ifdef.
> 
> Fixes: 384317ef4187 ("can: network namespace support for CAN_BCM protocol")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

A fix for this problem is part of the pull request I send to David
earlier today:

    https://www.mail-archive.com/netdev@vger.kernel.org/msg165764.html

regards,
Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [REGRESSION next-20170426] Commit 09515ef5ddad ("of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices") causes oops in mvneta
From: Ralph Sennhauser @ 2017-04-27 14:40 UTC (permalink / raw)
  To: Sricharan R
  Cc: Rafael J. Wysocki, Joerg Roedel, Bjorn Helgaas, linux-acpi,
	linux-kernel, linux-pci, Thomas Petazzoni, netdev
In-Reply-To: <2fb57b9b-3944-d9cc-1fac-8dcccaa0c37a@codeaurora.org>

On Thu, 27 Apr 2017 19:05:09 +0530
Sricharan R <sricharan@codeaurora.org> wrote:

> Hi,
> 
> On 4/26/2017 9:45 PM, Ralph Sennhauser wrote:
> > Hi Sricharan R,
> > 
> > Commit 09515ef5ddad ("of/acpi: Configure dma operations at probe
> > time for platform/amba/pci bus devices") causes a kernel panic as
> > in the log below on an armada-385. Reverting the commit fixes the
> > issue.
> > 
> > Regards
> > Ralph  
> 
> Somehow not getting a obvious clue on whats going wrong with the logs
> below. From the log and looking in to dts, the drivers seems to the
> one for "marvell,armada-370-neta".

Correct.

> Issue looks the data from the dma
> has gone bad and subsequently referring the wrong data has resulted
> in the crash. Looks like the dma_masks is the one going wrong.
> Can i get some logs from mvneta_probe, about dev->dma_mask,
> dev->coherent_dma_mask and dev->dma_ops with and without the patch
> to see whats the difference ?

Not sure I understood what exactly you are after. Might be faster to
just send me a patch with all debug print statements you like to see.

Regards
Ralph

^ permalink raw reply

* Re: [PATCH net-next 6/6] bpf: show bpf programs
From: Alexei Starovoitov @ 2017-04-27 14:45 UTC (permalink / raw)
  To: Hannes Frederic Sowa
  Cc: netdev@vger.kernel.org, Alexei Starovoitov, daniel, Jiri Benc,
	Aaron Conole, Martin KaFai Lau

On Thu, Apr 27, 2017 at 6:28 AM, Hannes Frederic Sowa
<hannes@stressinduktion.org> wrote:
>
>> I don't want this to become debugfs for bpf.
>
> Right now it just prints a list of ebpf programs. You reject of where
> things are going or do you already reject this particular patch?

both.
procfs/debugfs always starts as 'i just print a little, because it's easier'
and the next thing you know it's full of knobs and user tooling
to parse this text.

^ permalink raw reply

* Re: [PATCH net-next 4/6] bpf: track if the bpf program was loaded with SYS_ADMIN capabilities
From: Alexei Starovoitov @ 2017-04-27 14:49 UTC (permalink / raw)
  To: Hannes Frederic Sowa
  Cc: netdev@vger.kernel.org, Alexei Starovoitov, Jiri Benc,
	Aaron Conole, Daniel Borkmann

On Thu, Apr 27, 2017 at 6:17 AM, Hannes Frederic Sowa
<hannes@stressinduktion.org> wrote:
>
> cap_sys_admin influences the verifier a lot in terms which programs are
> accepted and which are not. So during investigations it might be even
> interesting if the bpf program required those special flags or if the
> same program could be loaded just as underprivileged.

there are bunch of other things that influence verifier.
should we add all of them ?
there is prog->aux->user which is more than enough for
debugging.

^ permalink raw reply

* [PATCH net-next 0/9] support unique MAC addresses for slave devices
From: Marco Chiappero @ 2017-04-27 14:51 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Jeff Kirsher, Alexander Duyck, Sainath Grandhi,
	Mahesh Bandewar, Marco Chiappero

Currently every slave device gets assigned the same MAC address, by
having it copied from the master interface. Since some code paths
depend on this identity, changing the MAC address on slave interfaces
is not supported. However identical MAC addresses can pose problems to
management and orchestration software that correctly expect network
interfaces on the same segment to have unique addresses.

Patches 1-8 include style fixes and refactoring (patch 9 depends upon)
that improve the overal quality and make the intruduction of the
feature straightforward.

Patch 9 enables slave devices to own unique MAC addresses and change
such addresses live, fixing lack of support and a related bug, as
MAC address changes on master were not propagated to slave devices.
In order to preserve the main peculiarity of this driver, that is
exposing only a single MAC address for outbound traffic, frames
egressing from master are now effectively masquerated when working in
L2 mode.

Marco Chiappero (9):
  ipvlan: fix coding style for the ipvlan tree
  ipvlan: refactor ipvlan_process_multicast for readability
  ipvlan: replace ipvlan_rcv_frame
  ipvlan: rework the IP lookup function
  ipvlan: improve and uniform naming
  ipvlan: reposition three functions
  ipvlan: relocate ipvlan_skb_crossing_ns calls
  ipvlan: improve compiler hints
  ipvlan: introduce individual MAC addresses

 drivers/net/ipvlan/ipvlan.h      |   2 +-
 drivers/net/ipvlan/ipvlan_core.c | 592 ++++++++++++++++++++-------------------
 drivers/net/ipvlan/ipvlan_main.c |  49 ++--
 drivers/net/ipvlan/ipvtap.c      |   1 +
 4 files changed, 333 insertions(+), 311 deletions(-)

-- 
2.9.3

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.

^ permalink raw reply

* [PATCH net-next 1/9] ipvlan: fix coding style for the ipvlan tree
From: Marco Chiappero @ 2017-04-27 14:51 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Jeff Kirsher, Alexander Duyck, Sainath Grandhi,
	Mahesh Bandewar, Marco Chiappero
In-Reply-To: <20170427145142.15830-1-marco.chiappero@intel.com>

Update the ipvlan and ipvtap drivers to comply to the Linux coding
style, fixing errors and warnings reported by checkpatch.

Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
---
 drivers/net/ipvlan/ipvlan_core.c | 29 ++++++++++++++++-------------
 drivers/net/ipvlan/ipvlan_main.c | 31 ++++++++++++++-----------------
 drivers/net/ipvlan/ipvtap.c      |  1 +
 3 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 1f3295e..1266f01 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -17,7 +17,7 @@ void ipvlan_init_secret(void)
 }
 
 void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
-			    unsigned int len, bool success, bool mcast)
+		     unsigned int len, bool success, bool mcast)
 {
 	if (likely(success)) {
 		struct ipvl_pcpu_stats *pcptr;
@@ -95,9 +95,9 @@ struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
 
 	list_for_each_entry(addr, &ipvlan->addrs, anode) {
 		if ((is_v6 && addr->atype == IPVL_IPV6 &&
-		    ipv6_addr_equal(&addr->ip6addr, iaddr)) ||
+		     ipv6_addr_equal(&addr->ip6addr, iaddr)) ||
 		    (!is_v6 && addr->atype == IPVL_IPV4 &&
-		    addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr))
+		     addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr))
 			return addr;
 	}
 	return NULL;
@@ -179,7 +179,7 @@ static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type)
 
 unsigned int ipvlan_mac_hash(const unsigned char *addr)
 {
-	u32 hash = jhash_1word(__get_unaligned_cpu32(addr+2),
+	u32 hash = jhash_1word(__get_unaligned_cpu32(addr + 2),
 			       ipvlan_jhash_secret);
 
 	return hash & IPVLAN_MAC_FILTER_MASK;
@@ -234,11 +234,13 @@ void ipvlan_process_multicast(struct work_struct *work)
 				nskb->pkt_type = pkt_type;
 				nskb->dev = ipvlan->dev;
 				if (tx_pkt)
-					ret = dev_forward_skb(ipvlan->dev, nskb);
+					ret = dev_forward_skb(ipvlan->dev,
+							      nskb);
 				else
 					ret = netif_rx(nskb);
 			}
-			ipvlan_count_rx(ipvlan, len, ret == NET_RX_SUCCESS, true);
+			ipvlan_count_rx(ipvlan, len, ret == NET_RX_SUCCESS,
+					true);
 			local_bh_enable();
 		}
 		rcu_read_unlock();
@@ -461,11 +463,11 @@ static int ipvlan_process_outbound(struct sk_buff *skb)
 		skb_reset_network_header(skb);
 	}
 
-	if (skb->protocol == htons(ETH_P_IPV6))
+	if (skb->protocol == htons(ETH_P_IPV6)) {
 		ret = ipvlan_process_v6_outbound(skb);
-	else if (skb->protocol == htons(ETH_P_IP))
+	} else if (skb->protocol == htons(ETH_P_IP)) {
 		ret = ipvlan_process_v4_outbound(skb);
-	else {
+	} else {
 		pr_warn_ratelimited("Dropped outbound packet type=%x\n",
 				    ntohs(skb->protocol));
 		kfree_skb(skb);
@@ -534,7 +536,8 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
 	if (ether_addr_equal(eth->h_dest, eth->h_source)) {
 		lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
 		if (lyr3h) {
-			addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
+			addr = ipvlan_addr_lookup(ipvlan->port, lyr3h,
+						  addr_type, true);
 			if (addr)
 				return ipvlan_rcv_frame(addr, &skb, true);
 		}
@@ -570,7 +573,7 @@ int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (unlikely(!pskb_may_pull(skb, sizeof(struct ethhdr))))
 		goto out;
 
-	switch(port->mode) {
+	switch (port->mode) {
 	case IPVLAN_MODE_L2:
 		return ipvlan_xmit_mode_l2(skb, dev);
 	case IPVLAN_MODE_L3:
@@ -580,7 +583,7 @@ int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	/* Should not reach here */
 	WARN_ONCE(true, "ipvlan_queue_xmit() called for mode = [%hx]\n",
-			  port->mode);
+		  port->mode);
 out:
 	kfree_skb(skb);
 	return NET_XMIT_DROP;
@@ -685,7 +688,7 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
 
 	/* Should not reach here */
 	WARN_ONCE(true, "ipvlan_handle_frame() called for mode = [%hx]\n",
-			  port->mode);
+		  port->mode);
 	kfree_skb(skb);
 	return RX_HANDLER_CONSUMED;
 }
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index aa8575c..b837807 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -9,7 +9,7 @@
 
 #include "ipvlan.h"
 
-static u32 ipvl_nf_hook_refcnt = 0;
+static u32 ipvl_nf_hook_refcnt;
 
 static struct nf_hook_ops ipvl_nfops[] __read_mostly = {
 	{
@@ -73,8 +73,9 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval)
 			if (!err) {
 				mdev->l3mdev_ops = &ipvl_l3mdev_ops;
 				mdev->priv_flags |= IFF_L3MDEV_MASTER;
-			} else
+			} else {
 				return err;
+			}
 		} else if (port->mode == IPVLAN_MODE_L3S) {
 			/* Old mode was L3S */
 			mdev->priv_flags &= ~IFF_L3MDEV_MASTER;
@@ -107,7 +108,7 @@ static int ipvlan_port_create(struct net_device *dev)
 		return -EBUSY;
 	}
 
-	port = kzalloc(sizeof(struct ipvl_port), GFP_KERNEL);
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
 	if (!port)
 		return -ENOMEM;
 
@@ -163,7 +164,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
 	 NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)
 
 #define IPVLAN_STATE_MASK \
-	((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
+	((1 << __LINK_STATE_NOCARRIER) | (1 << __LINK_STATE_DORMANT))
 
 static int ipvlan_init(struct net_device *dev)
 {
@@ -274,7 +275,7 @@ static void ipvlan_change_rx_flags(struct net_device *dev, int change)
 	struct net_device *phy_dev = ipvlan->phy_dev;
 
 	if (change & IFF_ALLMULTI)
-		dev_set_allmulti(phy_dev, dev->flags & IFF_ALLMULTI? 1 : -1);
+		dev_set_allmulti(phy_dev, (dev->flags & IFF_ALLMULTI) ? 1 : -1);
 }
 
 static void ipvlan_set_multicast_mac_filter(struct net_device *dev)
@@ -319,7 +320,7 @@ static void ipvlan_get_stats64(struct net_device *dev,
 		for_each_possible_cpu(idx) {
 			pcptr = per_cpu_ptr(ipvlan->pcpu_stats, idx);
 			do {
-				strt= u64_stats_fetch_begin_irq(&pcptr->syncp);
+				strt = u64_stats_fetch_begin_irq(&pcptr->syncp);
 				rx_pkts = pcptr->rx_pkts;
 				rx_bytes = pcptr->rx_bytes;
 				rx_mcast = pcptr->rx_mcast;
@@ -386,7 +387,7 @@ static const struct net_device_ops ipvlan_netdev_ops = {
 
 static int ipvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
 			      unsigned short type, const void *daddr,
-			      const void *saddr, unsigned len)
+			      const void *saddr, unsigned int len)
 {
 	const struct ipvl_dev *ipvlan = netdev_priv(dev);
 	struct net_device *phy_dev = ipvlan->phy_dev;
@@ -400,7 +401,7 @@ static int ipvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
 }
 
 static const struct header_ops ipvlan_header_ops = {
-	.create  	= ipvlan_hard_header,
+	.create		= ipvlan_hard_header,
 	.parse		= eth_header_parse,
 	.cache		= eth_header_cache,
 	.cache_update	= eth_header_cache_update,
@@ -571,13 +572,12 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
 		goto remove_ida;
 
 	err = netdev_upper_dev_link(phy_dev, dev);
-	if (err) {
+	if (err)
 		goto unregister_netdev;
-	}
+
 	err = ipvlan_set_port_mode(port, mode);
-	if (err) {
+	if (err)
 		goto unlink_netdev;
-	}
 
 	list_add_tail_rcu(&ipvlan->pnode, &port->ipvlans);
 	netif_stacked_transfer_operstate(phy_dev, dev);
@@ -627,8 +627,7 @@ void ipvlan_link_setup(struct net_device *dev)
 }
 EXPORT_SYMBOL_GPL(ipvlan_link_setup);
 
-static const struct nla_policy ipvlan_nl_policy[IFLA_IPVLAN_MAX + 1] =
-{
+static const struct nla_policy ipvlan_nl_policy[IFLA_IPVLAN_MAX + 1] = {
 	[IFLA_IPVLAN_MODE] = { .type = NLA_U16 },
 };
 
@@ -709,7 +708,7 @@ static int ipvlan_add_addr(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6)
 {
 	struct ipvl_addr *addr;
 
-	addr = kzalloc(sizeof(struct ipvl_addr), GFP_ATOMIC);
+	addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
 	if (!addr)
 		return -ENOMEM;
 
@@ -743,8 +742,6 @@ static void ipvlan_del_addr(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6)
 	ipvlan_ht_addr_del(addr);
 	list_del(&addr->anode);
 	kfree_rcu(addr, rcu);
-
-	return;
 }
 
 static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
diff --git a/drivers/net/ipvlan/ipvtap.c b/drivers/net/ipvlan/ipvtap.c
index 2b713b6..04b2d50 100644
--- a/drivers/net/ipvlan/ipvtap.c
+++ b/drivers/net/ipvlan/ipvtap.c
@@ -32,6 +32,7 @@ static struct cdev ipvtap_cdev;
 static const void *ipvtap_net_namespace(struct device *d)
 {
 	struct net_device *dev = to_net_dev(d->parent);
+
 	return dev_net(dev);
 }
 
-- 
2.9.3

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.

^ permalink raw reply related

* [PATCH net-next 2/9] ipvlan: refactor ipvlan_process_multicast for readability
From: Marco Chiappero @ 2017-04-27 14:51 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Jeff Kirsher, Alexander Duyck, Sainath Grandhi,
	Mahesh Bandewar, Marco Chiappero
In-Reply-To: <20170427145142.15830-1-marco.chiappero@intel.com>

The function ipvlan_process_multicast both dequeues and dispatches
packets from/to ipvlan slaves. Decouple these two steps by introducing
ipvlan_dispatch_multicast, in order to reduce indentation and improve
the overall readability.

Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
Tested-by: Marco Chiappero <marco.chiappero@intel.com>
---
 drivers/net/ipvlan/ipvlan_core.c | 107 +++++++++++++++++++++------------------
 1 file changed, 57 insertions(+), 50 deletions(-)

diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 1266f01..fd40c25 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -185,18 +185,69 @@ unsigned int ipvlan_mac_hash(const unsigned char *addr)
 	return hash & IPVLAN_MAC_FILTER_MASK;
 }
 
+static void ipvlan_dispatch_multicast(struct ipvl_port *port,
+				      struct sk_buff *skb, u8 pkt_type,
+				      unsigned int mac_hash)
+{
+	struct ipvl_dev *ipvlan;
+	struct sk_buff *nskb;
+	struct net_device *dev = skb->dev;
+	bool tx_pkt = IPVL_SKB_CB(skb)->tx_pkt;
+	bool consumed = false;
+	unsigned int len;
+	int ret;
+
+	/* dispatch to slaves */
+	rcu_read_lock();
+	list_for_each_entry_rcu(ipvlan, &port->ipvlans, pnode) {
+		if (tx_pkt && (ipvlan->dev == skb->dev))
+			continue;
+		if (!test_bit(mac_hash, ipvlan->mac_filters))
+			continue;
+		if (!(ipvlan->dev->flags & IFF_UP))
+			continue;
+		ret = NET_RX_DROP;
+		len = skb->len + ETH_HLEN;
+		nskb = skb_clone(skb, GFP_ATOMIC);
+		local_bh_disable();
+		if (nskb) {
+			consumed = true;
+			nskb->pkt_type = pkt_type;
+			nskb->dev = ipvlan->dev;
+			if (tx_pkt)
+				ret = dev_forward_skb(ipvlan->dev, nskb);
+			else
+				ret = netif_rx(nskb);
+		}
+		ipvlan_count_rx(ipvlan, len, ret == NET_RX_SUCCESS, true);
+		local_bh_enable();
+	}
+	rcu_read_unlock();
+
+	if (tx_pkt) {
+		/* If the packet originated here, send it out. */
+		skb->dev = port->dev;
+		skb->pkt_type = pkt_type;
+		dev_queue_xmit(skb);
+	} else {
+		if (consumed)
+			consume_skb(skb);
+		else
+			kfree_skb(skb);
+	}
+
+	if (dev)
+		dev_put(dev);
+}
+
 void ipvlan_process_multicast(struct work_struct *work)
 {
 	struct ipvl_port *port = container_of(work, struct ipvl_port, wq);
 	struct ethhdr *ethh;
-	struct ipvl_dev *ipvlan;
-	struct sk_buff *skb, *nskb;
+	struct sk_buff *skb;
 	struct sk_buff_head list;
-	unsigned int len;
 	unsigned int mac_hash;
-	int ret;
 	u8 pkt_type;
-	bool tx_pkt;
 
 	__skb_queue_head_init(&list);
 
@@ -205,11 +256,7 @@ void ipvlan_process_multicast(struct work_struct *work)
 	spin_unlock_bh(&port->backlog.lock);
 
 	while ((skb = __skb_dequeue(&list)) != NULL) {
-		struct net_device *dev = skb->dev;
-		bool consumed = false;
-
 		ethh = eth_hdr(skb);
-		tx_pkt = IPVL_SKB_CB(skb)->tx_pkt;
 		mac_hash = ipvlan_mac_hash(ethh->h_dest);
 
 		if (ether_addr_equal(ethh->h_dest, port->dev->broadcast))
@@ -217,47 +264,7 @@ void ipvlan_process_multicast(struct work_struct *work)
 		else
 			pkt_type = PACKET_MULTICAST;
 
-		rcu_read_lock();
-		list_for_each_entry_rcu(ipvlan, &port->ipvlans, pnode) {
-			if (tx_pkt && (ipvlan->dev == skb->dev))
-				continue;
-			if (!test_bit(mac_hash, ipvlan->mac_filters))
-				continue;
-			if (!(ipvlan->dev->flags & IFF_UP))
-				continue;
-			ret = NET_RX_DROP;
-			len = skb->len + ETH_HLEN;
-			nskb = skb_clone(skb, GFP_ATOMIC);
-			local_bh_disable();
-			if (nskb) {
-				consumed = true;
-				nskb->pkt_type = pkt_type;
-				nskb->dev = ipvlan->dev;
-				if (tx_pkt)
-					ret = dev_forward_skb(ipvlan->dev,
-							      nskb);
-				else
-					ret = netif_rx(nskb);
-			}
-			ipvlan_count_rx(ipvlan, len, ret == NET_RX_SUCCESS,
-					true);
-			local_bh_enable();
-		}
-		rcu_read_unlock();
-
-		if (tx_pkt) {
-			/* If the packet originated here, send it out. */
-			skb->dev = port->dev;
-			skb->pkt_type = pkt_type;
-			dev_queue_xmit(skb);
-		} else {
-			if (consumed)
-				consume_skb(skb);
-			else
-				kfree_skb(skb);
-		}
-		if (dev)
-			dev_put(dev);
+		ipvlan_dispatch_multicast(port, skb, pkt_type, mac_hash);
 	}
 }
 
-- 
2.9.3

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.

^ permalink raw reply related

* [PATCH net-next 3/9] ipvlan: replace ipvlan_rcv_frame
From: Marco Chiappero @ 2017-04-27 14:51 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Jeff Kirsher, Alexander Duyck, Sainath Grandhi,
	Mahesh Bandewar, Marco Chiappero
In-Reply-To: <20170427145142.15830-1-marco.chiappero@intel.com>

So far the ipvlan_rcv_frame function handled the reception for slaves of
both externally and internally (from the same port) originated packets.
However they need significantly different processing, with almost no
code to share.

This patch modifies ipvlan_rcv_frame to deal with internal packets only,
renaming it to ipvlan_rcv_int_frame, and introduces a new
ipvlan_rcv_ext_frame function for externally originated ones.

Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
Tested-by: Marco Chiappero <marco.chiappero@intel.com>
---
 drivers/net/ipvlan/ipvlan_core.c | 58 +++++++++++++++++++++-------------------
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index fd40c25..4683bad 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -280,46 +280,36 @@ static void ipvlan_skb_crossing_ns(struct sk_buff *skb, struct net_device *dev)
 		skb->dev = dev;
 }
 
-static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb,
-			    bool local)
+static int ipvlan_rcv_int_frame(struct ipvl_addr *addr, struct sk_buff **pskb)
 {
 	struct ipvl_dev *ipvlan = addr->master;
 	struct net_device *dev = ipvlan->dev;
-	unsigned int len;
-	rx_handler_result_t ret = RX_HANDLER_CONSUMED;
-	bool success = false;
 	struct sk_buff *skb = *pskb;
+	unsigned int len = skb->len + ETH_HLEN;
+	bool success = false;
 
-	len = skb->len + ETH_HLEN;
 	/* Only packets exchanged between two local slaves need to have
 	 * device-up check as well as skb-share check.
 	 */
-	if (local) {
-		if (unlikely(!(dev->flags & IFF_UP))) {
-			kfree_skb(skb);
-			goto out;
-		}
+	if (unlikely(!(dev->flags & IFF_UP))) {
+		kfree_skb(skb);
+		goto out;
+	}
 
-		skb = skb_share_check(skb, GFP_ATOMIC);
-		if (!skb)
-			goto out;
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (unlikely(!skb))
+		goto out;
 
-		*pskb = skb;
-	}
+	*pskb = skb;
 	ipvlan_skb_crossing_ns(skb, dev);
+	skb->pkt_type = PACKET_HOST;
 
-	if (local) {
-		skb->pkt_type = PACKET_HOST;
-		if (dev_forward_skb(ipvlan->dev, skb) == NET_RX_SUCCESS)
-			success = true;
-	} else {
-		ret = RX_HANDLER_ANOTHER;
+	if (dev_forward_skb(ipvlan->dev, skb) == NET_RX_SUCCESS)
 		success = true;
-	}
 
 out:
 	ipvlan_count_rx(ipvlan, len, success, false);
-	return ret;
+	return RX_HANDLER_CONSUMED;
 }
 
 static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port,
@@ -525,7 +515,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
 
 	addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
 	if (addr)
-		return ipvlan_rcv_frame(addr, &skb, true);
+		return ipvlan_rcv_int_frame(addr, &skb);
 
 out:
 	ipvlan_skb_crossing_ns(skb, ipvlan->phy_dev);
@@ -546,7 +536,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
 			addr = ipvlan_addr_lookup(ipvlan->port, lyr3h,
 						  addr_type, true);
 			if (addr)
-				return ipvlan_rcv_frame(addr, &skb, true);
+				return ipvlan_rcv_int_frame(addr, &skb);
 		}
 		skb = skb_share_check(skb, GFP_ATOMIC);
 		if (!skb)
@@ -616,6 +606,18 @@ static bool ipvlan_external_frame(struct sk_buff *skb, struct ipvl_port *port)
 	return true;
 }
 
+static int ipvlan_rcv_ext_frame(struct ipvl_addr *addr, struct sk_buff *skb)
+{
+	struct ipvl_dev *ipvlan = addr->master;
+	struct net_device *dev = ipvlan->dev;
+	unsigned int len = skb->len + ETH_HLEN;
+
+	ipvlan_skb_crossing_ns(skb, dev);
+	ipvlan_count_rx(ipvlan, len, true, false);
+
+	return RX_HANDLER_ANOTHER;
+}
+
 static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb,
 						 struct ipvl_port *port)
 {
@@ -631,7 +633,7 @@ static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb,
 
 	addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
 	if (addr)
-		ret = ipvlan_rcv_frame(addr, pskb, false);
+		ret = ipvlan_rcv_ext_frame(addr, skb);
 
 out:
 	return ret;
@@ -670,7 +672,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
 
 		addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
 		if (addr)
-			ret = ipvlan_rcv_frame(addr, pskb, false);
+			ret = ipvlan_rcv_ext_frame(addr, skb);
 	}
 
 	return ret;
-- 
2.9.3

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.

^ permalink raw reply related

* [PATCH net-next 4/9] ipvlan: rework the IP lookup function
From: Marco Chiappero @ 2017-04-27 14:51 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Jeff Kirsher, Alexander Duyck, Sainath Grandhi,
	Mahesh Bandewar, Marco Chiappero
In-Reply-To: <20170427145142.15830-1-marco.chiappero@intel.com>

Functions ipvlan_get_L3_hdr and ipvlan_addr_lookup are used to determine
whether a packet belongs to a slave by looking at L3 addresses. Being
tightly coupled, these two functions are always used in pair and have
some duplicated code that could be shared.

This patch combines them into a single ipvlan_get_slave_addr function
and refactor caller functions, streamlining code and improving
readability.

A ipvlan_get_slave_addr_dst utility function is also provided as most
lookups are based on the destination IP address.

Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
Tested-by: Marco Chiappero <marco.chiappero@intel.com>
---
 drivers/net/ipvlan/ipvlan_core.c | 187 +++++++++++----------------------------
 1 file changed, 52 insertions(+), 135 deletions(-)

diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 4683bad..876ce37 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -116,25 +116,34 @@ bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6)
 	return false;
 }
 
-static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type)
+static struct ipvl_addr *ipvlan_get_slave_addr(struct sk_buff *skb,
+					       struct ipvl_port *port,
+					       bool use_dest)
 {
-	void *lyr3h = NULL;
+	struct ipvl_addr *addr = NULL;
 
 	switch (skb->protocol) {
 	case htons(ETH_P_ARP): {
-		struct arphdr *arph;
+		u8 *arp_ptr;
+		__be32 dip;
 
-		if (unlikely(!pskb_may_pull(skb, sizeof(*arph))))
+		if (unlikely(!pskb_may_pull(skb, sizeof(struct arphdr))))
 			return NULL;
 
-		arph = arp_hdr(skb);
-		*type = IPVL_ARP;
-		lyr3h = arph;
+		arp_ptr = (u8 *)(arp_hdr(skb) + 1);
+		if (use_dest)
+			arp_ptr += (2 * port->dev->addr_len) + 4;
+		else
+			arp_ptr += port->dev->addr_len;
+
+		memcpy(&dip, arp_ptr, 4);
+		addr = ipvlan_ht_addr_lookup(port, &dip, false);
 		break;
 	}
 	case htons(ETH_P_IP): {
 		u32 pktlen;
 		struct iphdr *ip4h;
+		__be32 *i4addr;
 
 		if (unlikely(!pskb_may_pull(skb, sizeof(*ip4h))))
 			return NULL;
@@ -146,12 +155,14 @@ static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type)
 		if (skb->len < pktlen || pktlen < (ip4h->ihl * 4))
 			return NULL;
 
-		*type = IPVL_IPV4;
-		lyr3h = ip4h;
+		i4addr = use_dest ? &ip4h->daddr : &ip4h->saddr;
+		addr = ipvlan_ht_addr_lookup(port, i4addr, false);
 		break;
 	}
 	case htons(ETH_P_IPV6): {
 		struct ipv6hdr *ip6h;
+		struct nd_msg *ndmh;
+		struct in6_addr *i6addr;
 
 		if (unlikely(!pskb_may_pull(skb, sizeof(*ip6h))))
 			return NULL;
@@ -160,21 +171,28 @@ static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type)
 		if (ip6h->version != 6)
 			return NULL;
 
-		*type = IPVL_IPV6;
-		lyr3h = ip6h;
-		/* Only Neighbour Solicitation pkts need different treatment */
+		ndmh = (struct nd_msg *)(ip6h + 1);
 		if (ipv6_addr_any(&ip6h->saddr) &&
-		    ip6h->nexthdr == NEXTHDR_ICMP) {
-			*type = IPVL_ICMPV6;
-			lyr3h = ip6h + 1;
-		}
+		    ip6h->nexthdr == NEXTHDR_ICMP &&
+		    ndmh->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION)
+			i6addr = &ndmh->target;
+		else
+			i6addr = use_dest ? &ip6h->daddr : &ip6h->saddr;
+
+		addr = ipvlan_ht_addr_lookup(port, i6addr, true);
 		break;
 	}
 	default:
 		return NULL;
 	}
 
-	return lyr3h;
+	return addr;
+}
+
+static inline struct ipvl_addr *ipvlan_get_slave_addr_dst(struct sk_buff *skb,
+							 struct ipvl_port *port)
+{
+	return ipvlan_get_slave_addr(skb, port, true);
 }
 
 unsigned int ipvlan_mac_hash(const unsigned char *addr)
@@ -312,57 +330,6 @@ static int ipvlan_rcv_int_frame(struct ipvl_addr *addr, struct sk_buff **pskb)
 	return RX_HANDLER_CONSUMED;
 }
 
-static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port,
-					    void *lyr3h, int addr_type,
-					    bool use_dest)
-{
-	struct ipvl_addr *addr = NULL;
-
-	if (addr_type == IPVL_IPV6) {
-		struct ipv6hdr *ip6h;
-		struct in6_addr *i6addr;
-
-		ip6h = (struct ipv6hdr *)lyr3h;
-		i6addr = use_dest ? &ip6h->daddr : &ip6h->saddr;
-		addr = ipvlan_ht_addr_lookup(port, i6addr, true);
-	} else if (addr_type == IPVL_ICMPV6) {
-		struct nd_msg *ndmh;
-		struct in6_addr *i6addr;
-
-		/* Make sure that the NeighborSolicitation ICMPv6 packets
-		 * are handled to avoid DAD issue.
-		 */
-		ndmh = (struct nd_msg *)lyr3h;
-		if (ndmh->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
-			i6addr = &ndmh->target;
-			addr = ipvlan_ht_addr_lookup(port, i6addr, true);
-		}
-	} else if (addr_type == IPVL_IPV4) {
-		struct iphdr *ip4h;
-		__be32 *i4addr;
-
-		ip4h = (struct iphdr *)lyr3h;
-		i4addr = use_dest ? &ip4h->daddr : &ip4h->saddr;
-		addr = ipvlan_ht_addr_lookup(port, i4addr, false);
-	} else if (addr_type == IPVL_ARP) {
-		struct arphdr *arph;
-		unsigned char *arp_ptr;
-		__be32 dip;
-
-		arph = (struct arphdr *)lyr3h;
-		arp_ptr = (unsigned char *)(arph + 1);
-		if (use_dest)
-			arp_ptr += (2 * port->dev->addr_len) + 4;
-		else
-			arp_ptr += port->dev->addr_len;
-
-		memcpy(&dip, arp_ptr, 4);
-		addr = ipvlan_ht_addr_lookup(port, &dip, false);
-	}
-
-	return addr;
-}
-
 static int ipvlan_process_v4_outbound(struct sk_buff *skb)
 {
 	const struct iphdr *ip4h = ip_hdr(skb);
@@ -505,19 +472,12 @@ static void ipvlan_multicast_enqueue(struct ipvl_port *port,
 static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
 {
 	const struct ipvl_dev *ipvlan = netdev_priv(dev);
-	void *lyr3h;
 	struct ipvl_addr *addr;
-	int addr_type;
 
-	lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
-	if (!lyr3h)
-		goto out;
-
-	addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
+	addr = ipvlan_get_slave_addr_dst(skb, ipvlan->port);
 	if (addr)
 		return ipvlan_rcv_int_frame(addr, &skb);
 
-out:
 	ipvlan_skb_crossing_ns(skb, ipvlan->phy_dev);
 	return ipvlan_process_outbound(skb);
 }
@@ -527,17 +487,12 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
 	const struct ipvl_dev *ipvlan = netdev_priv(dev);
 	struct ethhdr *eth = eth_hdr(skb);
 	struct ipvl_addr *addr;
-	void *lyr3h;
-	int addr_type;
 
 	if (ether_addr_equal(eth->h_dest, eth->h_source)) {
-		lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
-		if (lyr3h) {
-			addr = ipvlan_addr_lookup(ipvlan->port, lyr3h,
-						  addr_type, true);
-			if (addr)
-				return ipvlan_rcv_int_frame(addr, &skb);
-		}
+		addr = ipvlan_get_slave_addr_dst(skb, ipvlan->port);
+		if (addr)
+			return ipvlan_rcv_int_frame(addr, &skb);
+
 		skb = skb_share_check(skb, GFP_ATOMIC);
 		if (!skb)
 			return NET_XMIT_DROP;
@@ -586,24 +541,10 @@ int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NET_XMIT_DROP;
 }
 
-static bool ipvlan_external_frame(struct sk_buff *skb, struct ipvl_port *port)
+static inline bool ipvlan_external_frame(struct sk_buff *skb,
+					 struct ipvl_port *port)
 {
-	struct ethhdr *eth = eth_hdr(skb);
-	struct ipvl_addr *addr;
-	void *lyr3h;
-	int addr_type;
-
-	if (ether_addr_equal(eth->h_source, skb->dev->dev_addr)) {
-		lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
-		if (!lyr3h)
-			return true;
-
-		addr = ipvlan_addr_lookup(port, lyr3h, addr_type, false);
-		if (addr)
-			return false;
-	}
-
-	return true;
+	return !ipvlan_get_slave_addr(skb, port, false);
 }
 
 static int ipvlan_rcv_ext_frame(struct ipvl_addr *addr, struct sk_buff *skb)
@@ -621,22 +562,14 @@ static int ipvlan_rcv_ext_frame(struct ipvl_addr *addr, struct sk_buff *skb)
 static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb,
 						 struct ipvl_port *port)
 {
-	void *lyr3h;
-	int addr_type;
 	struct ipvl_addr *addr;
 	struct sk_buff *skb = *pskb;
-	rx_handler_result_t ret = RX_HANDLER_PASS;
 
-	lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
-	if (!lyr3h)
-		goto out;
-
-	addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
+	addr = ipvlan_get_slave_addr_dst(skb, port);
 	if (addr)
-		ret = ipvlan_rcv_ext_frame(addr, skb);
+		return ipvlan_rcv_ext_frame(addr, skb);
 
-out:
-	return ret;
+	return RX_HANDLER_PASS;
 }
 
 static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
@@ -644,9 +577,6 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
 {
 	struct sk_buff *skb = *pskb;
 	struct ethhdr *eth = eth_hdr(skb);
-	rx_handler_result_t ret = RX_HANDLER_PASS;
-	void *lyr3h;
-	int addr_type;
 
 	if (is_multicast_ether_addr(eth->h_dest)) {
 		if (ipvlan_external_frame(skb, port)) {
@@ -666,16 +596,12 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
 	} else {
 		struct ipvl_addr *addr;
 
-		lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
-		if (!lyr3h)
-			return ret;
-
-		addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
+		addr = ipvlan_get_slave_addr_dst(skb, port);
 		if (addr)
-			ret = ipvlan_rcv_ext_frame(addr, skb);
+			return ipvlan_rcv_ext_frame(addr, skb);
 	}
 
-	return ret;
+	return RX_HANDLER_PASS;
 }
 
 rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
@@ -705,25 +631,16 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
 static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
 					    struct net_device *dev)
 {
-	struct ipvl_addr *addr = NULL;
 	struct ipvl_port *port;
-	void *lyr3h;
-	int addr_type;
 
 	if (!dev || !netif_is_ipvlan_port(dev))
-		goto out;
+		return NULL;
 
 	port = ipvlan_port_get_rcu(dev);
 	if (!port || port->mode != IPVLAN_MODE_L3S)
-		goto out;
-
-	lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
-	if (!lyr3h)
-		goto out;
+		return NULL;
 
-	addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
-out:
-	return addr;
+	return ipvlan_get_slave_addr_dst(skb, port);
 }
 
 struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
-- 
2.9.3

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.

^ permalink raw reply related

* [PATCH net-next 5/9] ipvlan: improve and uniform naming
From: Marco Chiappero @ 2017-04-27 14:51 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Jeff Kirsher, Alexander Duyck, Sainath Grandhi,
	Mahesh Bandewar, Marco Chiappero
In-Reply-To: <20170427145142.15830-1-marco.chiappero@intel.com>

Rename a few functions to make them more descriptive. Also rename a
couple of variables to make them consistent with similar ones in other
functions.

Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
Tested-by: Marco Chiappero <marco.chiappero@intel.com>
---
 drivers/net/ipvlan/ipvlan_core.c | 29 ++++++++++++++---------------
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 876ce37..54c4e85 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -330,7 +330,7 @@ static int ipvlan_rcv_int_frame(struct ipvl_addr *addr, struct sk_buff **pskb)
 	return RX_HANDLER_CONSUMED;
 }
 
-static int ipvlan_process_v4_outbound(struct sk_buff *skb)
+static int ipvlan_process_l3_outbound_v4(struct sk_buff *skb)
 {
 	const struct iphdr *ip4h = ip_hdr(skb);
 	struct net_device *dev = skb->dev;
@@ -367,7 +367,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
 	return ret;
 }
 
-static int ipvlan_process_v6_outbound(struct sk_buff *skb)
+static int ipvlan_process_l3_outbound_v6(struct sk_buff *skb)
 {
 	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
 	struct net_device *dev = skb->dev;
@@ -404,7 +404,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
 	return ret;
 }
 
-static int ipvlan_process_outbound(struct sk_buff *skb)
+static int ipvlan_process_l3_outbound(struct sk_buff *skb)
 {
 	struct ethhdr *ethh = eth_hdr(skb);
 	int ret = NET_XMIT_DROP;
@@ -428,9 +428,9 @@ static int ipvlan_process_outbound(struct sk_buff *skb)
 	}
 
 	if (skb->protocol == htons(ETH_P_IPV6)) {
-		ret = ipvlan_process_v6_outbound(skb);
+		ret = ipvlan_process_l3_outbound_v6(skb);
 	} else if (skb->protocol == htons(ETH_P_IP)) {
-		ret = ipvlan_process_v4_outbound(skb);
+		ret = ipvlan_process_l3_outbound_v4(skb);
 	} else {
 		pr_warn_ratelimited("Dropped outbound packet type=%x\n",
 				    ntohs(skb->protocol));
@@ -479,16 +479,16 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
 		return ipvlan_rcv_int_frame(addr, &skb);
 
 	ipvlan_skb_crossing_ns(skb, ipvlan->phy_dev);
-	return ipvlan_process_outbound(skb);
+	return ipvlan_process_l3_outbound(skb);
 }
 
 static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
 {
 	const struct ipvl_dev *ipvlan = netdev_priv(dev);
-	struct ethhdr *eth = eth_hdr(skb);
+	struct ethhdr *ethh = eth_hdr(skb);
 	struct ipvl_addr *addr;
 
-	if (ether_addr_equal(eth->h_dest, eth->h_source)) {
+	if (ether_addr_equal(ethh->h_dest, ethh->h_source)) {
 		addr = ipvlan_get_slave_addr_dst(skb, ipvlan->port);
 		if (addr)
 			return ipvlan_rcv_int_frame(addr, &skb);
@@ -504,7 +504,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
 		 */
 		return dev_forward_skb(ipvlan->phy_dev, skb);
 
-	} else if (is_multicast_ether_addr(eth->h_dest)) {
+	} else if (is_multicast_ether_addr(ethh->h_dest)) {
 		ipvlan_skb_crossing_ns(skb, NULL);
 		ipvlan_multicast_enqueue(ipvlan->port, skb, true);
 		return NET_XMIT_SUCCESS;
@@ -576,9 +576,8 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
 						 struct ipvl_port *port)
 {
 	struct sk_buff *skb = *pskb;
-	struct ethhdr *eth = eth_hdr(skb);
 
-	if (is_multicast_ether_addr(eth->h_dest)) {
+	if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
 		if (ipvlan_external_frame(skb, port)) {
 			struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
 
@@ -628,8 +627,8 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
 	return RX_HANDLER_CONSUMED;
 }
 
-static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
-					    struct net_device *dev)
+static struct ipvl_addr *ipvlan_skb_to_addr_l3s(struct sk_buff *skb,
+						struct net_device *dev)
 {
 	struct ipvl_port *port;
 
@@ -649,7 +648,7 @@ struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
 	struct ipvl_addr *addr;
 	struct net_device *sdev;
 
-	addr = ipvlan_skb_to_addr(skb, dev);
+	addr = ipvlan_skb_to_addr_l3s(skb, dev);
 	if (!addr)
 		goto out;
 
@@ -699,7 +698,7 @@ unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
 	struct ipvl_addr *addr;
 	unsigned int len;
 
-	addr = ipvlan_skb_to_addr(skb, skb->dev);
+	addr = ipvlan_skb_to_addr_l3s(skb, skb->dev);
 	if (!addr)
 		goto out;
 
-- 
2.9.3

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.

^ permalink raw reply related

* [PATCH net-next 7/9] ipvlan: relocate ipvlan_skb_crossing_ns calls
From: Marco Chiappero @ 2017-04-27 14:51 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Jeff Kirsher, Alexander Duyck, Sainath Grandhi,
	Mahesh Bandewar, Marco Chiappero
In-Reply-To: <20170427145142.15830-1-marco.chiappero@intel.com>

Relocate ipvlan_skb_crossing_ns invocations across the code to reduce
duplications and improve readability. Additionally introduce
ipvlan_process_l2_outbound for the purpose, similarly to
ipvlan_process_l3_outbound.

Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
---
 drivers/net/ipvlan/ipvlan_core.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 81dc3e5..a9fc1b5 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -289,6 +289,8 @@ void ipvlan_process_multicast(struct work_struct *work)
 		ethh = eth_hdr(skb);
 		mac_hash = ipvlan_mac_hash(ethh->h_dest);
 
+		ipvlan_skb_crossing_ns(skb, NULL);
+
 		if (ether_addr_equal(ethh->h_dest, port->dev->broadcast))
 			pkt_type = PACKET_BROADCAST;
 		else
@@ -433,7 +435,8 @@ static int ipvlan_process_l3_outbound_v6(struct sk_buff *skb)
 	return ret;
 }
 
-static int ipvlan_process_l3_outbound(struct sk_buff *skb)
+static int ipvlan_process_l3_outbound(struct sk_buff *skb,
+				      struct net_device *dev)
 {
 	struct ethhdr *ethh = eth_hdr(skb);
 	int ret = NET_XMIT_DROP;
@@ -446,6 +449,8 @@ static int ipvlan_process_l3_outbound(struct sk_buff *skb)
 		goto out;
 	}
 
+	ipvlan_skb_crossing_ns(skb, dev);
+
 	/* The ipvlan is a pseudo-L2 device, so the packets that we receive
 	 * will have L2; which need to discarded and processed further
 	 * in the net-ns of the main-device.
@@ -478,8 +483,14 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
 	if (addr)
 		return ipvlan_rcv_int_frame(addr, &skb);
 
-	ipvlan_skb_crossing_ns(skb, ipvlan->phy_dev);
-	return ipvlan_process_l3_outbound(skb);
+	return ipvlan_process_l3_outbound(skb, ipvlan->phy_dev);
+}
+
+static inline int ipvlan_process_l2_outbound(struct sk_buff *skb,
+					     struct net_device *dev)
+{
+	ipvlan_skb_crossing_ns(skb, dev);
+	return dev_queue_xmit(skb);
 }
 
 static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
@@ -505,13 +516,11 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
 		return dev_forward_skb(ipvlan->phy_dev, skb);
 
 	} else if (is_multicast_ether_addr(ethh->h_dest)) {
-		ipvlan_skb_crossing_ns(skb, NULL);
 		ipvlan_multicast_enqueue(ipvlan->port, skb, true);
 		return NET_XMIT_SUCCESS;
 	}
 
-	ipvlan_skb_crossing_ns(skb, ipvlan->phy_dev);
-	return dev_queue_xmit(skb);
+	return ipvlan_process_l2_outbound(skb, ipvlan->phy_dev);
 }
 
 int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -587,10 +596,8 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
 			 * when work-queue processes this frame. This is
 			 * achieved by returning RX_HANDLER_PASS.
 			 */
-			if (nskb) {
-				ipvlan_skb_crossing_ns(nskb, NULL);
+			if (nskb)
 				ipvlan_multicast_enqueue(port, nskb, false);
-			}
 		}
 	} else {
 		struct ipvl_addr *addr;
-- 
2.9.3

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.

^ permalink raw reply related

* [PATCH net-next 6/9] ipvlan: reposition three functions
From: Marco Chiappero @ 2017-04-27 14:51 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Jeff Kirsher, Alexander Duyck, Sainath Grandhi,
	Mahesh Bandewar, Marco Chiappero
In-Reply-To: <20170427145142.15830-1-marco.chiappero@intel.com>

Move ipvlan_multicast_enqueue, ipvlan_skb_crossing_ns and
ipvlan_mac_hash close to their related siblings.

Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
---
 drivers/net/ipvlan/ipvlan_core.c | 80 ++++++++++++++++++++--------------------
 1 file changed, 40 insertions(+), 40 deletions(-)

diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 54c4e85..81dc3e5 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -88,6 +88,14 @@ void ipvlan_ht_addr_del(struct ipvl_addr *addr)
 	hlist_del_init_rcu(&addr->hlnode);
 }
 
+unsigned int ipvlan_mac_hash(const unsigned char *addr)
+{
+	u32 hash = jhash_1word(__get_unaligned_cpu32(addr + 2),
+			       ipvlan_jhash_secret);
+
+	return hash & IPVLAN_MAC_FILTER_MASK;
+}
+
 struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
 				   const void *iaddr, bool is_v6)
 {
@@ -195,12 +203,16 @@ static inline struct ipvl_addr *ipvlan_get_slave_addr_dst(struct sk_buff *skb,
 	return ipvlan_get_slave_addr(skb, port, true);
 }
 
-unsigned int ipvlan_mac_hash(const unsigned char *addr)
+static void ipvlan_skb_crossing_ns(struct sk_buff *skb, struct net_device *dev)
 {
-	u32 hash = jhash_1word(__get_unaligned_cpu32(addr + 2),
-			       ipvlan_jhash_secret);
+	bool xnet = true;
 
-	return hash & IPVLAN_MAC_FILTER_MASK;
+	if (dev)
+		xnet = !net_eq(dev_net(skb->dev), dev_net(dev));
+
+	skb_scrub_packet(skb, xnet);
+	if (dev)
+		skb->dev = dev;
 }
 
 static void ipvlan_dispatch_multicast(struct ipvl_port *port,
@@ -286,16 +298,33 @@ void ipvlan_process_multicast(struct work_struct *work)
 	}
 }
 
-static void ipvlan_skb_crossing_ns(struct sk_buff *skb, struct net_device *dev)
+static void ipvlan_multicast_enqueue(struct ipvl_port *port,
+				     struct sk_buff *skb, bool tx_pkt)
 {
-	bool xnet = true;
+	if (skb->protocol == htons(ETH_P_PAUSE)) {
+		kfree_skb(skb);
+		return;
+	}
 
-	if (dev)
-		xnet = !net_eq(dev_net(skb->dev), dev_net(dev));
+	/* Record that the deferred packet is from TX or RX path. By
+	 * looking at mac-addresses on packet will lead to erronus decisions.
+	 * (This would be true for a loopback-mode on master device or a
+	 * hair-pin mode of the switch.)
+	 */
+	IPVL_SKB_CB(skb)->tx_pkt = tx_pkt;
 
-	skb_scrub_packet(skb, xnet);
-	if (dev)
-		skb->dev = dev;
+	spin_lock(&port->backlog.lock);
+	if (skb_queue_len(&port->backlog) < IPVLAN_QBACKLOG_LIMIT) {
+		if (skb->dev)
+			dev_hold(skb->dev);
+		__skb_queue_tail(&port->backlog, skb);
+		spin_unlock(&port->backlog.lock);
+		schedule_work(&port->wq);
+	} else {
+		spin_unlock(&port->backlog.lock);
+		atomic_long_inc(&skb->dev->rx_dropped);
+		kfree_skb(skb);
+	}
 }
 
 static int ipvlan_rcv_int_frame(struct ipvl_addr *addr, struct sk_buff **pskb)
@@ -440,35 +469,6 @@ static int ipvlan_process_l3_outbound(struct sk_buff *skb)
 	return ret;
 }
 
-static void ipvlan_multicast_enqueue(struct ipvl_port *port,
-				     struct sk_buff *skb, bool tx_pkt)
-{
-	if (skb->protocol == htons(ETH_P_PAUSE)) {
-		kfree_skb(skb);
-		return;
-	}
-
-	/* Record that the deferred packet is from TX or RX path. By
-	 * looking at mac-addresses on packet will lead to erronus decisions.
-	 * (This would be true for a loopback-mode on master device or a
-	 * hair-pin mode of the switch.)
-	 */
-	IPVL_SKB_CB(skb)->tx_pkt = tx_pkt;
-
-	spin_lock(&port->backlog.lock);
-	if (skb_queue_len(&port->backlog) < IPVLAN_QBACKLOG_LIMIT) {
-		if (skb->dev)
-			dev_hold(skb->dev);
-		__skb_queue_tail(&port->backlog, skb);
-		spin_unlock(&port->backlog.lock);
-		schedule_work(&port->wq);
-	} else {
-		spin_unlock(&port->backlog.lock);
-		atomic_long_inc(&skb->dev->rx_dropped);
-		kfree_skb(skb);
-	}
-}
-
 static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
 {
 	const struct ipvl_dev *ipvlan = netdev_priv(dev);
-- 
2.9.3

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.

^ permalink raw reply related

* [PATCH net-next 8/9] ipvlan: improve compiler hints
From: Marco Chiappero @ 2017-04-27 14:51 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Jeff Kirsher, Alexander Duyck, Sainath Grandhi,
	Mahesh Bandewar, Marco Chiappero
In-Reply-To: <20170427145142.15830-1-marco.chiappero@intel.com>

Extend inlining and branch prediction hints.

Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
---
 drivers/net/ipvlan/ipvlan_core.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index a9fc1b5..67e342d 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -88,7 +88,7 @@ void ipvlan_ht_addr_del(struct ipvl_addr *addr)
 	hlist_del_init_rcu(&addr->hlnode);
 }
 
-unsigned int ipvlan_mac_hash(const unsigned char *addr)
+inline unsigned int ipvlan_mac_hash(const unsigned char *addr)
 {
 	u32 hash = jhash_1word(__get_unaligned_cpu32(addr + 2),
 			       ipvlan_jhash_secret);
@@ -505,7 +505,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
 			return ipvlan_rcv_int_frame(addr, &skb);
 
 		skb = skb_share_check(skb, GFP_ATOMIC);
-		if (!skb)
+		if (unlikely(!skb))
 			return NET_XMIT_DROP;
 
 		/* Packet definitely does not belong to any of the
@@ -596,7 +596,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
 			 * when work-queue processes this frame. This is
 			 * achieved by returning RX_HANDLER_PASS.
 			 */
-			if (nskb)
+			if (likely(nskb))
 				ipvlan_multicast_enqueue(port, nskb, false);
 		}
 	} else {
-- 
2.9.3

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.

^ permalink raw reply related

* [PATCH net-next 9/9] ipvlan: introduce individual MAC addresses
From: Marco Chiappero @ 2017-04-27 14:51 UTC (permalink / raw)
  To: netdev
  Cc: David S . Miller, Jeff Kirsher, Alexander Duyck, Sainath Grandhi,
	Mahesh Bandewar, Marco Chiappero
In-Reply-To: <20170427145142.15830-1-marco.chiappero@intel.com>

Currently all the slave devices belonging to the same port inherit their
MAC address from its master device. This patch removes this limitation
and allows every slave device to obtain a unique MAC address, by default
randomly generated at creation time.

Moreover it is now possible to correctly modify the MAC address at any
time, fixing an existing bug as MAC address changes on the master were
not reflected on the slaves. It also avoids multiple interfaces sharing
the same IPv6 link-local address.

Since ipvlan is designed to expose a single MAC address for external
communications, the driver now behaves as follow:
- L2 mode:
   * Any reference to the internal MAC address of the originating slave
     is replaced with the MAC address of the master for outbound frames.
   * Likewise, the destination MAC address is overwritten with the
     internal one (once the correct slave is determined) for any
     incoming external frame.
   * For any internal slave-to-slave communication, the original MAC
     addresses are preserved (although not used for routing/switching).
- L3/L3s mode:
   * The destination MAC address for incoming external packets is
     replaced with the one belonging to the destination slave device
     (as for L2 mode)
   * Every other path behaves as before.

Being a significant behavioral change, version number has been
increased.

Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
Tested-by: Marco Chiappero <marco.chiappero@intel.com>
---
 drivers/net/ipvlan/ipvlan.h      |   2 +-
 drivers/net/ipvlan/ipvlan_core.c | 113 ++++++++++++++++++++++++++++++++++-----
 drivers/net/ipvlan/ipvlan_main.c |  18 +++----
 3 files changed, 111 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h
index 800a46c..efe4fd1 100644
--- a/drivers/net/ipvlan/ipvlan.h
+++ b/drivers/net/ipvlan/ipvlan.h
@@ -32,7 +32,7 @@
 #include <net/l3mdev.h>
 
 #define IPVLAN_DRV	"ipvlan"
-#define IPV_DRV_VER	"0.1"
+#define IPV_DRV_VER	"0.2"
 
 #define IPVLAN_HASH_SIZE	(1 << BITS_PER_BYTE)
 #define IPVLAN_HASH_MASK	(IPVLAN_HASH_SIZE - 1)
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 67e342d..a30bc11 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -215,6 +215,89 @@ static void ipvlan_skb_crossing_ns(struct sk_buff *skb, struct net_device *dev)
 		skb->dev = dev;
 }
 
+static inline struct nd_opt_hdr *ipvlan_icmp6_nd_opts(struct icmp6hdr *icmph)
+{
+	return (struct nd_opt_hdr *)((struct nd_msg *)icmph)->opt;
+}
+
+static inline struct nd_opt_hdr *ipvlan_icmp6_rs_opts(struct icmp6hdr *icmph)
+{
+	return (struct nd_opt_hdr *)((struct rs_msg *)icmph)->opt;
+}
+
+static void ipvlan_proxy_l2_update_icmp6(const struct net_device *master,
+					 struct sk_buff *skb,
+					 struct nd_opt_hdr *nd_opt,
+					 u8 opt_type)
+{
+	u32 opts_len = skb_tail_pointer(skb) - (u8 *)nd_opt;
+
+	while (opts_len) {
+		u32 opt_len = nd_opt->nd_opt_len << 3;
+
+		if (nd_opt->nd_opt_type == opt_type) {
+			struct ipv6hdr *ip6h = ipv6_hdr(skb);
+			struct icmp6hdr *icmph = icmp6_hdr(skb);
+			u32 len = ntohs(ip6h->payload_len);
+
+			memcpy(nd_opt + 1, master->dev_addr, master->addr_len);
+			icmph->icmp6_cksum = 0;
+			icmph->icmp6_cksum =
+				csum_ipv6_magic(&ip6h->saddr,
+						&ip6h->daddr, len,
+						IPPROTO_ICMPV6,
+						csum_partial(icmph, len, 0));
+			return;
+		}
+
+		opts_len -= opt_len;
+		nd_opt = ((void *)nd_opt) + opt_len;
+	}
+}
+
+static void ipvlan_proxy_l2_outbound(struct sk_buff *skb,
+				     const struct net_device *master)
+{
+	/* masquerade the source MAC address for every outgoing frame */
+	memcpy(eth_hdr(skb)->h_source, master->dev_addr, master->addr_len);
+
+	/* ARP and some NDISC packets need additional treatment */
+	if (skb->protocol == htons(ETH_P_IPV6)) {
+		struct ipv6hdr *ip6h = ipv6_hdr(skb);
+		struct icmp6hdr *icmph = icmp6_hdr(skb);
+		struct nd_opt_hdr *nd_opt;
+		u8 opt_type;
+
+		if (likely(ip6h->nexthdr != NEXTHDR_ICMP))
+			return;
+
+		switch (icmph->icmp6_type) {
+		case NDISC_NEIGHBOUR_SOLICITATION: {
+			nd_opt = ipvlan_icmp6_nd_opts(icmph);
+			opt_type = ND_OPT_SOURCE_LL_ADDR;
+			break;
+		}
+		case NDISC_NEIGHBOUR_ADVERTISEMENT: {
+			nd_opt = ipvlan_icmp6_nd_opts(icmph);
+			opt_type = ND_OPT_TARGET_LL_ADDR;
+			break;
+		}
+		case NDISC_ROUTER_SOLICITATION: {
+			nd_opt = ipvlan_icmp6_rs_opts(icmph);
+			opt_type = ND_OPT_SOURCE_LL_ADDR;
+			break;
+		}
+		default:
+			return;
+		}
+
+		ipvlan_proxy_l2_update_icmp6(master, skb, nd_opt, opt_type);
+
+	} else if (unlikely(skb->protocol == htons(ETH_P_ARP))) {
+		memcpy(arp_hdr(skb) + 1, master->dev_addr, master->addr_len);
+	}
+}
+
 static void ipvlan_dispatch_multicast(struct ipvl_port *port,
 				      struct sk_buff *skb, u8 pkt_type,
 				      unsigned int mac_hash)
@@ -258,6 +341,7 @@ static void ipvlan_dispatch_multicast(struct ipvl_port *port,
 		/* If the packet originated here, send it out. */
 		skb->dev = port->dev;
 		skb->pkt_type = pkt_type;
+		ipvlan_proxy_l2_outbound(skb, port->dev);
 		dev_queue_xmit(skb);
 	} else {
 		if (consumed)
@@ -489,6 +573,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
 static inline int ipvlan_process_l2_outbound(struct sk_buff *skb,
 					     struct net_device *dev)
 {
+	ipvlan_proxy_l2_outbound(skb, dev);
 	ipvlan_skb_crossing_ns(skb, dev);
 	return dev_queue_xmit(skb);
 }
@@ -499,27 +584,27 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
 	struct ethhdr *ethh = eth_hdr(skb);
 	struct ipvl_addr *addr;
 
-	if (ether_addr_equal(ethh->h_dest, ethh->h_source)) {
-		addr = ipvlan_get_slave_addr_dst(skb, ipvlan->port);
-		if (addr)
-			return ipvlan_rcv_int_frame(addr, &skb);
+	if (is_multicast_ether_addr(ethh->h_dest)) {
+		ipvlan_multicast_enqueue(ipvlan->port, skb, true);
+		return NET_XMIT_SUCCESS;
+	}
 
+	if (ether_addr_equal(ethh->h_dest, ipvlan->phy_dev->dev_addr)) {
 		skb = skb_share_check(skb, GFP_ATOMIC);
 		if (unlikely(!skb))
 			return NET_XMIT_DROP;
 
-		/* Packet definitely does not belong to any of the
-		 * virtual devices, but the dest is local. So forward
-		 * the skb for the main-dev. At the RX side we just return
-		 * RX_PASS for it to be processed further on the stack.
+		/* Forward the skb for the master device. At the RX side we
+		 * just return RX_HANDLER_PASS for it to be processed further
+		 * on the stack.
 		 */
 		return dev_forward_skb(ipvlan->phy_dev, skb);
-
-	} else if (is_multicast_ether_addr(ethh->h_dest)) {
-		ipvlan_multicast_enqueue(ipvlan->port, skb, true);
-		return NET_XMIT_SUCCESS;
 	}
 
+	addr = ipvlan_get_slave_addr_dst(skb, ipvlan->port);
+	if (addr)
+		return ipvlan_rcv_int_frame(addr, &skb);
+
 	return ipvlan_process_l2_outbound(skb, ipvlan->phy_dev);
 }
 
@@ -562,6 +647,10 @@ static int ipvlan_rcv_ext_frame(struct ipvl_addr *addr, struct sk_buff *skb)
 	struct net_device *dev = ipvlan->dev;
 	unsigned int len = skb->len + ETH_HLEN;
 
+	/* NOTE: although not necessary restore the actual destination
+	 * address; this is also what traffic sniffers will display.
+	 */
+	memcpy(eth_hdr(skb)->h_dest, dev->dev_addr, dev->addr_len);
 	ipvlan_skb_crossing_ns(skb, dev);
 	ipvlan_count_rx(ipvlan, len, true, false);
 
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index b837807..709f27d 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -378,6 +378,7 @@ static const struct net_device_ops ipvlan_netdev_ops = {
 	.ndo_start_xmit		= ipvlan_start_xmit,
 	.ndo_fix_features	= ipvlan_fix_features,
 	.ndo_change_rx_flags	= ipvlan_change_rx_flags,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_set_rx_mode	= ipvlan_set_multicast_mac_filter,
 	.ndo_get_stats64	= ipvlan_get_stats64,
 	.ndo_vlan_rx_add_vid	= ipvlan_vlan_rx_add_vid,
@@ -392,9 +393,10 @@ static int ipvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
 	const struct ipvl_dev *ipvlan = netdev_priv(dev);
 	struct net_device *phy_dev = ipvlan->phy_dev;
 
-	/* TODO Probably use a different field than dev_addr so that the
-	 * mac-address on the virtual device is portable and can be carried
-	 * while the packets use the mac-addr on the physical device.
+	/* This driver uses (almost exclusively) L3 addresses for
+	 * routing/switching. Use the actual slave's MAC address,
+	 * but overwrite it later during the packet processing for
+	 * frames leaving from master
 	 */
 	return dev_hard_header(skb, phy_dev, type, daddr,
 			       saddr ? : dev->dev_addr, len);
@@ -559,11 +561,8 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
 	/* Increment id-base to the next slot for the future assignment */
 	port->dev_id_start = err + 1;
 
-	/* TODO Probably put random address here to be presented to the
-	 * world but keep using the physical-dev address for the outgoing
-	 * packets.
-	 */
-	memcpy(dev->dev_addr, phy_dev->dev_addr, ETH_ALEN);
+	/* TODO: consider storing the original MAC address in dev->perm_addr */
+	eth_hw_addr_random(dev);
 
 	dev->priv_flags |= IFF_IPVLAN_SLAVE;
 
@@ -619,7 +618,8 @@ void ipvlan_link_setup(struct net_device *dev)
 	ether_setup(dev);
 
 	dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
-	dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE;
+	dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE
+			   | IFF_LIVE_ADDR_CHANGE;
 	dev->netdev_ops = &ipvlan_netdev_ops;
 	dev->destructor = free_netdev;
 	dev->header_ops = &ipvlan_header_ops;
-- 
2.9.3

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.

^ permalink raw reply related

* RE: [PATCH v6 1/5] skbuff: return -EMSGSIZE in skb_to_sgvec to prevent overflow
From: David Laight @ 2017-04-27 14:54 UTC (permalink / raw)
  To: 'Jason A. Donenfeld', Sabrina Dubroca
  Cc: Netdev, LKML, kernel-hardening@lists.openwall.com, David Miller
In-Reply-To: <CAHmME9oa3LYsnBgguxFqbJwps1ai=cuHHEgSpfY36AQHAN5r1Q@mail.gmail.com>

From: Jason A. Donenfeld
> On Thu, Apr 27, 2017 at 1:30 PM, Sabrina Dubroca <sd@queasysnail.net> wrote:
> > Hmm, I think this can actually happen:
> 
> Alright, perhaps better to err on the side of caution, then.

You only need to recurse if both pointers are set.

	David


^ 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