Netdev List
 help / color / mirror / Atom feed
* [PATCH 06/64] drivers: net: bcm63xx: use setup_timer() helper.
From: Allen Pais @ 2017-09-21 17:04 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, m.grzeschik, dmitry.tarnyagin, wg, mkl, mark.einon,
	linux, pcnet32, f.fainelli, bcm-kernel-feedback-list, venza, ajk,
	jes, romieu, khc, simon, davem, linux-can, adi-buildroot-devel,
	Allen Pais
In-Reply-To: <1506013525-29291-1-git-send-email-allen.lkml@gmail.com>

    Use setup_timer function instead of initializing timer with the
    function and data fields.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/net/ethernet/broadcom/bcm63xx_enet.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 4f3845a..f8bbbbf 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1857,9 +1857,8 @@ static int bcm_enet_probe(struct platform_device *pdev)
 	spin_lock_init(&priv->rx_lock);
 
 	/* init rx timeout (used for oom) */
-	init_timer(&priv->rx_timeout);
-	priv->rx_timeout.function = bcm_enet_refill_rx_timer;
-	priv->rx_timeout.data = (unsigned long)dev;
+	setup_timer(&priv->rx_timeout, bcm_enet_refill_rx_timer,
+		    (unsigned long)dev);
 
 	/* init the mib update lock&work */
 	mutex_init(&priv->mib_update_lock);
-- 
2.7.4

^ permalink raw reply related

* [PATCH 08/64] drivers: net: am79c961: use setup_timer() helper.
From: Allen Pais @ 2017-09-21 17:04 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, m.grzeschik, dmitry.tarnyagin, wg, mkl, mark.einon,
	linux, pcnet32, f.fainelli, bcm-kernel-feedback-list, venza, ajk,
	jes, romieu, khc, simon, davem, linux-can, adi-buildroot-devel,
	Allen Pais
In-Reply-To: <1506013525-29291-1-git-send-email-allen.lkml@gmail.com>

    Use setup_timer function instead of initializing timer with the
    function and data fields.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/net/ethernet/amd/am79c961a.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/amd/am79c961a.c b/drivers/net/ethernet/amd/am79c961a.c
index b11e910..0612dbe 100644
--- a/drivers/net/ethernet/amd/am79c961a.c
+++ b/drivers/net/ethernet/amd/am79c961a.c
@@ -728,9 +728,7 @@ static int am79c961_probe(struct platform_device *pdev)
 	am79c961_banner();
 
 	spin_lock_init(&priv->chip_lock);
-	init_timer(&priv->timer);
-	priv->timer.data = (unsigned long)dev;
-	priv->timer.function = am79c961_timer;
+	setup_timer(&priv->timer, am79c961_timer, (unsigned long)dev);
 
 	if (am79c961_hw_init(dev))
 		goto release;
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH net 1/3] net: mvpp2: fix the dma_mask and coherent_dma_mask settings for PPv2.2
From: David Miller @ 2017-09-21 17:07 UTC (permalink / raw)
  To: antoine.tenart
  Cc: andrew, gregory.clement, thomas.petazzoni, miquel.raynal, nadavh,
	linux, linux-kernel, mw, stefanc, netdev
In-Reply-To: <20170921142413.GH3568@kwain>

From: Antoine Tenart <antoine.tenart@free-electrons.com>
Date: Thu, 21 Sep 2017 16:24:13 +0200

> That's also the default when the platform does not allocate dma_mask.

That's the problem that needs to be fixed then.

^ permalink raw reply

* Re: [REGRESSION] Warning in tcp_fastretrans_alert() of net/ipv4/tcp_input.c
From: Yuchung Cheng @ 2017-09-21 17:07 UTC (permalink / raw)
  To: 10035198.1vE6NFrMDO
  Cc: Oleksandr Natalenko, Alexey Kuznetsov, Hideaki YOSHIFUJI, netdev,
	linux-kernel@vger.kernel.org
In-Reply-To: <20170921014620.GA20906@castle>

On Wed, Sep 20, 2017 at 6:46 PM, Roman Gushchin <guro@fb.com> wrote:
>
> > Hello.
> >
> > Since, IIRC, v4.11, there is some regression in TCP stack resulting in the
> > warning shown below. Most of the time it is harmless, but rarely it just
> > causes either freeze or (I believe, this is related too) panic in
> > tcp_sacktag_walk() (because sk_buff passed to this function is NULL).
> > Unfortunately, I still do not have proper stacktrace from panic, but will try
> > to capture it if possible.
> >
> > Also, I have custom settings regarding TCP stack, shown below as well. ifb is
> > used to shape traffic with tc.
> >
> > Please note this regression was already reported as BZ [1] and as a letter to
> > ML [2], but got neither attention nor resolution. It is reproducible for (not
> > only) me on my home router since v4.11 till v4.13.1 incl.
> >
> > Please advise on how to deal with it. I'll provide any additional info if
> > necessary, also ready to test patches if any.
> >
> > Thanks.
> >
> > [1] https://bugzilla.kernel.org/show_bug.cgi?id=195835
> > [2] https://www.spinics.net/lists/netdev/msg436158.html
>
> We're experiencing the same problems on some machines in our fleet.
> Exactly the same symptoms: tcp_fastretrans_alert() warnings and
> sometimes panics in tcp_sacktag_walk().
>
> Here is an example of a backtrace with the panic log:
do you still see the panics if you disable RACK?
sysctl net.ipv4.tcp_recovery=0?

also have you experience any sack reneg? could you post the output of
' nstat |grep -i TCP' thanks


>
> 978.210080]  fuse
> [973978.214099]  sg
> [973978.217789]  loop
> [973978.221829]  efivarfs
> [973978.226544]  autofs4
> [973978.231109] CPU: 12 PID: 3806320 Comm: ld:srv:W20 Tainted: G        W       4.11.3-7_fbk1_1174_ga56eebf #7
> [973978.250563] Hardware name: Wiwynn Leopard-Orv2/Leopard-DDR BW, BIOS LBM06   10/28/2016
> [973978.266558] Call Trace:
> [973978.271615]  <IRQ>
> [973978.275817]  dump_stack+0x4d/0x70
> [973978.282626]  __warn+0xd3/0xf0
> [973978.288727]  warn_slowpath_null+0x1e/0x20
> [973978.296910]  tcp_fastretrans_alert+0xacf/0xbd0
> [973978.305974]  tcp_ack+0xbce/0x1390
> [973978.312770]  tcp_rcv_established+0x1ce/0x740
> [973978.321488]  tcp_v6_do_rcv+0x195/0x440
> [973978.329166]  tcp_v6_rcv+0x94c/0x9f0
> [973978.336323]  ip6_input_finish+0xea/0x430
> [973978.344330]  ip6_input+0x32/0xa0
> [973978.350968]  ? ip6_rcv_finish+0xa0/0xa0
> [973978.358799]  ip6_rcv_finish+0x4b/0xa0
> [973978.366289]  ipv6_rcv+0x2ec/0x4f0
> [973978.373082]  ? ip6_make_skb+0x1c0/0x1c0
> [973978.380919]  __netif_receive_skb_core+0x2d5/0x9a0
> [973978.390505]  __netif_receive_skb+0x16/0x70
> [973978.398875]  netif_receive_skb_internal+0x23/0x80
> [973978.408462]  napi_gro_receive+0x113/0x1d0
> [973978.416657]  mlx5e_handle_rx_cqe_mpwrq+0x5b6/0x8d0
> [973978.426398]  mlx5e_poll_rx_cq+0x7c/0x7f0
> [973978.434405]  mlx5e_napi_poll+0x8c/0x380
> [973978.442238]  ? mlx5_cq_completion+0x54/0xb0
> [973978.450770]  net_rx_action+0x22e/0x380
> [973978.458447]  __do_softirq+0x106/0x2e8
> [973978.465950]  irq_exit+0xb0/0xc0
> [973978.472396]  do_IRQ+0x4f/0xd0
> [973978.478495]  common_interrupt+0x86/0x86
> [973978.486329] RIP: 0033:0x7f8dee58d8ae
> [973978.493642] RSP: 002b:00007f8cb925f078 EFLAGS: 00000206
> [973978.504251]  ORIG_RAX: ffffffffffffff5f
> [973978.512085] RAX: 00007f8cb925f1a8 RBX: 0000000048000000 RCX: 00007f8764bd6a80
> [973978.526508] RDX: 00000000000001ba RSI: 00007f7cb4ca3410 RDI: 00007f7cb4ca3410
> [973978.540927] RBP: 000000000000000d R08: 00007f8764bd6b00 R09: 00007f8764bd6b80
> [973978.555347] R10: 0000000000002400 R11: 00007f8dee58e240 R12: d3273c84146e8c29
> [973978.569766] R13: 9dac83ddf04c235c R14: 00007f7cb4ca33b0 R15: 00007f7cb4ca4f50
> [973978.584189]  </IRQ>
> [973978.588650] ---[ end trace 5d1c83e12a57d039 ]---
> [973995.178183] BUG: unable to handle kernel
> [973995.186385] NULL pointer dereference
> [973995.193692]  at 0000000000000028
> [973995.200323] IP: tcp_sacktag_walk+0x2b7/0x460
> [973995.209032] PGD 102d856067
> [973995.214789] PUD fded0d067
> [973995.220385] PMD 0
> [973995.224577]
> [973995.227732] ------------[ cut here ]------------
> [973995.237128] Oops: 0000 [#1] SMP
> [973995.243575] Modules linked in:
> [973995.249868]  mptctl
> [973995.254251]  mptbase
> [973995.258792]  xt_DSCP
> [973995.263331]  xt_set
> [973995.267698]  ip_set_hash_ip
> [973995.273452]  cls_u32
> [973995.277993]  sch_sfq
> [973995.282535]  cls_fw
> [973995.286904]  sch_htb
> [973995.291444]  mpt3sas
> [973995.295982]  raid_class
> [973995.301044]  ip6table_mangle
> [973995.306973]  iptable_mangle
> [973995.312726]  cls_bpf
> [973995.317268]  tcp_diag
> [973995.321983]  udp_diag
> [973995.326697]  inet_diag
> [973995.331585]  ip6table_filter
> [973995.337513]  xt_NFLOG
> [973995.342226]  nfnetlink_log
> [973995.347807]  xt_comment
> [973995.352866]  xt_statistic
> [973995.358276]  iptable_filter
> [973995.364029]  xt_mark
> [973995.368572]  sb_edac
> [973995.373113]  edac_core
> [973995.378001]  x86_pkg_temp_thermal
> [973995.384795]  intel_powerclamp
> [973995.390897]  coretemp
> [973995.395608]  kvm_intel
> [973995.400498]  kvm
> [973995.404345]  irqbypass
> [973995.409235]  ses
> [973995.413078]  iTCO_wdt
> [973995.417794]  iTCO_vendor_support
> [973995.424415]  enclosure
> [973995.429301]  lpc_ich
> [973995.433843]  scsi_transport_sas
> [973995.440292]  mfd_core
> [973995.445007]  efivars
> [973995.449548]  ipmi_si
> [973995.454087]  ipmi_devintf
> [973995.459496]  i2c_i801
> [973995.464209]  ipmi_msghandler
> [973995.470138]  acpi_cpufreq
> [973995.475545]  button
> [973995.479914]  sch_fq_codel
> [973995.485319]  nfsd
> [973995.489341]  auth_rpcgss
> [973995.494573]  nfs_acl
> [973995.499114]  oid_registry
> [973995.504524]  lockd
> [973995.508717]  grace
> [973995.512912]  sunrpc
> [973995.517280]  megaraid_sas
> [973995.522689]  fuse
> [973995.526709]  sg
> [973995.530382]  loop
> [973995.534405]  efivarfs
> [973995.539118]  autofs4
> [973995.543660] CPU: 19 PID: 3806297 Comm: ld:srv:W0 Tainted: G        W       4.11.3-7_fbk1_1174_ga56eebf #7
> [973995.562936] Hardware name: Wiwynn Leopard-Orv2/Leopard-DDR BW, BIOS LBM06   10/28/2016
> [973995.578914] task: ffff880129e5c380 task.stack: ffffc900210cc000
> [973995.590914] RIP: 0010:tcp_sacktag_walk+0x2b7/0x460
> [973995.600648] RSP: 0000:ffff88203ef438e8 EFLAGS: 00010207
> [973995.611254] RAX: 0000000000000001 RBX: 0000000000000000 RCX: 000000004e4ec474
> [973995.625677] RDX: 000000004e4ec2ad RSI: ffff8810361faa00 RDI: ffff881ffecf8840
> [973995.640102] RBP: ffff88203ef43940 R08: 0000000045729921 R09: 0000000000000000
> [973995.654519] R10: 00000000000085d6 R11: ffff881ffecf8998 R12: ffff881ffecf8840
> [973995.668938] R13: ffff88203ef43a48 R14: 0000000000000000 R15: ffff881ffecf8998
> [973995.683362] FS:  00007f8cc8cf7700(0000) GS:ffff88203ef40000(0000) knlGS:0000000000000000
> [973995.699686] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [973995.711331] CR2: 0000000000000028 CR3: 0000000104c1b000 CR4: 00000000003406e0
> [973995.725755] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [973995.740175] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> [973995.754595] Call Trace:
> [973995.759652]  <IRQ>
> [973995.763855]  ? kprobe_perf_func+0x28/0x210
> [973995.772210]  tcp_sacktag_write_queue+0x5ff/0x9e0
> [973995.781615]  tcp_ack+0x677/0x1390
> [973995.788408]  tcp_rcv_established+0x1ce/0x740
> [973995.797112]  tcp_v6_do_rcv+0x195/0x440
> [973995.804767]  tcp_v6_rcv+0x94c/0x9f0
> [973995.811911]  ip6_input_finish+0xea/0x430
> [973995.819917]  ip6_input+0x32/0xa0
> [973995.826538]  ? ip6_rcv_finish+0xa0/0xa0
> [973995.834373]  ip6_rcv_finish+0x4b/0xa0
> [973995.841859]  ipv6_rcv+0x2ec/0x4f0
> [973995.848653]  ? ip6_fragment+0x9f0/0x9f0
> [973995.856489]  ? ip6_make_skb+0x1c0/0x1c0
> [973995.864323]  __netif_receive_skb_core+0x2d5/0x9a0
> [973995.873891]  __netif_receive_skb+0x16/0x70
> [973995.882244]  netif_receive_skb_internal+0x23/0x80
> [973995.891812]  napi_gro_receive+0x113/0x1d0
> [973995.899993]  mlx5e_handle_rx_cqe_mpwrq+0x5b6/0x8d0
> [973995.909735]  mlx5e_poll_rx_cq+0x7c/0x7f0
> [973995.917740]  mlx5e_napi_poll+0x8c/0x380
> [973995.925576]  ? mlx5_cq_completion+0x54/0xb0
> [973995.934101]  net_rx_action+0x22e/0x380
> [973995.941764]  __do_softirq+0x106/0x2e8
> [973995.949255]  irq_exit+0xb0/0xc0
> [973995.955696]  do_IRQ+0x4f/0xd0
> [973995.961798]  common_interrupt+0x86/0x86
> [973995.969634] RIP: 0033:0x7f8dec97a557
> [973995.976945] RSP: 002b:00007f8cc8cf2f48 EFLAGS: 00000206
> [973995.987552]  ORIG_RAX: ffffffffffffff20
> [973995.995386] RAX: 00007f7fa9e15230 RBX: 00007f8c2153a160 RCX: 00007f7fa9e15230
> [973996.009810] RDX: 0000000000000000 RSI: 00007f8cc8cf3040 RDI: 00007f8c204f90c0
> [973996.024230] RBP: 00007f8cc8cf2f80 R08: 0000000000000001 R09: 000131aa4c002c01
> [973996.038652] R10: 0000000000000000 R11: 0000000000000001 R12: 00007f8c2153a170
> [973996.053073] R13: 00007f8cc8cf3040 R14: 00007f8c204f90c0 R15: 00007f8c2153a120
> [973996.067494]  </IRQ>
> [973996.071858] Code:
> [973996.076051] b9
> [973996.079723] 01
> [973996.083383] 00
> [973996.087056] 00
> [973996.090730] 00
> [973996.094388] 85
> [973996.098062] c0
> [973996.101738] 0f
> [973996.105410] 8e
> [973996.109087] da
> [973996.112759] fd
> [973996.116433] ff
> [973996.120109] ff
> [973996.123783] 85
> [973996.127457] c0
> [973996.131132] 75
> [973996.134806] 28
> [973996.138481] 0f
> [973996.142156] b7
> [973996.145831] 43
> [973996.149504] 30
> [973996.153180] 41
> [973996.156835] 01
> [973996.160511] 45
> [973996.164168] 04
> [973996.167843] 48
> [973996.171517] 8b
> [973996.175190] 1b
> [973996.178848] 4c
> [973996.182521] 39
> [973996.186198] fb
> [973996.189872] 74
> [973996.193529] 8c
> [973996.197202] 49
> [973996.200877] 3b
> [973996.204534] 9c
> [973996.208209] 24
> [973996.211883] 50
> [973996.215559] 01
> [973996.219215] 00
> [973996.222889] 00
> [973996.226562] 74
> [973996.230221] c1
> [973996.233894] <8b>
> [973996.237916] 43
> [973996.241590] 28
> [973996.245264] 3b
> [973996.248921] 45
> [973996.252596] d4
> [973996.256271] 0f
> [973996.259929] 88
> [973996.263601] 9f
> [973996.267276] fd
> [973996.270935] ff
> [973996.274592] ff
> [973996.278267] eb
> [973996.281938] b3
> [973996.285614] 48
> [973996.289289] 8d
> [973996.292964] 43
> [973996.296638] 10
> [973996.300296] 8b
> [973996.303969] 4b
> [973996.307642] 28
> [973996.311325] RIP: tcp_sacktag_walk+0x2b7/0x460 RSP: ffff88203ef438e8
> [973996.324007] ------------[ cut here ]------------
> [973996.333399] CR2: 0000000000000028
> [973996.340218] ---[ end trace 5d1c83e12a57d03a ]---
> [973996.349605] Kernel panic - not syncing: Fatal exception in interrupt
> [973996.362521] Kernel Offset: disabled
> TBOOT: wait until all APs ready for txt shutdown
> TBOOT: IA32_FEATURE_CONTROL_MSR: 0000ff07
> TBOOT: CPU is SMX-capable
> TBOOT: CPU is VMX-capable
> TBOOT: SMX is enabled
> TBOOT: TXT chipset and all needed capabilities present
> TBOOT: TPM: Pcr 17 extend, return value = 0000003D
> TBOOT: TPM: Pcr 18 extend, return value = 0000003D
> TBOOT: TPM: Pcr 19 extend, return value = 0000003D
> TBOOT: cap'ed dynamic PCRs
> TBOOT: waiting for APs (0) to exit guests...
> TBOOT: .
> TBOOT:
> TBOOT: all APs exited guests
> TBOOT: calling txt_shutdown on AP
>
>
> Thanks!

^ permalink raw reply

* [PATCH 44/64] drivers: net: pxa168: use setup_timer() helper.
From: Allen Pais @ 2017-09-21 17:05 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, m.grzeschik, dmitry.tarnyagin, wg, mkl, mark.einon,
	linux, pcnet32, f.fainelli, bcm-kernel-feedback-list, venza, ajk,
	jes, romieu, khc, simon, davem, linux-can, adi-buildroot-devel,
	Allen Pais
In-Reply-To: <1506013525-29291-1-git-send-email-allen.lkml@gmail.com>

    Use setup_timer function instead of initializing timer with the
    function and data fields.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/net/ethernet/marvell/pxa168_eth.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 9937249..91b1c15 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1496,9 +1496,8 @@ static int pxa168_eth_probe(struct platform_device *pdev)
 	netif_napi_add(dev, &pep->napi, pxa168_rx_poll, pep->rx_ring_size);
 
 	memset(&pep->timeout, 0, sizeof(struct timer_list));
-	init_timer(&pep->timeout);
-	pep->timeout.function = rxq_refill_timer_wrapper;
-	pep->timeout.data = (unsigned long)pep;
+	setup_timer(&pep->timeout, rxq_refill_timer_wrapper,
+		    (unsigned long)pep);
 
 	pep->smi_bus = mdiobus_alloc();
 	if (!pep->smi_bus) {
-- 
2.7.4

^ permalink raw reply related

* [PATCH 48/64] drivers: net: amd: use setup_timer() helper.
From: Allen Pais @ 2017-09-21 17:05 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, m.grzeschik, dmitry.tarnyagin, wg, mkl, mark.einon,
	linux, pcnet32, f.fainelli, bcm-kernel-feedback-list, venza, ajk,
	jes, romieu, khc, simon, davem, linux-can, adi-buildroot-devel,
	Allen Pais
In-Reply-To: <1506013525-29291-1-git-send-email-allen.lkml@gmail.com>

    Use setup_timer function instead of initializing timer with the
    function and data fields.

Signed-off-by: Allen Pais <allen.lkml@gmail.com>
---
 drivers/net/ethernet/amd/a2065.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c
index e22f976..998d30e 100644
--- a/drivers/net/ethernet/amd/a2065.c
+++ b/drivers/net/ethernet/amd/a2065.c
@@ -733,10 +733,9 @@ static int a2065_init_one(struct zorro_dev *z,
 	dev->watchdog_timeo = 5*HZ;
 	dev->dma = 0;
 
-	init_timer(&priv->multicast_timer);
-	priv->multicast_timer.data = (unsigned long) dev;
-	priv->multicast_timer.function =
-		(void (*)(unsigned long))lance_set_multicast;
+	setup_timer(&priv->multicast_timer,
+		    (void(*)(unsigned long))lance_set_multicast,
+		    (unsigned long)dev);
 
 	err = register_netdev(dev);
 	if (err) {
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH net] net: prevent dst uses after free
From: Martin KaFai Lau @ 2017-09-21 17:12 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Paweł Staszewski, Wei Wang, Cong Wang,
	Linux Kernel Network Developers, Eric Dumazet
In-Reply-To: <1506010546.29839.148.camel@edumazet-glaptop3.roam.corp.google.com>

On Thu, Sep 21, 2017 at 04:15:46PM +0000, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
> 
> In linux-4.13, Wei worked hard to convert dst to a traditional
> refcounted model, removing GC.
> 
> We now want to make sure a dst refcount can not transition from 0 back
> to 1.
> 
> The problem here is that input path attached a not refcounted dst to an
> skb. Then later, because packet is forwarded and hits skb_dst_force()
> before exiting RCU section, we might try to take a refcount on one dst
> that is about to be freed, if another cpu saw 1 -> 0 transition in
> dst_release() and queued the dst for freeing after one RCU grace period.
> 
> Lets unify skb_dst_force() and skb_dst_force_safe(), since we should
> always perform the complete check against dst refcount, and not assume
> it is not zero.
Acked-by: Martin KaFai Lau <kafai@fb.com>

> 
> Bugzilla : https://bugzilla.kernel.org/show_bug.cgi?id=197005
> 
> [  989.919496]  skb_dst_force+0x32/0x34
> [  989.919498]  __dev_queue_xmit+0x1ad/0x482
> [  989.919501]  ? eth_header+0x28/0xc6
> [  989.919502]  dev_queue_xmit+0xb/0xd
> [  989.919504]  neigh_connected_output+0x9b/0xb4
> [  989.919507]  ip_finish_output2+0x234/0x294
> [  989.919509]  ? ipt_do_table+0x369/0x388
> [  989.919510]  ip_finish_output+0x12c/0x13f
> [  989.919512]  ip_output+0x53/0x87
> [  989.919513]  ip_forward_finish+0x53/0x5a
> [  989.919515]  ip_forward+0x2cb/0x3e6
> [  989.919516]  ? pskb_trim_rcsum.part.9+0x4b/0x4b
> [  989.919518]  ip_rcv_finish+0x2e2/0x321
> [  989.919519]  ip_rcv+0x26f/0x2eb
> [  989.919522]  ? vlan_do_receive+0x4f/0x289
> [  989.919523]  __netif_receive_skb_core+0x467/0x50b
> [  989.919526]  ? tcp_gro_receive+0x239/0x239
> [  989.919529]  ? inet_gro_receive+0x226/0x238
> [  989.919530]  __netif_receive_skb+0x4d/0x5f
> [  989.919532]  netif_receive_skb_internal+0x5c/0xaf
> [  989.919533]  napi_gro_receive+0x45/0x81
> [  989.919536]  ixgbe_poll+0xc8a/0xf09
> [  989.919539]  ? kmem_cache_free_bulk+0x1b6/0x1f7
> [  989.919540]  net_rx_action+0xf4/0x266
> [  989.919543]  __do_softirq+0xa8/0x19d
> [  989.919545]  irq_exit+0x5d/0x6b
> [  989.919546]  do_IRQ+0x9c/0xb5
> [  989.919548]  common_interrupt+0x93/0x93
> [  989.919548]  </IRQ>
> 
> 
> Similarly dst_clone() can use dst_hold() helper to have additional
> debugging, as a follow up to commit 44ebe79149ff ("net: add debug
> atomic_inc_not_zero() in dst_hold()")
> 
> In net-next we will convert dst atomic_t to refcount_t for peace of
> mind.
> 
> Fixes: a4c2fd7f7891 ("net: remove DST_NOCACHE flag")
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Wei Wang <weiwan@google.com>
> Reported-by: Paweł Staszewski <pstaszewski@itcare.pl>
> Bisected-by: Paweł Staszewski <pstaszewski@itcare.pl>
> ---
>  include/net/dst.h   |   22 ++++------------------
>  include/net/route.h |    2 +-
>  include/net/sock.h  |    2 +-
>  3 files changed, 6 insertions(+), 20 deletions(-)
> 
> diff --git a/include/net/dst.h b/include/net/dst.h
> index 93568bd0a3520bb7402f04d90cf04ac99c81cfbe..06a6765da074449e6f1fe42ee05e711e898ad372 100644
> --- a/include/net/dst.h
> +++ b/include/net/dst.h
> @@ -271,7 +271,7 @@ static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
>  static inline struct dst_entry *dst_clone(struct dst_entry *dst)
>  {
>  	if (dst)
> -		atomic_inc(&dst->__refcnt);
> +		dst_hold(dst);
>  	return dst;
>  }
>  
> @@ -311,21 +311,6 @@ static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb
>  	__skb_dst_copy(nskb, oskb->_skb_refdst);
>  }
>  
> -/**
> - * skb_dst_force - makes sure skb dst is refcounted
> - * @skb: buffer
> - *
> - * If dst is not yet refcounted, let's do it
> - */
> -static inline void skb_dst_force(struct sk_buff *skb)
> -{
> -	if (skb_dst_is_noref(skb)) {
> -		WARN_ON(!rcu_read_lock_held());
> -		skb->_skb_refdst &= ~SKB_DST_NOREF;
> -		dst_clone(skb_dst(skb));
> -	}
> -}
> -
>  /**
>   * dst_hold_safe - Take a reference on a dst if possible
>   * @dst: pointer to dst entry
> @@ -339,16 +324,17 @@ static inline bool dst_hold_safe(struct dst_entry *dst)
>  }
>  
>  /**
> - * skb_dst_force_safe - makes sure skb dst is refcounted
> + * skb_dst_force - makes sure skb dst is refcounted
>   * @skb: buffer
>   *
>   * If dst is not yet refcounted and not destroyed, grab a ref on it.
>   */
> -static inline void skb_dst_force_safe(struct sk_buff *skb)
> +static inline void skb_dst_force(struct sk_buff *skb)
>  {
>  	if (skb_dst_is_noref(skb)) {
>  		struct dst_entry *dst = skb_dst(skb);
>  
> +		WARN_ON(!rcu_read_lock_held());
>  		if (!dst_hold_safe(dst))
>  			dst = NULL;
>  
> diff --git a/include/net/route.h b/include/net/route.h
> index 1b09a9368c68d46f0c5ee8ce3cefe566000c1ec1..57dfc6850d378e4b96f13b140eef554d66c24cdf 100644
> --- a/include/net/route.h
> +++ b/include/net/route.h
> @@ -190,7 +190,7 @@ static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
>  	rcu_read_lock();
>  	err = ip_route_input_noref(skb, dst, src, tos, devin);
>  	if (!err) {
> -		skb_dst_force_safe(skb);
> +		skb_dst_force(skb);
>  		if (!skb_dst(skb))
>  			err = -EINVAL;
>  	}
> diff --git a/include/net/sock.h b/include/net/sock.h
> index 03a362568357acc7278a318423dd3873103f90ca..a6b9a8d1a6df3f72df8f1aac0f577257fa6452d0 100644
> --- a/include/net/sock.h
> +++ b/include/net/sock.h
> @@ -856,7 +856,7 @@ void sk_stream_write_space(struct sock *sk);
>  static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
>  {
>  	/* dont let skb dst not refcounted, we are going to leave rcu lock */
> -	skb_dst_force_safe(skb);
> +	skb_dst_force(skb);
>  
>  	if (!sk->sk_backlog.tail)
>  		sk->sk_backlog.head = skb;
> 
> 

^ permalink raw reply

* Re: [PATCH net-next 2/7] rtnetlink: add helper to put master ifindex
From: David Ahern @ 2017-09-21 17:16 UTC (permalink / raw)
  To: Florian Westphal, netdev
In-Reply-To: <20170921165902.10746-3-fw@strlen.de>

On 9/21/17 10:58 AM, Florian Westphal wrote:

> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index a78fd61da0ec..c801212ee40e 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -1307,6 +1307,31 @@ static u32 rtnl_get_event(unsigned long event)
>  	return rtnl_event_type;
>  }
>  
> +static int put_master_ifindex(struct sk_buff *skb, struct net_device *dev)
> +{
> +	const struct net_device *upper_dev;
> +	int ret = 0;
> +
> +	rcu_read_lock();
> +
> +	upper_dev = netdev_master_upper_dev_get_rcu(dev);
> +	if (upper_dev)
> +		ret = nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex);
> +
> +	rcu_read_unlock();
> +	return ret;
> +}
> +
> +static int nla_put_iflink(struct sk_buff *skb, const struct net_device *dev)
> +{
> +	int ifindex = dev_get_iflink(dev);
> +
> +	if (dev->ifindex == ifindex)
> +		return 0;
> +
> +	return nla_put_u32(skb, IFLA_LINK, ifindex);
> +}
> +
>  static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
>  			    int type, u32 pid, u32 seq, u32 change,
>  			    unsigned int flags, u32 ext_filter_mask,

Subject references only change for master index, put the patch is
converting 2 things to helpers.

^ permalink raw reply

* Re: [PATCH net-next 5/7] rtnetlink: add helper to dump vf information
From: David Ahern @ 2017-09-21 17:17 UTC (permalink / raw)
  To: Florian Westphal, netdev
In-Reply-To: <20170921165902.10746-6-fw@strlen.de>

On 9/21/17 10:59 AM, Florian Westphal wrote:
> similar to earlier patches, split out more parts of this function to
> better see what is happening and where we assume rtnl is locked.
> 
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>  net/core/rtnetlink.c | 80 ++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 50 insertions(+), 30 deletions(-)
> 
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index 1af3ef7f329d..7503021fe308 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -1211,6 +1211,36 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
>  	return -EMSGSIZE;
>  }
>  
> +static noinline_for_stack int rtnl_fill_vf(struct sk_buff *skb,
> +					   struct net_device *dev,
> +					   u32 ext_filter_mask)
> +{
> +	struct nlattr *vfinfo;
> +	int i, num_vfs;
> +
> +	if (!dev->dev.parent || ((ext_filter_mask & RTEXT_FILTER_VF) == 0))
> +		return 0;
> +
> +	num_vfs = dev_num_vf(dev->dev.parent);
> +	if (nla_put_u32(skb, IFLA_NUM_VF, num_vfs))
> +		return -EMSGSIZE;
> +
> +	if (!dev->netdev_ops->ndo_get_vf_config)
> +		return 0;
> +
> +	vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST);
> +	if (!vfinfo)
> +		return -EMSGSIZE;
> +
> +	for (i = 0; i < num_vfs; i++) {
> +		if (rtnl_fill_vfinfo(skb, dev, i, vfinfo))
> +			return -EMSGSIZE;
> +	}
> +
> +	nla_nest_end(skb, vfinfo);
> +	return 0;
> +}
> +
>  static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
>  {
>  	struct rtnl_link_ifmap map;
> @@ -1355,6 +1385,23 @@ static int noinline nla_put_ifalias(struct sk_buff *skb, struct net_device *dev)
>  	return 0;
>  }
>  
> +static int noinline rtnl_fill_link_netnsid(struct sk_buff *skb,
> +				  const struct net_device *dev)
> +{
> +	if (dev->rtnl_link_ops && dev->rtnl_link_ops->get_link_net) {
> +		struct net *link_net = dev->rtnl_link_ops->get_link_net(dev);
> +
> +		if (!net_eq(dev_net(dev), link_net)) {
> +			int id = peernet2id_alloc(dev_net(dev), link_net);
> +
> +			if (nla_put_s32(skb, IFLA_LINK_NETNSID, id))
> +				return -EMSGSIZE;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,

Similarly for this patch -- subject references vf helper yet the code
changes flips netnsid as well.

^ permalink raw reply

* Re: [net-next v3] bridge: trigger RTM_NEWLINK when interface is modified by bridge ioctl
From: Roopa Prabhu @ 2017-09-21 17:20 UTC (permalink / raw)
  To: David Ahern
  Cc: Vincent Bernat, Stephen Hemminger, David Miller, bridge,
	netdev@vger.kernel.org
In-Reply-To: <0cdf06b9-e67d-c035-e0f1-c4eb143bf631@gmail.com>

On Thu, Sep 21, 2017 at 9:43 AM, David Ahern <dsahern@gmail.com> wrote:
> On 9/21/17 4:05 AM, Vincent Bernat wrote:
>> Currently, there is a difference in netlink events received when an
>> interface is modified through bridge ioctl() or through netlink. This
>> patch generates additional events when an interface is added to or
>> removed from a bridge via ioctl().
>>
>> When adding then removing an interface from a bridge with netlink, we
>> get:
>>
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UNKNOWN group default
>>     link/ether 9e:da:60:ee:cf:c8 brd ff:ff:ff:ff:ff:ff
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UNKNOWN group default
>>     link/ether 9e:da:60:ee:cf:c8 brd ff:ff:ff:ff:ff:ff
>>
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UNKNOWN group default
>>     link/ether 9e:da:60:ee:cf:c8 brd ff:ff:ff:ff:ff:ff
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> Deleted 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
>>     link/ether 9e:da:60:ee:cf:c8 brd ff:ff:ff:ff:ff:ff
>>
>> When using ioctl():
>>
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UNKNOWN group default
>>     link/ether 9e:da:60:ee:cf:c8 brd ff:ff:ff:ff:ff:ff
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UNKNOWN group default
>>     link/ether 9e:da:60:ee:cf:c8 brd ff:ff:ff:ff:ff:ff
>>
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UNKNOWN group default
>>     link/ether 9e:da:60:ee:cf:c8 brd ff:ff:ff:ff:ff:ff
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> Deleted 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master bridge0 state UNKNOWN
>>     link/ether 9e:da:60:ee:cf:c8
>> 5: dummy1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
>>     link/ether 9e:da:60:ee:cf:c8 brd ff:ff:ff:ff:ff:ff
>>
>> Without this patch, the last netlink notification is not sent.
>>
>> Signed-off-by: Vincent Bernat <vincent@bernat.im>
>> ---
>>  net/bridge/br_ioctl.c | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
>> index 7970f8540cbb..66cd98772051 100644
>> --- a/net/bridge/br_ioctl.c
>> +++ b/net/bridge/br_ioctl.c
>> @@ -102,6 +102,9 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
>>       else
>>               ret = br_del_if(br, dev);
>>
>> +     if (!ret)
>> +             rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_MASTER, GFP_KERNEL);
>> +
>>       return ret;
>>  }
>>
>>
>
> Agreed that this is needed for userspace to know about the master change
> when done through ioctl. The bridge code is emitting a lot of what
> appears to be redundant messages for both paths (netlink and ioctl).
>
> Reviewed-by: David Ahern <dsahern@gmail.com>
>


this patch seems fine...but ideally I would have assumed
netdev_upper_dev_unlink which
is eventually called in both paths would generate the RTN_NEWLINK
IFF_MASTER in response
to the NETDEV_CHANGEUPPER notifier. If we add it there now, it might
need some more fixes
to not generate redundant notifications for the netlink case.

^ permalink raw reply

* Re: [PATCH net-next 7/7] rtnetlink: rtnl_have_link_slave_info doesn't need rtnl
From: David Ahern @ 2017-09-21 17:24 UTC (permalink / raw)
  To: Florian Westphal, netdev
In-Reply-To: <20170921165902.10746-8-fw@strlen.de>

On 9/21/17 10:59 AM, Florian Westphal wrote:
> @@ -539,6 +543,8 @@ static int rtnl_link_slave_info_fill(struct sk_buff *skb,
>  	struct nlattr *slave_data;
>  	int err;
>  
> +	ASSERT_RTNL();
> +
>  	master_dev = netdev_master_upper_dev_get((struct net_device *) dev);
>  	if (!master_dev)
>  		return 0;
> @@ -570,6 +576,8 @@ static int rtnl_link_info_fill(struct sk_buff *skb,
>  	struct nlattr *data;
>  	int err;
>  
> +	ASSERT_RTNL();
> +
>  	if (!ops)
>  		return 0;
>  	if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0)
> @@ -600,6 +608,8 @@ static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
>  	struct nlattr *linkinfo;
>  	int err = -EMSGSIZE;
>  
> +	ASSERT_RTNL();
> +
>  	linkinfo = nla_nest_start(skb, IFLA_LINKINFO);
>  	if (linkinfo == NULL)
>  		goto out;
> 


Since rtnl_link_slave_info_fill and rtnl_link_info_fill are only called
by rtnl_link_fill and rtnl_link_fill is only called rtnl_fill_ifinfo
which as the ASSERT_RTNL why add to these lower functions as well?

^ permalink raw reply

* Re: [PATCH net-next 5/7] rtnetlink: add helper to dump vf information
From: Florian Westphal @ 2017-09-21 17:25 UTC (permalink / raw)
  To: David Ahern; +Cc: Florian Westphal, netdev
In-Reply-To: <bdc39ebf-e934-16ce-0834-e0795774a656@gmail.com>

David Ahern <dsahern@gmail.com> wrote:
> On 9/21/17 10:59 AM, Florian Westphal wrote:
> > similar to earlier patches, split out more parts of this function to
> > better see what is happening and where we assume rtnl is locked.

[..]

> > +static noinline_for_stack int rtnl_fill_vf(struct sk_buff *skb,
> > +					   struct net_device *dev,
> > +					   u32 ext_filter_mask)
[..]
> > +static int noinline rtnl_fill_link_netnsid(struct sk_buff *skb,
> > +				  const struct net_device *dev)
[..]
> >  static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
> 
> Similarly for this patch -- subject references vf helper yet the code
> changes flips netnsid as well.

Right, anomly due to improper squash-merge.
I'll send a v2 tomorrow (giving more time for others to comment).

^ permalink raw reply

* Re: [net-next v3] bridge: trigger RTM_NEWLINK when interface is modified by bridge ioctl
From: David Ahern @ 2017-09-21 17:29 UTC (permalink / raw)
  To: Roopa Prabhu, David Ahern
  Cc: netdev@vger.kernel.org, bridge, Vincent Bernat, David Miller
In-Reply-To: <CAJieiUjqttMeC24CzDa8Y8g=opRKoa2hbG2Cb+78u632vA3uqw@mail.gmail.com>

On 9/21/17 11:20 AM, Roopa Prabhu wrote:
> this patch seems fine...but ideally I would have assumed
> netdev_upper_dev_unlink which
> is eventually called in both paths would generate the RTN_NEWLINK
> IFF_MASTER in response
> to the NETDEV_CHANGEUPPER notifier. If we add it there now, it might
> need some more fixes
> to not generate redundant notifications for the netlink case.

Agreed and it is another pandora's box

^ permalink raw reply

* Re: [PATCH net-next 7/7] rtnetlink: rtnl_have_link_slave_info doesn't need rtnl
From: Florian Westphal @ 2017-09-21 17:31 UTC (permalink / raw)
  To: David Ahern; +Cc: Florian Westphal, netdev
In-Reply-To: <b645a22f-9153-b327-8995-2b140cff59a0@gmail.com>

David Ahern <dsahern@gmail.com> wrote:
> On 9/21/17 10:59 AM, Florian Westphal wrote:
> > @@ -539,6 +543,8 @@ static int rtnl_link_slave_info_fill(struct sk_buff *skb,
> >  	struct nlattr *slave_data;
> >  	int err;
> >  
> > +	ASSERT_RTNL();
> > +
[..]
master_dev = netdev_master_upper_dev_get((struct net_device *) dev);

> Since rtnl_link_slave_info_fill and rtnl_link_info_fill are only called
> by rtnl_link_fill and rtnl_link_fill is only called rtnl_fill_ifinfo
> which as the ASSERT_RTNL why add to these lower functions as well?

I'll remove this patch in v2 and will hold it back in my private queue;
these serve more as a reminder/TODO for myself rather than anything else.

^ permalink raw reply

* Re: [PATCH iproute2 master 1/2] json: move json printer to common library
From: Julien Fortin @ 2017-09-21 17:47 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: Stephen Hemminger, ast, netdev
In-Reply-To: <635a857b7b32cd0df79805f8e32b20a2674a675d.1505956723.git.daniel@iogearbox.net>

On Thu, Sep 21, 2017 at 1:42 AM, Daniel Borkmann <daniel@iogearbox.net> wrote:
> Move the json printer which is based on json writer into the
> iproute2 library, so it can be used by library code and tools
> other than ip. Should probably have been done from the beginning
> like that given json writer is in the library already anyway.
> No functional changes.
>
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Julien Fortin <julien@cumulusnetworks.com>
> ---
>  include/json_print.h |  71 ++++++++++++++++
>  ip/Makefile          |   2 +-
>  ip/ip_common.h       |  65 ++------------
>  ip/ip_print.c        | 233 ---------------------------------------------------
>  lib/Makefile         |   2 +-
>  lib/json_print.c     | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 312 insertions(+), 292 deletions(-)
>  create mode 100644 include/json_print.h
>  delete mode 100644 ip/ip_print.c
>  create mode 100644 lib/json_print.c
>
> diff --git a/include/json_print.h b/include/json_print.h
> new file mode 100644
> index 0000000..44cf5ac
> --- /dev/null
> +++ b/include/json_print.h
> @@ -0,0 +1,71 @@
> +/*
> + * json_print.h                "print regular or json output, based on json_writer".
> + *
> + *             This program is free software; you can redistribute it and/or
> + *             modify it under the terms of the GNU General Public License
> + *             as published by the Free Software Foundation; either version
> + *             2 of the License, or (at your option) any later version.
> + *
> + * Authors:    Julien Fortin, <julien@cumulusnetworks.com>
> + */
> +
> +#ifndef _JSON_PRINT_H_
> +#define _JSON_PRINT_H_
> +
> +#include "json_writer.h"
> +#include "color.h"
> +
> +json_writer_t *get_json_writer(void);
> +
> +/*
> + * use:
> + *      - PRINT_ANY for context based output
> + *      - PRINT_FP for non json specific output
> + *      - PRINT_JSON for json specific output
> + */
> +enum output_type {
> +       PRINT_FP = 1,
> +       PRINT_JSON = 2,
> +       PRINT_ANY = 4,
> +};
> +
> +void new_json_obj(int json, FILE *fp);
> +void delete_json_obj(void);
> +
> +bool is_json_context(void);
> +
> +void set_current_fp(FILE *fp);
> +
> +void fflush_fp(void);
> +
> +void open_json_object(const char *str);
> +void close_json_object(void);
> +void open_json_array(enum output_type type, const char *delim);
> +void close_json_array(enum output_type type, const char *delim);
> +
> +#define _PRINT_FUNC(type_name, type)                                   \
> +       void print_color_##type_name(enum output_type t,                \
> +                                    enum color_attr color,             \
> +                                    const char *key,                   \
> +                                    const char *fmt,                   \
> +                                    type value);                       \
> +                                                                       \
> +       static inline void print_##type_name(enum output_type t,        \
> +                                            const char *key,           \
> +                                            const char *fmt,           \
> +                                            type value)                \
> +       {                                                               \
> +               print_color_##type_name(t, -1, key, fmt, value);        \
> +       }
> +_PRINT_FUNC(int, int);
> +_PRINT_FUNC(bool, bool);
> +_PRINT_FUNC(null, const char*);
> +_PRINT_FUNC(string, const char*);
> +_PRINT_FUNC(uint, uint64_t);
> +_PRINT_FUNC(hu, unsigned short);
> +_PRINT_FUNC(hex, unsigned int);
> +_PRINT_FUNC(0xhex, unsigned int);
> +_PRINT_FUNC(lluint, unsigned long long int);
> +#undef _PRINT_FUNC
> +
> +#endif /* _JSON_PRINT_H_ */
> diff --git a/ip/Makefile b/ip/Makefile
> index 52c9a2e..5a1c7ad 100644
> --- a/ip/Makefile
> +++ b/ip/Makefile
> @@ -9,7 +9,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
>      link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \
>      iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \
>      iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \
> -    ipvrf.o iplink_xstats.o ipseg6.o ip_print.o
> +    ipvrf.o iplink_xstats.o ipseg6.o
>
>  RTMONOBJ=rtmon.o
>
> diff --git a/ip/ip_common.h b/ip/ip_common.h
> index efc789c..4b8b0a7 100644
> --- a/ip/ip_common.h
> +++ b/ip/ip_common.h
> @@ -1,3 +1,10 @@
> +#ifndef _IP_COMMON_H_
> +#define _IP_COMMON_H_
> +
> +#include <stdbool.h>
> +
> +#include "json_print.h"
> +
>  struct link_filter {
>         int ifindex;
>         int family;
> @@ -101,8 +108,6 @@ static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb)
>
>  extern struct rtnl_handle rth;
>
> -#include <stdbool.h>
> -
>  struct link_util {
>         struct link_util        *next;
>         const char              *id;
> @@ -141,58 +146,4 @@ int name_is_vrf(const char *name);
>
>  void print_num(FILE *fp, unsigned int width, uint64_t count);
>
> -#include "json_writer.h"
> -
> -json_writer_t   *get_json_writer(void);
> -/*
> - * use:
> - *      - PRINT_ANY for context based output
> - *      - PRINT_FP for non json specific output
> - *      - PRINT_JSON for json specific output
> - */
> -enum output_type {
> -       PRINT_FP = 1,
> -       PRINT_JSON = 2,
> -       PRINT_ANY = 4,
> -};
> -
> -void new_json_obj(int json, FILE *fp);
> -void delete_json_obj(void);
> -
> -bool is_json_context(void);
> -
> -void set_current_fp(FILE *fp);
> -
> -void fflush_fp(void);
> -
> -void open_json_object(const char *str);
> -void close_json_object(void);
> -void open_json_array(enum output_type type, const char *delim);
> -void close_json_array(enum output_type type, const char *delim);
> -
> -#include "color.h"
> -
> -#define _PRINT_FUNC(type_name, type)                                   \
> -       void print_color_##type_name(enum output_type t,                \
> -                                    enum color_attr color,             \
> -                                    const char *key,                   \
> -                                    const char *fmt,                   \
> -                                    type value);                       \
> -                                                                       \
> -       static inline void print_##type_name(enum output_type t,        \
> -                                            const char *key,           \
> -                                            const char *fmt,           \
> -                                            type value)                \
> -       {                                                               \
> -               print_color_##type_name(t, -1, key, fmt, value);        \
> -       }
> -_PRINT_FUNC(int, int);
> -_PRINT_FUNC(bool, bool);
> -_PRINT_FUNC(null, const char*);
> -_PRINT_FUNC(string, const char*);
> -_PRINT_FUNC(uint, uint64_t);
> -_PRINT_FUNC(hu, unsigned short);
> -_PRINT_FUNC(hex, unsigned int);
> -_PRINT_FUNC(0xhex, unsigned int);
> -_PRINT_FUNC(lluint, unsigned long long int);
> -#undef _PRINT_FUNC
> +#endif /* _IP_COMMON_H_ */
> diff --git a/ip/ip_print.c b/ip/ip_print.c
> deleted file mode 100644
> index 4cd6a0b..0000000
> --- a/ip/ip_print.c
> +++ /dev/null
> @@ -1,233 +0,0 @@
> -/*
> - * ip_print.c          "ip print regular or json output".
> - *
> - *             This program is free software; you can redistribute it and/or
> - *             modify it under the terms of the GNU General Public License
> - *             as published by the Free Software Foundation; either version
> - *             2 of the License, or (at your option) any later version.
> - *
> - * Authors:    Julien Fortin, <julien@cumulusnetworks.com>
> - *
> - */
> -
> -#include <stdarg.h>
> -#include <stdio.h>
> -
> -#include "utils.h"
> -#include "ip_common.h"
> -#include "json_writer.h"
> -
> -static json_writer_t *_jw;
> -static FILE *_fp;
> -
> -#define _IS_JSON_CONTEXT(type) ((type & PRINT_JSON || type & PRINT_ANY) && _jw)
> -#define _IS_FP_CONTEXT(type) (!_jw && (type & PRINT_FP || type & PRINT_ANY))
> -
> -void new_json_obj(int json, FILE *fp)
> -{
> -       if (json) {
> -               _jw = jsonw_new(fp);
> -               if (!_jw) {
> -                       perror("json object");
> -                       exit(1);
> -               }
> -               jsonw_pretty(_jw, true);
> -               jsonw_start_array(_jw);
> -       }
> -       set_current_fp(fp);
> -}
> -
> -void delete_json_obj(void)
> -{
> -       if (_jw) {
> -               jsonw_end_array(_jw);
> -               jsonw_destroy(&_jw);
> -       }
> -}
> -
> -bool is_json_context(void)
> -{
> -       return _jw != NULL;
> -}
> -
> -void set_current_fp(FILE *fp)
> -{
> -       if (!fp) {
> -               fprintf(stderr, "Error: invalid file pointer.\n");
> -               exit(1);
> -       }
> -       _fp = fp;
> -}
> -
> -json_writer_t *get_json_writer(void)
> -{
> -       return _jw;
> -}
> -
> -void open_json_object(const char *str)
> -{
> -       if (_IS_JSON_CONTEXT(PRINT_JSON)) {
> -               if (str)
> -                       jsonw_name(_jw, str);
> -               jsonw_start_object(_jw);
> -       }
> -}
> -
> -void close_json_object(void)
> -{
> -       if (_IS_JSON_CONTEXT(PRINT_JSON))
> -               jsonw_end_object(_jw);
> -}
> -
> -/*
> - * Start json array or string array using
> - * the provided string as json key (if not null)
> - * or as array delimiter in non-json context.
> - */
> -void open_json_array(enum output_type type, const char *str)
> -{
> -       if (_IS_JSON_CONTEXT(type)) {
> -               if (str)
> -                       jsonw_name(_jw, str);
> -               jsonw_start_array(_jw);
> -       } else if (_IS_FP_CONTEXT(type)) {
> -               fprintf(_fp, "%s", str);
> -       }
> -}
> -
> -/*
> - * End json array or string array
> - */
> -void close_json_array(enum output_type type, const char *str)
> -{
> -       if (_IS_JSON_CONTEXT(type)) {
> -               jsonw_pretty(_jw, false);
> -               jsonw_end_array(_jw);
> -               jsonw_pretty(_jw, true);
> -       } else if (_IS_FP_CONTEXT(type)) {
> -               fprintf(_fp, "%s", str);
> -       }
> -}
> -
> -/*
> - * pre-processor directive to generate similar
> - * functions handling different types
> - */
> -#define _PRINT_FUNC(type_name, type)                                   \
> -       void print_color_##type_name(enum output_type t,                \
> -                                    enum color_attr color,             \
> -                                    const char *key,                   \
> -                                    const char *fmt,                   \
> -                                    type value)                        \
> -       {                                                               \
> -               if (_IS_JSON_CONTEXT(t)) {                              \
> -                       if (!key)                                       \
> -                               jsonw_##type_name(_jw, value);          \
> -                       else                                            \
> -                               jsonw_##type_name##_field(_jw, key, value); \
> -               } else if (_IS_FP_CONTEXT(t)) {                         \
> -                       color_fprintf(_fp, color, fmt, value);          \
> -               }                                                       \
> -       }
> -_PRINT_FUNC(int, int);
> -_PRINT_FUNC(hu, unsigned short);
> -_PRINT_FUNC(uint, uint64_t);
> -_PRINT_FUNC(lluint, unsigned long long int);
> -#undef _PRINT_FUNC
> -
> -void print_color_string(enum output_type type,
> -                       enum color_attr color,
> -                       const char *key,
> -                       const char *fmt,
> -                       const char *value)
> -{
> -       if (_IS_JSON_CONTEXT(type)) {
> -               if (key && !value)
> -                       jsonw_name(_jw, key);
> -               else if (!key && value)
> -                       jsonw_string(_jw, value);
> -               else
> -                       jsonw_string_field(_jw, key, value);
> -       } else if (_IS_FP_CONTEXT(type)) {
> -               color_fprintf(_fp, color, fmt, value);
> -       }
> -}
> -
> -/*
> - * value's type is bool. When using this function in FP context you can't pass
> - * a value to it, you will need to use "is_json_context()" to have different
> - * branch for json and regular output. grep -r "print_bool" for example
> - */
> -void print_color_bool(enum output_type type,
> -                     enum color_attr color,
> -                     const char *key,
> -                     const char *fmt,
> -                     bool value)
> -{
> -       if (_IS_JSON_CONTEXT(type)) {
> -               if (key)
> -                       jsonw_bool_field(_jw, key, value);
> -               else
> -                       jsonw_bool(_jw, value);
> -       } else if (_IS_FP_CONTEXT(type)) {
> -               color_fprintf(_fp, color, fmt, value ? "true" : "false");
> -       }
> -}
> -
> -/*
> - * In JSON context uses hardcode %#x format: 42 -> 0x2a
> - */
> -void print_color_0xhex(enum output_type type,
> -                      enum color_attr color,
> -                      const char *key,
> -                      const char *fmt,
> -                      unsigned int hex)
> -{
> -       if (_IS_JSON_CONTEXT(type)) {
> -               SPRINT_BUF(b1);
> -
> -               snprintf(b1, sizeof(b1), "%#x", hex);
> -               print_string(PRINT_JSON, key, NULL, b1);
> -       } else if (_IS_FP_CONTEXT(type)) {
> -               color_fprintf(_fp, color, fmt, hex);
> -       }
> -}
> -
> -void print_color_hex(enum output_type type,
> -                    enum color_attr color,
> -                    const char *key,
> -                    const char *fmt,
> -                    unsigned int hex)
> -{
> -       if (_IS_JSON_CONTEXT(type)) {
> -               SPRINT_BUF(b1);
> -
> -               snprintf(b1, sizeof(b1), "%x", hex);
> -               if (key)
> -                       jsonw_string_field(_jw, key, b1);
> -               else
> -                       jsonw_string(_jw, b1);
> -       } else if (_IS_FP_CONTEXT(type)) {
> -               color_fprintf(_fp, color, fmt, hex);
> -       }
> -}
> -
> -/*
> - * In JSON context we don't use the argument "value" we simply call jsonw_null
> - * whereas FP context can use "value" to output anything
> - */
> -void print_color_null(enum output_type type,
> -                     enum color_attr color,
> -                     const char *key,
> -                     const char *fmt,
> -                     const char *value)
> -{
> -       if (_IS_JSON_CONTEXT(type)) {
> -               if (key)
> -                       jsonw_null_field(_jw, key);
> -               else
> -                       jsonw_null(_jw);
> -       } else if (_IS_FP_CONTEXT(type)) {
> -               color_fprintf(_fp, color, fmt, value);
> -       }
> -}
> diff --git a/lib/Makefile b/lib/Makefile
> index 5e9f72f..0fbdf4c 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -3,7 +3,7 @@ include ../config.mk
>  CFLAGS += -fPIC
>
>  UTILOBJ = utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o \
> -       inet_proto.o namespace.o json_writer.o \
> +       inet_proto.o namespace.o json_writer.o json_print.o \
>         names.o color.o bpf.o exec.o fs.o
>
>  NLOBJ=libgenl.o ll_map.o libnetlink.o
> diff --git a/lib/json_print.c b/lib/json_print.c
> new file mode 100644
> index 0000000..93b4119
> --- /dev/null
> +++ b/lib/json_print.c
> @@ -0,0 +1,231 @@
> +/*
> + * json_print.c                "print regular or json output, based on json_writer".
> + *
> + *             This program is free software; you can redistribute it and/or
> + *             modify it under the terms of the GNU General Public License
> + *             as published by the Free Software Foundation; either version
> + *             2 of the License, or (at your option) any later version.
> + *
> + * Authors:    Julien Fortin, <julien@cumulusnetworks.com>
> + */
> +
> +#include <stdarg.h>
> +#include <stdio.h>
> +
> +#include "utils.h"
> +#include "json_print.h"
> +
> +static json_writer_t *_jw;
> +static FILE *_fp;
> +
> +#define _IS_JSON_CONTEXT(type) ((type & PRINT_JSON || type & PRINT_ANY) && _jw)
> +#define _IS_FP_CONTEXT(type) (!_jw && (type & PRINT_FP || type & PRINT_ANY))
> +
> +void new_json_obj(int json, FILE *fp)
> +{
> +       if (json) {
> +               _jw = jsonw_new(fp);
> +               if (!_jw) {
> +                       perror("json object");
> +                       exit(1);
> +               }
> +               jsonw_pretty(_jw, true);
> +               jsonw_start_array(_jw);
> +       }
> +       set_current_fp(fp);
> +}
> +
> +void delete_json_obj(void)
> +{
> +       if (_jw) {
> +               jsonw_end_array(_jw);
> +               jsonw_destroy(&_jw);
> +       }
> +}
> +
> +bool is_json_context(void)
> +{
> +       return _jw != NULL;
> +}
> +
> +void set_current_fp(FILE *fp)
> +{
> +       if (!fp) {
> +               fprintf(stderr, "Error: invalid file pointer.\n");
> +               exit(1);
> +       }
> +       _fp = fp;
> +}
> +
> +json_writer_t *get_json_writer(void)
> +{
> +       return _jw;
> +}
> +
> +void open_json_object(const char *str)
> +{
> +       if (_IS_JSON_CONTEXT(PRINT_JSON)) {
> +               if (str)
> +                       jsonw_name(_jw, str);
> +               jsonw_start_object(_jw);
> +       }
> +}
> +
> +void close_json_object(void)
> +{
> +       if (_IS_JSON_CONTEXT(PRINT_JSON))
> +               jsonw_end_object(_jw);
> +}
> +
> +/*
> + * Start json array or string array using
> + * the provided string as json key (if not null)
> + * or as array delimiter in non-json context.
> + */
> +void open_json_array(enum output_type type, const char *str)
> +{
> +       if (_IS_JSON_CONTEXT(type)) {
> +               if (str)
> +                       jsonw_name(_jw, str);
> +               jsonw_start_array(_jw);
> +       } else if (_IS_FP_CONTEXT(type)) {
> +               fprintf(_fp, "%s", str);
> +       }
> +}
> +
> +/*
> + * End json array or string array
> + */
> +void close_json_array(enum output_type type, const char *str)
> +{
> +       if (_IS_JSON_CONTEXT(type)) {
> +               jsonw_pretty(_jw, false);
> +               jsonw_end_array(_jw);
> +               jsonw_pretty(_jw, true);
> +       } else if (_IS_FP_CONTEXT(type)) {
> +               fprintf(_fp, "%s", str);
> +       }
> +}
> +
> +/*
> + * pre-processor directive to generate similar
> + * functions handling different types
> + */
> +#define _PRINT_FUNC(type_name, type)                                   \
> +       void print_color_##type_name(enum output_type t,                \
> +                                    enum color_attr color,             \
> +                                    const char *key,                   \
> +                                    const char *fmt,                   \
> +                                    type value)                        \
> +       {                                                               \
> +               if (_IS_JSON_CONTEXT(t)) {                              \
> +                       if (!key)                                       \
> +                               jsonw_##type_name(_jw, value);          \
> +                       else                                            \
> +                               jsonw_##type_name##_field(_jw, key, value); \
> +               } else if (_IS_FP_CONTEXT(t)) {                         \
> +                       color_fprintf(_fp, color, fmt, value);          \
> +               }                                                       \
> +       }
> +_PRINT_FUNC(int, int);
> +_PRINT_FUNC(hu, unsigned short);
> +_PRINT_FUNC(uint, uint64_t);
> +_PRINT_FUNC(lluint, unsigned long long int);
> +#undef _PRINT_FUNC
> +
> +void print_color_string(enum output_type type,
> +                       enum color_attr color,
> +                       const char *key,
> +                       const char *fmt,
> +                       const char *value)
> +{
> +       if (_IS_JSON_CONTEXT(type)) {
> +               if (key && !value)
> +                       jsonw_name(_jw, key);
> +               else if (!key && value)
> +                       jsonw_string(_jw, value);
> +               else
> +                       jsonw_string_field(_jw, key, value);
> +       } else if (_IS_FP_CONTEXT(type)) {
> +               color_fprintf(_fp, color, fmt, value);
> +       }
> +}
> +
> +/*
> + * value's type is bool. When using this function in FP context you can't pass
> + * a value to it, you will need to use "is_json_context()" to have different
> + * branch for json and regular output. grep -r "print_bool" for example
> + */
> +void print_color_bool(enum output_type type,
> +                     enum color_attr color,
> +                     const char *key,
> +                     const char *fmt,
> +                     bool value)
> +{
> +       if (_IS_JSON_CONTEXT(type)) {
> +               if (key)
> +                       jsonw_bool_field(_jw, key, value);
> +               else
> +                       jsonw_bool(_jw, value);
> +       } else if (_IS_FP_CONTEXT(type)) {
> +               color_fprintf(_fp, color, fmt, value ? "true" : "false");
> +       }
> +}
> +
> +/*
> + * In JSON context uses hardcode %#x format: 42 -> 0x2a
> + */
> +void print_color_0xhex(enum output_type type,
> +                      enum color_attr color,
> +                      const char *key,
> +                      const char *fmt,
> +                      unsigned int hex)
> +{
> +       if (_IS_JSON_CONTEXT(type)) {
> +               SPRINT_BUF(b1);
> +
> +               snprintf(b1, sizeof(b1), "%#x", hex);
> +               print_string(PRINT_JSON, key, NULL, b1);
> +       } else if (_IS_FP_CONTEXT(type)) {
> +               color_fprintf(_fp, color, fmt, hex);
> +       }
> +}
> +
> +void print_color_hex(enum output_type type,
> +                    enum color_attr color,
> +                    const char *key,
> +                    const char *fmt,
> +                    unsigned int hex)
> +{
> +       if (_IS_JSON_CONTEXT(type)) {
> +               SPRINT_BUF(b1);
> +
> +               snprintf(b1, sizeof(b1), "%x", hex);
> +               if (key)
> +                       jsonw_string_field(_jw, key, b1);
> +               else
> +                       jsonw_string(_jw, b1);
> +       } else if (_IS_FP_CONTEXT(type)) {
> +               color_fprintf(_fp, color, fmt, hex);
> +       }
> +}
> +
> +/*
> + * In JSON context we don't use the argument "value" we simply call jsonw_null
> + * whereas FP context can use "value" to output anything
> + */
> +void print_color_null(enum output_type type,
> +                     enum color_attr color,
> +                     const char *key,
> +                     const char *fmt,
> +                     const char *value)
> +{
> +       if (_IS_JSON_CONTEXT(type)) {
> +               if (key)
> +                       jsonw_null_field(_jw, key);
> +               else
> +                       jsonw_null(_jw);
> +       } else if (_IS_FP_CONTEXT(type)) {
> +               color_fprintf(_fp, color, fmt, value);
> +       }
> +}
> --
> 1.9.3
>

^ permalink raw reply

* [PATCH net-next v2 0/4] cxgb4: add support to offload tc flower
From: Rahul Lakkireddy @ 2017-09-21 18:11 UTC (permalink / raw)
  To: netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil, Rahul Lakkireddy

This series of patches add support to offload tc flower onto Chelsio
NICs.

Patch 1 adds basic skeleton to prepare for offloading tc flower flows.

Patch 2 adds support to add/remove flows for offload.  Flows can have
accompanying masks.  Following match and action are currently supported
for offload:
Match:  ether-protocol, IPv4/IPv6 addresses, L4 ports (TCP/UDP)
Action: drop, redirect to another port on the device.

Patch 3 adds support to offload tc-flower flows having
vlan actions: pop, push, and modify.

Patch 4 adds support to fetch stats for the offloaded tc flower flows
from hardware.

Support for offloading more match and action types are to be followed
in subsequent series.

Thanks,
Rahul

---
v2:
- Setting ftid to -1 not required after bitmap_find_free_region
  in cxgb4_get_free_ftid.
- Direct return can be used as jumping to error path is not needed
  if flower entry allocation failed in cxgb4_tc_flower_replace.
  Same applies if flower entry not found in cxgb4_tc_flower_destroy.
- Also, removed an extra return from cxgb4_tc_flower_destroy.
- Avoid wrapping line for netdev_err message. Also, use
  consistent error message string.

Kumar Sanghvi (4):
  cxgb4: add tc flower offload skeleton
  cxgb4: add basic tc flower offload support
  cxgb4: add support to offload action vlan
  cxgb4: fetch stats for offloaded tc flower flows

 drivers/net/ethernet/chelsio/cxgb4/Makefile        |   4 +-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h         |   4 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c  | 100 +++++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |  25 ++
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 452 +++++++++++++++++++++
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h   |  66 +++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h     |   3 +
 7 files changed, 653 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
 create mode 100644 drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h

-- 
2.14.1

^ permalink raw reply

* [PATCH net-next v2 1/4] cxgb4: add tc flower offload skeleton
From: Rahul Lakkireddy @ 2017-09-21 18:11 UTC (permalink / raw)
  To: netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil, Rahul Lakkireddy
In-Reply-To: <cover.1506015856.git.rahul.lakkireddy@chelsio.com>

From: Kumar Sanghvi <kumaras@chelsio.com>

Add basic skeleton to prepare for offloading tc-flower flows.

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
---
v2:
- No changes.

 drivers/net/ethernet/chelsio/cxgb4/Makefile        |  4 +-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    | 22 +++++++++
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 57 ++++++++++++++++++++++
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h   | 46 +++++++++++++++++
 4 files changed, 128 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
 create mode 100644 drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h

diff --git a/drivers/net/ethernet/chelsio/cxgb4/Makefile b/drivers/net/ethernet/chelsio/cxgb4/Makefile
index 817212702f0a..fecd7aab673b 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/Makefile
+++ b/drivers/net/ethernet/chelsio/cxgb4/Makefile
@@ -4,7 +4,9 @@
 
 obj-$(CONFIG_CHELSIO_T4) += cxgb4.o
 
-cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o cxgb4_uld.o sched.o cxgb4_filter.o cxgb4_tc_u32.o cxgb4_ptp.o
+cxgb4-objs := cxgb4_main.o l2t.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o \
+	      cxgb4_uld.o sched.o cxgb4_filter.o cxgb4_tc_u32.o \
+	      cxgb4_ptp.o cxgb4_tc_flower.o
 cxgb4-$(CONFIG_CHELSIO_T4_DCB) +=  cxgb4_dcb.o
 cxgb4-$(CONFIG_CHELSIO_T4_FCOE) +=  cxgb4_fcoe.o
 cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 92d9d795d874..8923affbdaf8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -79,6 +79,7 @@
 #include "l2t.h"
 #include "sched.h"
 #include "cxgb4_tc_u32.h"
+#include "cxgb4_tc_flower.h"
 #include "cxgb4_ptp.h"
 
 char cxgb4_driver_name[] = KBUILD_MODNAME;
@@ -2873,6 +2874,25 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
 	return err;
 }
 
+static int cxgb_setup_tc_flower(struct net_device *dev,
+				struct tc_cls_flower_offload *cls_flower)
+{
+	if (!is_classid_clsact_ingress(cls_flower->common.classid) ||
+	    cls_flower->common.chain_index)
+		return -EOPNOTSUPP;
+
+	switch (cls_flower->command) {
+	case TC_CLSFLOWER_REPLACE:
+		return cxgb4_tc_flower_replace(dev, cls_flower);
+	case TC_CLSFLOWER_DESTROY:
+		return cxgb4_tc_flower_destroy(dev, cls_flower);
+	case TC_CLSFLOWER_STATS:
+		return cxgb4_tc_flower_stats(dev, cls_flower);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static int cxgb_setup_tc_cls_u32(struct net_device *dev,
 				 struct tc_cls_u32_offload *cls_u32)
 {
@@ -2907,6 +2927,8 @@ static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
 	switch (type) {
 	case TC_SETUP_CLSU32:
 		return cxgb_setup_tc_cls_u32(dev, type_data);
+	case TC_SETUP_CLSFLOWER:
+		return cxgb_setup_tc_flower(dev, type_data);
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
new file mode 100644
index 000000000000..16dff71e4d02
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the Chelsio T4/T5/T6 Ethernet driver for Linux.
+ *
+ * Copyright (c) 2017 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <net/tc_act/tc_gact.h>
+#include <net/tc_act/tc_mirred.h>
+
+#include "cxgb4.h"
+#include "cxgb4_tc_flower.h"
+
+int cxgb4_tc_flower_replace(struct net_device *dev,
+			    struct tc_cls_flower_offload *cls)
+{
+	return -EOPNOTSUPP;
+}
+
+int cxgb4_tc_flower_destroy(struct net_device *dev,
+			    struct tc_cls_flower_offload *cls)
+{
+	return -EOPNOTSUPP;
+}
+
+int cxgb4_tc_flower_stats(struct net_device *dev,
+			  struct tc_cls_flower_offload *cls)
+{
+	return -EOPNOTSUPP;
+}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
new file mode 100644
index 000000000000..b321fc205b5a
--- /dev/null
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Chelsio T4/T5/T6 Ethernet driver for Linux.
+ *
+ * Copyright (c) 2017 Chelsio Communications, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CXGB4_TC_FLOWER_H
+#define __CXGB4_TC_FLOWER_H
+
+#include <net/pkt_cls.h>
+
+int cxgb4_tc_flower_replace(struct net_device *dev,
+			    struct tc_cls_flower_offload *cls);
+int cxgb4_tc_flower_destroy(struct net_device *dev,
+			    struct tc_cls_flower_offload *cls);
+int cxgb4_tc_flower_stats(struct net_device *dev,
+			  struct tc_cls_flower_offload *cls);
+#endif /* __CXGB4_TC_FLOWER_H */
-- 
2.14.1

^ permalink raw reply related

* [PATCH net-next v2 2/4] cxgb4: add basic tc flower offload support
From: Rahul Lakkireddy @ 2017-09-21 18:11 UTC (permalink / raw)
  To: netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil, Rahul Lakkireddy
In-Reply-To: <cover.1506015856.git.rahul.lakkireddy@chelsio.com>

From: Kumar Sanghvi <kumaras@chelsio.com>

Add support to add/remove flows for offload.  Following match
and action are supported for offloading a flow:

Match: ether-protocol, IPv4/IPv6 addresses, L4 ports (TCP/UDP)
Action: drop, redirect to another port on the device.

The qualifying flows can have accompanying mask information.

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
---
v2:
- Setting ftid to -1 not required after bitmap_find_free_region
  in cxgb4_get_free_ftid.
- Direct return can be used as jumping to error path is not needed
  if flower entry allocation failed in cxgb4_tc_flower_replace.
  Same applies if flower entry not found in cxgb4_tc_flower_destroy.
- Also, removed an extra return from cxgb4_tc_flower_destroy.

 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h         |   3 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c  |  24 ++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |   2 +
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 280 ++++++++++++++++++++-
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h   |  17 ++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h     |   1 +
 6 files changed, 325 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index ea72d2d2e1b4..26eac599ab2c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -904,6 +904,9 @@ struct adapter {
 	/* TC u32 offload */
 	struct cxgb4_tc_u32_table *tc_u32;
 	struct chcr_stats_debug chcr_stats;
+
+	/* TC flower offload */
+	DECLARE_HASHTABLE(flower_anymatch_tbl, 9);
 };
 
 /* Support for "sched-class" command to allow a TX Scheduling Class to be
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
index 45b5853ca2f1..a1f644eb0cec 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
@@ -148,6 +148,30 @@ static int get_filter_steerq(struct net_device *dev,
 	return iq;
 }
 
+int cxgb4_get_free_ftid(struct net_device *dev, int family)
+{
+	struct adapter *adap = netdev2adap(dev);
+	struct tid_info *t = &adap->tids;
+	int ftid;
+
+	spin_lock_bh(&t->ftid_lock);
+	if (family == PF_INET) {
+		ftid = find_first_zero_bit(t->ftid_bmap, t->nftids);
+		if (ftid >= t->nftids)
+			ftid = -1;
+	} else {
+		ftid = bitmap_find_free_region(t->ftid_bmap, t->nftids, 2);
+		if (ftid < 0)
+			goto out_unlock;
+
+		/* this is only a lookup, keep the found region unallocated */
+		bitmap_release_region(t->ftid_bmap, ftid, 2);
+	}
+out_unlock:
+	spin_unlock_bh(&t->ftid_lock);
+	return ftid;
+}
+
 static int cxgb4_set_ftid(struct tid_info *t, int fidx, int family)
 {
 	spin_lock_bh(&t->ftid_lock);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 8923affbdaf8..3ba4e1ff8486 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -5105,6 +5105,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		if (!adapter->tc_u32)
 			dev_warn(&pdev->dev,
 				 "could not offload tc u32, continuing\n");
+
+		cxgb4_init_tc_flower(adapter);
 	}
 
 	if (is_offload(adapter)) {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index 16dff71e4d02..dda34d5a52fb 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -38,16 +38,287 @@
 #include "cxgb4.h"
 #include "cxgb4_tc_flower.h"
 
+static struct ch_tc_flower_entry *allocate_flower_entry(void)
+{
+	struct ch_tc_flower_entry *new = kzalloc(sizeof(*new), GFP_KERNEL);
+	return new;
+}
+
+/* Must be called with either RTNL or rcu_read_lock */
+static struct ch_tc_flower_entry *ch_flower_lookup(struct adapter *adap,
+						   unsigned long flower_cookie)
+{
+	struct ch_tc_flower_entry *flower_entry;
+
+	hash_for_each_possible_rcu(adap->flower_anymatch_tbl, flower_entry,
+				   link, flower_cookie)
+		if (flower_entry->tc_flower_cookie == flower_cookie)
+			return flower_entry;
+	return NULL;
+}
+
+static void cxgb4_process_flow_match(struct net_device *dev,
+				     struct tc_cls_flower_offload *cls,
+				     struct ch_filter_specification *fs)
+{
+	u16 addr_type = 0;
+
+	if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
+		struct flow_dissector_key_control *key =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_CONTROL,
+						  cls->key);
+
+		addr_type = key->addr_type;
+	}
+
+	if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+		struct flow_dissector_key_basic *key =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_BASIC,
+						  cls->key);
+		struct flow_dissector_key_basic *mask =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_BASIC,
+						  cls->mask);
+		u16 ethtype_key = ntohs(key->n_proto);
+		u16 ethtype_mask = ntohs(mask->n_proto);
+
+		if (ethtype_key == ETH_P_ALL) {
+			ethtype_key = 0;
+			ethtype_mask = 0;
+		}
+
+		fs->val.ethtype = ethtype_key;
+		fs->mask.ethtype = ethtype_mask;
+		fs->val.proto = key->ip_proto;
+		fs->mask.proto = mask->ip_proto;
+	}
+
+	if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
+		struct flow_dissector_key_ipv4_addrs *key =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+						  cls->key);
+		struct flow_dissector_key_ipv4_addrs *mask =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+						  cls->mask);
+		fs->type = 0;
+		memcpy(&fs->val.lip[0], &key->dst, sizeof(key->dst));
+		memcpy(&fs->val.fip[0], &key->src, sizeof(key->src));
+		memcpy(&fs->mask.lip[0], &mask->dst, sizeof(mask->dst));
+		memcpy(&fs->mask.fip[0], &mask->src, sizeof(mask->src));
+	}
+
+	if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
+		struct flow_dissector_key_ipv6_addrs *key =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+						  cls->key);
+		struct flow_dissector_key_ipv6_addrs *mask =
+			skb_flow_dissector_target(cls->dissector,
+						  FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+						  cls->mask);
+
+		fs->type = 1;
+		memcpy(&fs->val.lip[0], key->dst.s6_addr, sizeof(key->dst));
+		memcpy(&fs->val.fip[0], key->src.s6_addr, sizeof(key->src));
+		memcpy(&fs->mask.lip[0], mask->dst.s6_addr, sizeof(mask->dst));
+		memcpy(&fs->mask.fip[0], mask->src.s6_addr, sizeof(mask->src));
+	}
+
+	if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
+		struct flow_dissector_key_ports *key, *mask;
+
+		key = skb_flow_dissector_target(cls->dissector,
+						FLOW_DISSECTOR_KEY_PORTS,
+						cls->key);
+		mask = skb_flow_dissector_target(cls->dissector,
+						 FLOW_DISSECTOR_KEY_PORTS,
+						 cls->mask);
+		fs->val.lport = cpu_to_be16(key->dst);
+		fs->mask.lport = cpu_to_be16(mask->dst);
+		fs->val.fport = cpu_to_be16(key->src);
+		fs->mask.fport = cpu_to_be16(mask->src);
+	}
+
+	/* Match only packets coming from the ingress port where this
+	 * filter will be created.
+	 */
+	fs->val.iport = netdev2pinfo(dev)->port_id;
+	fs->mask.iport = ~0;
+}
+
+static int cxgb4_validate_flow_match(struct net_device *dev,
+				     struct tc_cls_flower_offload *cls)
+{
+	if (cls->dissector->used_keys &
+	    ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
+	      BIT(FLOW_DISSECTOR_KEY_BASIC) |
+	      BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
+	      BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
+	      BIT(FLOW_DISSECTOR_KEY_PORTS))) {
+		netdev_warn(dev, "Unsupported key used: 0x%x\n",
+			    cls->dissector->used_keys);
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+static void cxgb4_process_flow_actions(struct net_device *in,
+				       struct tc_cls_flower_offload *cls,
+				       struct ch_filter_specification *fs)
+{
+	const struct tc_action *a;
+	LIST_HEAD(actions);
+
+	tcf_exts_to_list(cls->exts, &actions);
+	list_for_each_entry(a, &actions, list) {
+		if (is_tcf_gact_shot(a)) {
+			fs->action = FILTER_DROP;
+		} else if (is_tcf_mirred_egress_redirect(a)) {
+			int ifindex = tcf_mirred_ifindex(a);
+			struct net_device *out = __dev_get_by_index(dev_net(in),
+								    ifindex);
+			struct port_info *pi = netdev_priv(out);
+
+			fs->action = FILTER_SWITCH;
+			fs->eport = pi->port_id;
+		}
+	}
+}
+
+static int cxgb4_validate_flow_actions(struct net_device *dev,
+				       struct tc_cls_flower_offload *cls)
+{
+	const struct tc_action *a;
+	LIST_HEAD(actions);
+
+	tcf_exts_to_list(cls->exts, &actions);
+	list_for_each_entry(a, &actions, list) {
+		if (is_tcf_gact_shot(a)) {
+			/* Do nothing */
+		} else if (is_tcf_mirred_egress_redirect(a)) {
+			struct adapter *adap = netdev2adap(dev);
+			struct net_device *n_dev;
+			unsigned int i, ifindex;
+			bool found = false;
+
+			ifindex = tcf_mirred_ifindex(a);
+			for_each_port(adap, i) {
+				n_dev = adap->port[i];
+				if (ifindex == n_dev->ifindex) {
+					found = true;
+					break;
+				}
+			}
+
+			/* If interface doesn't belong to our hw, then
+			 * the provided output port is not valid
+			 */
+			if (!found) {
+				netdev_err(dev, "%s: Out port invalid\n",
+					   __func__);
+				return -EINVAL;
+			}
+		} else {
+			netdev_err(dev, "%s: Unsupported action\n", __func__);
+			return -EOPNOTSUPP;
+		}
+	}
+	return 0;
+}
+
 int cxgb4_tc_flower_replace(struct net_device *dev,
 			    struct tc_cls_flower_offload *cls)
 {
-	return -EOPNOTSUPP;
+	struct adapter *adap = netdev2adap(dev);
+	struct ch_tc_flower_entry *ch_flower;
+	struct ch_filter_specification *fs;
+	struct filter_ctx ctx;
+	int fidx;
+	int ret;
+
+	if (cxgb4_validate_flow_actions(dev, cls))
+		return -EOPNOTSUPP;
+
+	if (cxgb4_validate_flow_match(dev, cls))
+		return -EOPNOTSUPP;
+
+	ch_flower = allocate_flower_entry();
+	if (!ch_flower) {
+		netdev_err(dev, "%s: ch_flower alloc failed.\n", __func__);
+		return -ENOMEM;
+	}
+
+	fs = &ch_flower->fs;
+	fs->hitcnts = 1;
+	cxgb4_process_flow_actions(dev, cls, fs);
+	cxgb4_process_flow_match(dev, cls, fs);
+
+	fidx = cxgb4_get_free_ftid(dev, fs->type ? PF_INET6 : PF_INET);
+	if (fidx < 0) {
+		netdev_err(dev, "%s: No fidx for offload.\n", __func__);
+		ret = -ENOMEM;
+		goto free_entry;
+	}
+
+	init_completion(&ctx.completion);
+	ret = __cxgb4_set_filter(dev, fidx, fs, &ctx);
+	if (ret) {
+		netdev_err(dev, "%s: filter creation err %d\n",
+			   __func__, ret);
+		goto free_entry;
+	}
+
+	/* Wait for reply */
+	ret = wait_for_completion_timeout(&ctx.completion, 10 * HZ);
+	if (!ret) {
+		ret = -ETIMEDOUT;
+		goto free_entry;
+	}
+
+	ret = ctx.result;
+	/* Check if hw returned error for filter creation */
+	if (ret) {
+		netdev_err(dev, "%s: filter creation err %d\n",
+			   __func__, ret);
+		goto free_entry;
+	}
+
+	INIT_HLIST_NODE(&ch_flower->link);
+	ch_flower->tc_flower_cookie = cls->cookie;
+	ch_flower->filter_id = ctx.tid;
+	hash_add_rcu(adap->flower_anymatch_tbl, &ch_flower->link, cls->cookie);
+
+	return ret;
+
+free_entry:
+	kfree(ch_flower);
+	return ret;
 }
 
 int cxgb4_tc_flower_destroy(struct net_device *dev,
 			    struct tc_cls_flower_offload *cls)
 {
-	return -EOPNOTSUPP;
+	struct adapter *adap = netdev2adap(dev);
+	struct ch_tc_flower_entry *ch_flower;
+	int ret;
+
+	ch_flower = ch_flower_lookup(adap, cls->cookie);
+	if (!ch_flower)
+		return -ENOENT;
+
+	ret = cxgb4_del_filter(dev, ch_flower->filter_id);
+	if (ret)
+		goto err;
+
+	hash_del_rcu(&ch_flower->link);
+	kfree_rcu(ch_flower, rcu);
+
+err:
+	return ret;
 }
 
 int cxgb4_tc_flower_stats(struct net_device *dev,
@@ -55,3 +326,8 @@ int cxgb4_tc_flower_stats(struct net_device *dev,
 {
 	return -EOPNOTSUPP;
 }
+
+void cxgb4_init_tc_flower(struct adapter *adap)
+{
+	hash_init(adap->flower_anymatch_tbl);
+}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
index b321fc205b5a..6145a9e056eb 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
@@ -37,10 +37,27 @@
 
 #include <net/pkt_cls.h>
 
+struct ch_tc_flower_stats {
+	u64 packet_count;
+	u64 byte_count;
+	u64 last_used;
+};
+
+struct ch_tc_flower_entry {
+	struct ch_filter_specification fs;
+	struct ch_tc_flower_stats stats;
+	unsigned long tc_flower_cookie;
+	struct hlist_node link;
+	struct rcu_head rcu;
+	u32 filter_id;
+};
+
 int cxgb4_tc_flower_replace(struct net_device *dev,
 			    struct tc_cls_flower_offload *cls);
 int cxgb4_tc_flower_destroy(struct net_device *dev,
 			    struct tc_cls_flower_offload *cls);
 int cxgb4_tc_flower_stats(struct net_device *dev,
 			  struct tc_cls_flower_offload *cls);
+
+void cxgb4_init_tc_flower(struct adapter *adap);
 #endif /* __CXGB4_TC_FLOWER_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 84541fce94c5..88487095d14f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -212,6 +212,7 @@ struct filter_ctx {
 
 struct ch_filter_specification;
 
+int cxgb4_get_free_ftid(struct net_device *dev, int family);
 int __cxgb4_set_filter(struct net_device *dev, int filter_id,
 		       struct ch_filter_specification *fs,
 		       struct filter_ctx *ctx);
-- 
2.14.1

^ permalink raw reply related

* [PATCH net-next v2 3/4] cxgb4: add support to offload action vlan
From: Rahul Lakkireddy @ 2017-09-21 18:11 UTC (permalink / raw)
  To: netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil, Rahul Lakkireddy
In-Reply-To: <cover.1506015856.git.rahul.lakkireddy@chelsio.com>

From: Kumar Sanghvi <kumaras@chelsio.com>

Add support for offloading tc-flower flows having
vlan actions: pop, push and modify.

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
---
v2:
- Avoid wrapping line for netdev_err message. Also, use
  consistent error message string.

 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index dda34d5a52fb..e42d2efc9ea2 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -34,6 +34,7 @@
 
 #include <net/tc_act/tc_gact.h>
 #include <net/tc_act/tc_mirred.h>
+#include <net/tc_act/tc_vlan.h>
 
 #include "cxgb4.h"
 #include "cxgb4_tc_flower.h"
@@ -185,6 +186,27 @@ static void cxgb4_process_flow_actions(struct net_device *in,
 
 			fs->action = FILTER_SWITCH;
 			fs->eport = pi->port_id;
+		} else if (is_tcf_vlan(a)) {
+			u32 vlan_action = tcf_vlan_action(a);
+			u8 prio = tcf_vlan_push_prio(a);
+			u16 vid = tcf_vlan_push_vid(a);
+			u16 vlan_tci = (prio << VLAN_PRIO_SHIFT) | vid;
+
+			switch (vlan_action) {
+			case TCA_VLAN_ACT_POP:
+				fs->newvlan |= VLAN_REMOVE;
+				break;
+			case TCA_VLAN_ACT_PUSH:
+				fs->newvlan |= VLAN_INSERT;
+				fs->vlan = vlan_tci;
+				break;
+			case TCA_VLAN_ACT_MODIFY:
+				fs->newvlan |= VLAN_REWRITE;
+				fs->vlan = vlan_tci;
+				break;
+			default:
+				break;
+			}
 		}
 	}
 }
@@ -222,6 +244,26 @@ static int cxgb4_validate_flow_actions(struct net_device *dev,
 					   __func__);
 				return -EINVAL;
 			}
+		} else if (is_tcf_vlan(a)) {
+			u16 proto = be16_to_cpu(tcf_vlan_push_proto(a));
+			u32 vlan_action = tcf_vlan_action(a);
+
+			switch (vlan_action) {
+			case TCA_VLAN_ACT_POP:
+				break;
+			case TCA_VLAN_ACT_PUSH:
+			case TCA_VLAN_ACT_MODIFY:
+				if (proto != ETH_P_8021Q) {
+					netdev_err(dev, "%s: Unsupported vlan proto\n",
+						   __func__);
+					return -EOPNOTSUPP;
+				}
+				break;
+			default:
+				netdev_err(dev, "%s: Unsupported vlan action\n",
+					   __func__);
+				return -EOPNOTSUPP;
+			}
 		} else {
 			netdev_err(dev, "%s: Unsupported action\n", __func__);
 			return -EOPNOTSUPP;
-- 
2.14.1

^ permalink raw reply related

* [PATCH net-next v2 4/4] cxgb4: fetch stats for offloaded tc flower flows
From: Rahul Lakkireddy @ 2017-09-21 18:11 UTC (permalink / raw)
  To: netdev; +Cc: davem, kumaras, ganeshgr, nirranjan, indranil, Rahul Lakkireddy
In-Reply-To: <cover.1506015856.git.rahul.lakkireddy@chelsio.com>

From: Kumar Sanghvi <kumaras@chelsio.com>

Add support to retrieve stats from hardware for offloaded tc flower
flows.  Also, poll for the stats of offloaded flows via timer callback.

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
---
v2:
- No changes.

 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h         |  1 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c  | 76 +++++++++++++++++++++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |  1 +
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c   | 79 +++++++++++++++++++++-
 .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h   |  3 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h     |  2 +
 6 files changed, 161 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 26eac599ab2c..8a94d97df025 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -907,6 +907,7 @@ struct adapter {
 
 	/* TC flower offload */
 	DECLARE_HASHTABLE(flower_anymatch_tbl, 9);
+	struct timer_list flower_stats_timer;
 };
 
 /* Support for "sched-class" command to allow a TX Scheduling Class to be
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
index a1f644eb0cec..bdedf3dce51a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
@@ -148,6 +148,82 @@ static int get_filter_steerq(struct net_device *dev,
 	return iq;
 }
 
+static int get_filter_count(struct adapter *adapter, unsigned int fidx,
+			    u64 *pkts, u64 *bytes)
+{
+	unsigned int tcb_base, tcbaddr;
+	unsigned int word_offset;
+	struct filter_entry *f;
+	__be64 be64_byte_count;
+	int ret;
+
+	tcb_base = t4_read_reg(adapter, TP_CMM_TCB_BASE_A);
+	if ((fidx != (adapter->tids.nftids + adapter->tids.nsftids - 1)) &&
+	    fidx >= adapter->tids.nftids)
+		return -E2BIG;
+
+	f = &adapter->tids.ftid_tab[fidx];
+	if (!f->valid)
+		return -EINVAL;
+
+	tcbaddr = tcb_base + f->tid * TCB_SIZE;
+
+	spin_lock(&adapter->win0_lock);
+	if (is_t4(adapter->params.chip)) {
+		__be64 be64_count;
+
+		/* T4 doesn't maintain byte counts in hw */
+		*bytes = 0;
+
+		/* Get pkts */
+		word_offset = 4;
+		ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
+				   tcbaddr + (word_offset * sizeof(__be32)),
+				   sizeof(be64_count),
+				   (__be32 *)&be64_count,
+				   T4_MEMORY_READ);
+		if (ret < 0)
+			goto out;
+		*pkts = be64_to_cpu(be64_count);
+	} else {
+		__be32 be32_count;
+
+		/* Get bytes */
+		word_offset = 4;
+		ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
+				   tcbaddr + (word_offset * sizeof(__be32)),
+				   sizeof(be64_byte_count),
+				   &be64_byte_count,
+				   T4_MEMORY_READ);
+		if (ret < 0)
+			goto out;
+		*bytes = be64_to_cpu(be64_byte_count);
+
+		/* Get pkts */
+		word_offset = 6;
+		ret = t4_memory_rw(adapter, MEMWIN_NIC, MEM_EDC0,
+				   tcbaddr + (word_offset * sizeof(__be32)),
+				   sizeof(be32_count),
+				   &be32_count,
+				   T4_MEMORY_READ);
+		if (ret < 0)
+			goto out;
+		*pkts = (u64)be32_to_cpu(be32_count);
+	}
+
+out:
+	spin_unlock(&adapter->win0_lock);
+	return ret;
+}
+
+int cxgb4_get_filter_counters(struct net_device *dev, unsigned int fidx,
+			      u64 *hitcnt, u64 *bytecnt)
+{
+	struct adapter *adapter = netdev2adap(dev);
+
+	return get_filter_count(adapter, fidx, hitcnt, bytecnt);
+}
+
 int cxgb4_get_free_ftid(struct net_device *dev, int family)
 {
 	struct adapter *adap = netdev2adap(dev);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 3ba4e1ff8486..d634098d52ab 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -4637,6 +4637,7 @@ static void free_some_resources(struct adapter *adapter)
 	kvfree(adapter->l2t);
 	t4_cleanup_sched(adapter);
 	kvfree(adapter->tids.tid_tab);
+	cxgb4_cleanup_tc_flower(adapter);
 	cxgb4_cleanup_tc_u32(adapter);
 	kfree(adapter->sge.egr_map);
 	kfree(adapter->sge.ingr_map);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index e42d2efc9ea2..a36bd66d2834 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -39,9 +39,12 @@
 #include "cxgb4.h"
 #include "cxgb4_tc_flower.h"
 
+#define STATS_CHECK_PERIOD (HZ / 2)
+
 static struct ch_tc_flower_entry *allocate_flower_entry(void)
 {
 	struct ch_tc_flower_entry *new = kzalloc(sizeof(*new), GFP_KERNEL);
+	spin_lock_init(&new->lock);
 	return new;
 }
 
@@ -363,13 +366,87 @@ int cxgb4_tc_flower_destroy(struct net_device *dev,
 	return ret;
 }
 
+void ch_flower_stats_cb(unsigned long data)
+{
+	struct adapter *adap = (struct adapter *)data;
+	struct ch_tc_flower_entry *flower_entry;
+	struct ch_tc_flower_stats *ofld_stats;
+	unsigned int i;
+	u64 packets;
+	u64 bytes;
+	int ret;
+
+	rcu_read_lock();
+	hash_for_each_rcu(adap->flower_anymatch_tbl, i, flower_entry, link) {
+		ret = cxgb4_get_filter_counters(adap->port[0],
+						flower_entry->filter_id,
+						&packets, &bytes);
+		if (!ret) {
+			spin_lock(&flower_entry->lock);
+			ofld_stats = &flower_entry->stats;
+
+			if (ofld_stats->prev_packet_count != packets) {
+				ofld_stats->prev_packet_count = packets;
+				ofld_stats->last_used = jiffies;
+			}
+			spin_unlock(&flower_entry->lock);
+		}
+	}
+	rcu_read_unlock();
+	mod_timer(&adap->flower_stats_timer, jiffies + STATS_CHECK_PERIOD);
+}
+
 int cxgb4_tc_flower_stats(struct net_device *dev,
 			  struct tc_cls_flower_offload *cls)
 {
-	return -EOPNOTSUPP;
+	struct adapter *adap = netdev2adap(dev);
+	struct ch_tc_flower_stats *ofld_stats;
+	struct ch_tc_flower_entry *ch_flower;
+	u64 packets;
+	u64 bytes;
+	int ret;
+
+	ch_flower = ch_flower_lookup(adap, cls->cookie);
+	if (!ch_flower) {
+		ret = -ENOENT;
+		goto err;
+	}
+
+	ret = cxgb4_get_filter_counters(dev, ch_flower->filter_id,
+					&packets, &bytes);
+	if (ret < 0)
+		goto err;
+
+	spin_lock_bh(&ch_flower->lock);
+	ofld_stats = &ch_flower->stats;
+	if (ofld_stats->packet_count != packets) {
+		if (ofld_stats->prev_packet_count != packets)
+			ofld_stats->last_used = jiffies;
+		tcf_exts_stats_update(cls->exts, bytes - ofld_stats->byte_count,
+				      packets - ofld_stats->packet_count,
+				      ofld_stats->last_used);
+
+		ofld_stats->packet_count = packets;
+		ofld_stats->byte_count = bytes;
+		ofld_stats->prev_packet_count = packets;
+	}
+	spin_unlock_bh(&ch_flower->lock);
+	return 0;
+
+err:
+	return ret;
 }
 
 void cxgb4_init_tc_flower(struct adapter *adap)
 {
 	hash_init(adap->flower_anymatch_tbl);
+	setup_timer(&adap->flower_stats_timer, ch_flower_stats_cb,
+		    (unsigned long)adap);
+	mod_timer(&adap->flower_stats_timer, jiffies + STATS_CHECK_PERIOD);
+}
+
+void cxgb4_cleanup_tc_flower(struct adapter *adap)
+{
+	if (adap->flower_stats_timer.function)
+		del_timer_sync(&adap->flower_stats_timer);
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
index 6145a9e056eb..604feffc752e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
@@ -38,6 +38,7 @@
 #include <net/pkt_cls.h>
 
 struct ch_tc_flower_stats {
+	u64 prev_packet_count;
 	u64 packet_count;
 	u64 byte_count;
 	u64 last_used;
@@ -49,6 +50,7 @@ struct ch_tc_flower_entry {
 	unsigned long tc_flower_cookie;
 	struct hlist_node link;
 	struct rcu_head rcu;
+	spinlock_t lock; /* lock for stats */
 	u32 filter_id;
 };
 
@@ -60,4 +62,5 @@ int cxgb4_tc_flower_stats(struct net_device *dev,
 			  struct tc_cls_flower_offload *cls);
 
 void cxgb4_init_tc_flower(struct adapter *adap);
+void cxgb4_cleanup_tc_flower(struct adapter *adap);
 #endif /* __CXGB4_TC_FLOWER_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 88487095d14f..52324c77a4fe 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -221,6 +221,8 @@ int __cxgb4_del_filter(struct net_device *dev, int filter_id,
 int cxgb4_set_filter(struct net_device *dev, int filter_id,
 		     struct ch_filter_specification *fs);
 int cxgb4_del_filter(struct net_device *dev, int filter_id);
+int cxgb4_get_filter_counters(struct net_device *dev, unsigned int fidx,
+			      u64 *hitcnt, u64 *bytecnt);
 
 static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
 {
-- 
2.14.1

^ permalink raw reply related

* [PATCH iproute2] man: fix documentation for range of route table ID
From: Thomas Haller @ 2017-09-21 18:14 UTC (permalink / raw)
  To: Stephen Hemminger, netdev; +Cc: Thomas Haller

Signed-off-by: Thomas Haller <thaller@redhat.com>
---
 man/man8/ip-route.8.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in
index 803de3b9..9717b959 100644
--- a/man/man8/ip-route.8.in
+++ b/man/man8/ip-route.8.in
@@ -322,7 +322,7 @@ normal routing tables.
 .P
 .B Route tables:
 Linux-2.x can pack routes into several routing tables identified
-by a number in the range from 1 to 2^31 or by name from the file
+by a number in the range from 0 to 2^32-1 or by name from the file
 .B @SYSCONFDIR@/rt_tables
 By default all normal routes are inserted into the
 .B main
-- 
2.13.5

^ permalink raw reply related

* Re: usb/net/p54: trying to register non-static key in p54_unregister_leds
From: Andrey Konovalov @ 2017-09-21 18:22 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Christian Lamparter, Kalle Valo, linux-wireless, netdev, LKML,
	Dmitry Vyukov, Kostya Serebryany, syzkaller, Stephen Boyd,
	Tejun Heo, Yong Zhang
In-Reply-To: <1505937307.3026.20.camel@sipsolutions.net>

On Wed, Sep 20, 2017 at 9:55 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> On Wed, 2017-09-20 at 21:27 +0200, Christian Lamparter wrote:
>
>> It seems this is caused as a result of:
>>     -> lock_map_acquire(&work->lockdep_map);
>>           lock_map_release(&work->lockdep_map);
>>
>>     in flush_work() [0]
>
> Agree.
>
>> This was added by:
>>
>>       commit 0976dfc1d0cd80a4e9dfaf87bd8744612bde475a
>>       Author: Stephen Boyd <sboyd@codeaurora.org>
>>       Date:   Fri Apr 20 17:28:50 2012 -0700
>>
>>       workqueue: Catch more locking problems with flush_work()
>
> Yes, but that doesn't matter.
>
>> Looking at the Stephen's patch, it's clear that it was made
>> with "static DECLARE_WORK(work, my_work)" in mind. However
>> p54's led_work is "per-device", hence it is stored in the
>> devices context p54_common, which is dynamically allocated.
>> So, maybe revert Stephen's patch?
>
> I disagree - as the lockdep warning says:
>
>> > INFO: trying to register non-static key.
>> > the code is fine but needs lockdep annotation.
>> > turning off the locking correctness validator.
>
> What it needs is to actually correctly go through initializing the work
> at least once.
>
> Without more information, I can't really say what's going on, but I
> assume that something is failing and p54_unregister_leds() is getting
> invoked without p54_init_leds() having been invoked, so essentially
> it's trying to flush a work that was never initialized?
>
> INIT_DELAYED_WORK() does, after all, initialize the lockdep map
> properly via __INIT_WORK().

Since I'm able to reproduce this, please let me know if you need me to
collect some debug traces to help with the triage.

Thanks!

>
> johannes
>
> --
> You received this message because you are subscribed to the Google Groups "syzkaller" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to syzkaller+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply

* Re: [kernel-hardening] Re: [PATCH v3 03/31] usercopy: Mark kmalloc caches as usercopy caches
From: Kees Cook @ 2017-09-21 18:26 UTC (permalink / raw)
  To: Christopher Lameter
  Cc: LKML, David Windsor, Pekka Enberg, David Rientjes, Joonsoo Kim,
	Andrew Morton, Linux-MM, linux-xfs, linux-fsdevel@vger.kernel.org,
	Network Development, kernel-hardening@lists.openwall.com
In-Reply-To: <alpine.DEB.2.20.1709211102320.14742@nuc-kabylake>

On Thu, Sep 21, 2017 at 9:04 AM, Christopher Lameter <cl@linux.com> wrote:
> On Thu, 21 Sep 2017, Kees Cook wrote:
>
>> > So what is the point of this patch?
>>
>> The DMA kmalloc caches are not whitelisted:
>
> The DMA kmalloc caches are pretty obsolete and mostly there for obscure
> drivers.
>
> ??

They may be obsolete, but they're still in the kernel, and they aren't
copied to userspace, so we can mark them.

>> >>                         kmalloc_dma_caches[i] = create_kmalloc_cache(n,
>> >> -                               size, SLAB_CACHE_DMA | flags);
>> >> +                               size, SLAB_CACHE_DMA | flags, 0, 0);
>>
>> So this is creating the distinction between the kmallocs that go to
>> userspace and those that don't. The expectation is that future work
>> can start to distinguish between "for userspace" and "only kernel"
>> kmalloc allocations, as is already done here for DMA.
>
> The creation of the kmalloc caches in earlier patches already setup the
> "whitelisting". Why do it twice?

Patch 1 is to allow for things to mark their whitelists. Patch 30
disables the full whitelisting, since then we've defined them all, so
the kmalloc caches need to mark themselves as whitelisted.

Patch 1 leaves unmarked things whitelisted so we can progressively
tighten the restriction and have a bisectable series. (i.e. if there
is something wrong with one of the whitelists in the series, it will
bisect to that one, not the one that removes the global whitelist from
patch 1.)

-Kees

-- 
Kees Cook
Pixel Security

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH iproute2] man: fix documentation for range of route table ID
From: Phil Sutter @ 2017-09-21 18:26 UTC (permalink / raw)
  To: Thomas Haller; +Cc: Stephen Hemminger, netdev
In-Reply-To: <20170921181411.17720-1-thaller@redhat.com>

On Thu, Sep 21, 2017 at 08:14:11PM +0200, Thomas Haller wrote:
> Signed-off-by: Thomas Haller <thaller@redhat.com>

Fixes: 4ec1933dfddfc ("Update ip.8 man page to describe route table id values")

(So that bug is over 7 years old. :)

Cheers, Phil

^ permalink raw reply

* Re: [PATCH 1/7] net: qrtr: Invoke sk_error_report() after setting sk_err
From: Chris Lew @ 2017-09-21 18:27 UTC (permalink / raw)
  To: Bjorn Andersson, David S. Miller; +Cc: netdev, linux-kernel, linux-arm-msm
In-Reply-To: <20170907060329.32402-2-bjorn.andersson@linaro.org>



On 9/6/2017 11:03 PM, Bjorn Andersson wrote:
> Rather than manually waking up any context sleeping on the sock to
> signal an error we should call sk_error_report(). This has the added
> benefit that in-kernel consumers can override this notificatino with
> its own callback.
> 

Typo with notification.

Thanks,
Chris

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ 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