* [net 1/1] tipc: fix flow control accounting for implicit connect
From: Jon Maloy @ 2018-09-25 16:21 UTC (permalink / raw)
To: davem, netdev
Cc: gordan.mihaljevic, tung.q.nguyen, hoang.h.le, jon.maloy,
canh.d.luu, ying.xue, tipc-discussion
From: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
In the case of implicit connect message with data > 1K, the flow
control accounting is incorrect. At this state, the socket does not
know the peer nodes capability and falls back to legacy flow control
by return 1, however the receiver of this message will perform the
new block accounting. This leads to a slack and eventually traffic
disturbance.
In this commit, we perform tipc_node_get_capabilities() at implicit
connect and perform accounting based on the peer's capability.
Signed-off-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
---
net/tipc/socket.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 3f03ddd..b6f99b0 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1419,8 +1419,10 @@ static int __tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dlen)
/* Handle implicit connection setup */
if (unlikely(dest)) {
rc = __tipc_sendmsg(sock, m, dlen);
- if (dlen && (dlen == rc))
+ if (dlen && dlen == rc) {
+ tsk->peer_caps = tipc_node_get_capabilities(net, dnode);
tsk->snt_unacked = tsk_inc(tsk, dlen + msg_hdr_sz(hdr));
+ }
return rc;
}
--
2.1.4
^ permalink raw reply related
* RE: [PATCH net 3/7] lan78xx: Check for supported Wake-on-LAN modes
From: Woojung.Huh @ 2018-09-25 22:32 UTC (permalink / raw)
To: f.fainelli, netdev
Cc: davem, UNGLinuxDriver, steve.glendinning, keescook, akurz,
hayeswang, kai.heng.feng, grundler, zhongjiang, bigeasy,
ran.wang_1, edumazet, linux-usb, linux-kernel
In-Reply-To: <8de18c23-d846-cbb4-c852-9b7d97a95c11@gmail.com>
Hi Florian,
> @@ -1401,19 +1401,10 @@ static int lan78xx_set_wol(struct net_device
...
> + if (pdata->wol & ~WAKE_ALL)
> + return -EINVAL;
If I understand correctly, it needs to check againt "wol->wolopts" than pdata->wol.
> +
> + pdata->wol = wol->wolopts;
Thanks.
Woojung
^ permalink raw reply
* Re: [PATCH net-next v1 1/5] net: allow binding socket in a VRF when there's an unbound socket
From: David Ahern @ 2018-09-25 17:16 UTC (permalink / raw)
To: mmanning, netdev; +Cc: Robert Shearman
In-Reply-To: <97367b8a-dd62-0b42-3f07-30e4b897546a@vyatta.att-mail.com>
On 9/25/18 9:26 AM, Mike Manning wrote:
> On 24/09/2018 23:44, David Ahern wrote:
>> On 9/24/18 10:13 AM, Mike Manning wrote:
>>> From: Robert Shearman <rshearma@vyatta.att-mail.com>
>>>
>>> There is no easy way currently for applications that want to receive
>>> packets in the default VRF to be isolated from packets arriving in
>>> VRFs, which makes using VRF-unaware applications in a VRF-aware system
>>> a potential security risk.
>>
>> That comment is not correct.
>>
>> The point of the l3mdev sysctl's is to prohibit this case. Setting
>> net.ipv4.{tcp,udp}_l3mdev_accept=0 means that a packet arriving on an
>> interface enslaved to a VRF can not be received by a global socket.
> Hi David, thanks for reviewing this. The converse does not hold though,
> i.e. there is no guarantee that the unbound socket will be selected for
> packets when not in a VRF, if there is an unbound socket and a socket
> bound to a VRF. Also, such packets should not be handled by the socket
I need an explicit example here. You are saying a packet arriving on an
interface not enslaved to a VRF might match a socket bound to a VRF?
> in the VRF if there is no unbound socket. We also had an issue with raw
> socket lookup device bind matching. I can break this particular patch
> into smaller patches and provide more detail, would this help? I will
> also update/break up the other patches according to your comments.
Why not add an l3mdev sysctl for raw sockets then?
Yes, please send smaller patches. A diff stat of:
15 files changed, 109 insertions(+), 62 deletions(-)
is a bit harsh.
>
>>
>> Setting the l3mdev to 1 allows the default socket to work across VRFs.
>> If that is not what you want for a given app or a given VRF, then one
>> option is to add netfilter rules on the VRF device to prohibit it. I
>> just verified this works for both tcp and udp.
>
> Netfilter is per application and so does not scale. I have not checked
> if it is suitable for packet handling on raw sockets.
>
>>
>> Further, overlapping binds are allowed using SO_REUSEPORT meaning I can
>> have a server running in the default vrf bound to a port AND a server
>> running bound to a specific vrf and the same port:
>>
>> udp UNCONN 0 0 *%red:12345 *:*
>> users:(("vrf-test",pid=1376,fd=3))
>> udp UNCONN 0 0 *:12345 *:*
>> users:(("vrf-test",pid=1375,fd=3))
>>
>> tcp LISTEN 0 1 *%red:12345 *:*
>> users:(("vrf-test",pid=1356,fd=3))
>> tcp LISTEN 0 1 *:12345 *:*
>> users:(("vrf-test",pid=1352,fd=3))
>>
>> For packets arriving on an interface enslaved to a VRF the socket lookup
>> will pick the VRF server over the global one.
>
> Agreed, but the converse is not guaranteed to hold i.e. packets that are
> not in a VRF may be handled by a socket bound to a VRF.
>
> We do use SO_REUSEPORT for our own applications so as to run instances
> in the default and other VRFs, but still require these patches (or
> similar) due to how packets are handled when there is an unbound socket
> and sockets bound to different VRFs.
Why can't compute_score be adjusted to account for that case?
>
>>
>> --
>>
>> With this patch set I am seeing a number of tests failing -- socket
>> connections working when they should not or not working when they
>> should. I only skimmed the results. I am guessing this patch is the
>> reason, but that is just a guess.
>>
>> You need to make sure all permutations of:
>> 1. net.ipv4.{tcp,udp}_l3mdev_accept={0,1},
>> 2. connection in the default VRF and in a VRF,
>> 3. locally originated and remote traffic,
>> 4. ipv4 and ipv6
>>
>
> We are using raw, datagram and stream sockets for ipv4 & ipv6, require
> connectivity for local and remote addresses where appropriate and need
> route leaking between VRFs when configured, we are unaware of any
> outstanding bugs. Is there some way that I can run/analyze the tests
> that are failing for you?
I am not distributing my vrf tests right now. Before sending the
response I quickly verified one case is easy for you to see: set the udp
sysctl to 0, start a global server, send a packet to it via an interface
enslaved to a VRF. It should fail ECONNREFUSED (no socket match) but
instead packet reaches the server.
>
> Also cf patch 2/5 note that ping to link-local addresses is handled
> consistently with that to global addresses in a VRF, so this now
> succeeds if ping is done in the VRF, i.e. 'sudo ip vrf exec <vrf> ping
> <ll> -I <intf>
Shifting packets destined to a LLA from the real device to the vrf
device is a change in behavior. It is not clear to me at the moment that
it will not cause a problem.
>
>> continue to work as expected meaning packets flow when they should and
>> fail with the right error when they should not. I believe the UDP cases
>> were the main ones failing.
>>
>> Given the test failures, I did not look at the code changes in the patch.
>>
>
A couple of the patches are fine as is - or need a small change. It
might be easier for you to send those outside of the socket lookup set.
^ permalink raw reply
* Re: [PATCH net v2 1/2] net: core: add member wol_enabled to struct net_device
From: Heiner Kallweit @ 2018-09-25 17:30 UTC (permalink / raw)
To: Michal Kubecek
Cc: Andrew Lunn, Florian Fainelli, David Miller,
Realtek linux nic maintainers, netdev@vger.kernel.org
In-Reply-To: <20180925082830.GC30601@unicorn.suse.cz>
On 25.09.2018 10:28, Michal Kubecek wrote:
> (I wrote my comment to v1 because I overlooked there is a v2 already;
> duplicating it here.)
>
> On Mon, Sep 24, 2018 at 09:58:59PM +0200, Heiner Kallweit wrote:
>> Add flag wol_enabled to struct net_device indicating whether
>> Wake-on-LAN is enabled. As first user phy_suspend() will use it to
>> decide whether PHY can be suspended or not.
>>
>> Fixes: f1e911d5d0df ("r8169: add basic phylib support")
>> Fixes: e8cfd9d6c772 ("net: phy: call state machine synchronously in phy_stop")
>> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
>> ---
>> include/linux/netdevice.h | 3 +++
>> net/core/ethtool.c | 9 ++++++++-
>> 2 files changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>> index 1cbbf77a6..f5f1f1450 100644
>> --- a/include/linux/netdevice.h
>> +++ b/include/linux/netdevice.h
>> @@ -1756,6 +1756,8 @@ enum netdev_priv_flags {
>> * switch driver and used to set the phys state of the
>> * switch port.
>> *
>> + * @wol_enabled: Wake-on-LAN is enabled
>> + *
>> * FIXME: cleanup struct net_device such that network protocol info
>> * moves out.
>> */
>> @@ -2039,6 +2041,7 @@ struct net_device {
>> struct lock_class_key *qdisc_tx_busylock;
>> struct lock_class_key *qdisc_running_key;
>> bool proto_down;
>> + unsigned wol_enabled:1;
>> };
>> #define to_net_dev(d) container_of(d, struct net_device, dev)
>>
>
> As there is no bitfield yet, this would add 4 bytes to struct net_device.
> How about using a bit in net_device::priv_flags like IFF_RXFH_CONFIGURED
> in ethtool_set_rxfh_indir() and ethtool_set_rxfh()?
>
Indeed alternatively we could add a private flag and the related
getter/setter.
Regarding the size argument: We have few bool members in struct
net_device (uc_promisc, dismantle, needs_free_netdev, proto_down)
which most likely can be transparently converted to bitfield
members. Then a wol_enabled bitfield member would be no overhead.
I don't have a strong preference and would leave it up to David.
> Michal Kubecek
>
Heiner
^ permalink raw reply
* Re: Marvell phy errata origins?
From: Harini Katakam @ 2018-09-25 17:30 UTC (permalink / raw)
To: Andrew Lunn
Cc: danielwa, Florian Fainelli, afleming, Harini Katakam, netdev,
hramdasi, jpitti, gcasheek
In-Reply-To: <20180925153916.GD1676@lunn.ch>
Hi Daniel,
On Tue, Sep 25, 2018 at 9:10 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> > I hope this this thread isn't too old to bring back to life. So it seems
> > that Harini found that m88e1111 did not need this errata, and Cisco
> > previously found that Harini's patch fixed m88e1112, we included it
> > internally for that reason
> >
> > Now I'm getting reports that this errata fixes issues we're seeing on
> > m88e1111. We see an interrupt storm without the errata, despite the errata
> > not being defined in the datasheet.
>
> Is everybody actually using interrupts? It could be in one system
> phylib is polling.
>
Yes, we weren't using interrupts; we used phy poll.
As I recall, the register and page combination was reserved and
the access seemed to fail.
It will be useful if we can the errata description or version details.
I'll check if I can get any more information.
Regards,
Harini
^ permalink raw reply
* Re: [PATCH net-next 0/3] r8169: series with smaller improvements
From: David Miller @ 2018-09-25 17:36 UTC (permalink / raw)
To: hkallweit1; +Cc: nic_swsd, netdev
In-Reply-To: <2dcf188b-852a-f785-c6e4-e63041b76c86@gmail.com>
From: Heiner Kallweit <hkallweit1@gmail.com>
Date: Tue, 25 Sep 2018 07:55:36 +0200
> This series includes smaller improvements, nothing exciting.
Series applied.
^ permalink raw reply
* Re: [PATCH net 0/3 RESEND] xen-netback: hash mapping handling adjustments
From: David Miller @ 2018-09-25 17:40 UTC (permalink / raw)
To: JBeulich; +Cc: paul.durrant, wei.liu2, xen-devel, netdev
In-Reply-To: <5BA9EDB502000078001EB724@prv1-mh.provo.novell.com>
From: "Jan Beulich" <JBeulich@suse.com>
Date: Tue, 25 Sep 2018 02:11:33 -0600
> First and foremost the fix for XSA-270. On top of that further changes
> which looked desirable to me while investigating that XSA.
>
> 1: fix input validation in xenvif_set_hash_mapping()
> 2: validate queue numbers in xenvif_set_hash_mapping()
> 3: handle page straddling in xenvif_set_hash_mapping()
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
Series applied and queued up for -stable.
Thanks.
^ permalink raw reply
* Re: [PATCH net-next] tls: Fix socket mem accounting error under async encryption
From: David Miller @ 2018-09-25 17:44 UTC (permalink / raw)
To: vakul.garg; +Cc: netdev, borisp, aviadye, davejwatson, doronrk
In-Reply-To: <20180925105617.22543-1-vakul.garg@nxp.com>
From: Vakul Garg <vakul.garg@nxp.com>
Date: Tue, 25 Sep 2018 16:26:17 +0530
> Current async encryption implementation sometimes showed up socket
> memory accounting error during socket close. This results in kernel
> warning calltrace. The root cause of the problem is that socket var
> sk_forward_alloc gets corrupted due to access in sk_mem_charge()
> and sk_mem_uncharge() being invoked from multiple concurrent contexts
> in multicore processor. The apis sk_mem_charge() and sk_mem_uncharge()
> are called from functions alloc_plaintext_sg(), free_sg() etc. It is
> required that memory accounting apis are called under a socket lock.
>
> The plaintext sg data sent for encryption is freed using free_sg() in
> tls_encryption_done(). It is wrong to call free_sg() from this function.
> This is because this function may run in irq context. We cannot acquire
> socket lock in this function.
>
> We remove calling of function free_sg() for plaintext data from
> tls_encryption_done() and defer freeing up of plaintext data to the time
> when the record is picked up from tx_list and transmitted/freed. When
> tls_tx_records() gets called, socket is already locked and thus there is
> no concurrent access problem.
>
> Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
> Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Applied.
^ permalink raw reply
* KASAN: slab-out-of-bounds Read in tls_write_space
From: syzbot @ 2018-09-25 23:54 UTC (permalink / raw)
To: aviadye, borisp, davejwatson, davem, linux-kernel, netdev,
syzkaller-bugs
Hello,
syzbot found the following crash on:
HEAD commit: bd4d08daeb95 Merge branch 'net-dsa-b53-SGMII-modes-fixes'
git tree: net-next
console output: https://syzkaller.appspot.com/x/log.txt?x=110b6a1a400000
kernel config: https://syzkaller.appspot.com/x/.config?x=e79b9299baeb2298
dashboard link: https://syzkaller.appspot.com/bug?extid=12638b747fd208f6cff0
compiler: gcc (GCC) 8.0.1 20180413 (experimental)
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=167d9b9e400000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=15c4003a400000
IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+12638b747fd208f6cff0@syzkaller.appspotmail.com
random: sshd: uninitialized urandom read (32 bytes read)
random: sshd: uninitialized urandom read (32 bytes read)
random: sshd: uninitialized urandom read (32 bytes read)
TCP: request_sock_TCPv6: Possible SYN flooding on port 20002. Sending
cookies. Check SNMP counters.
==================================================================
BUG: KASAN: slab-out-of-bounds in __swab64p include/uapi/linux/swab.h:192
[inline]
BUG: KASAN: slab-out-of-bounds in __be64_to_cpup
include/uapi/linux/byteorder/little_endian.h:74 [inline]
BUG: KASAN: slab-out-of-bounds in is_tx_ready include/net/tls.h:354 [inline]
BUG: KASAN: slab-out-of-bounds in tls_write_space+0x29d/0x2d0
net/tls/tls_main.c:236
Read of size 8 at addr ffff8801bc3c9ff0 by task ksoftirqd/1/18
CPU: 1 PID: 18 Comm: ksoftirqd/1 Not tainted 4.19.0-rc4+ #227
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x1c4/0x2b4 lib/dump_stack.c:113
print_address_description.cold.8+0x9/0x1ff mm/kasan/report.c:256
kasan_report_error mm/kasan/report.c:354 [inline]
kasan_report.cold.9+0x242/0x309 mm/kasan/report.c:412
__asan_report_load8_noabort+0x14/0x20 mm/kasan/report.c:433
__swab64p include/uapi/linux/swab.h:192 [inline]
__be64_to_cpup include/uapi/linux/byteorder/little_endian.h:74 [inline]
is_tx_ready include/net/tls.h:354 [inline]
tls_write_space+0x29d/0x2d0 net/tls/tls_main.c:236
tcp_new_space net/ipv4/tcp_input.c:5154 [inline]
tcp_check_space+0x53f/0x920 net/ipv4/tcp_input.c:5165
tcp_data_snd_check net/ipv4/tcp_input.c:5175 [inline]
tcp_rcv_established+0xde8/0x2120 net/ipv4/tcp_input.c:5656
tcp_v6_do_rcv+0x4b3/0x13c0 net/ipv6/tcp_ipv6.c:1326
tcp_v6_rcv+0x2f7a/0x38a0 net/ipv6/tcp_ipv6.c:1555
ip6_input_finish+0x3fc/0x1aa0 net/ipv6/ip6_input.c:384
NF_HOOK include/linux/netfilter.h:287 [inline]
ip6_input+0xe9/0x600 net/ipv6/ip6_input.c:427
dst_input include/net/dst.h:450 [inline]
ip6_rcv_finish+0x17a/0x330 net/ipv6/ip6_input.c:76
NF_HOOK include/linux/netfilter.h:287 [inline]
ipv6_rcv+0x113/0x640 net/ipv6/ip6_input.c:272
__netif_receive_skb_one_core+0x14d/0x200 net/core/dev.c:4894
__netif_receive_skb+0x2c/0x1e0 net/core/dev.c:5004
process_backlog+0x217/0x760 net/core/dev.c:5808
napi_poll net/core/dev.c:6228 [inline]
net_rx_action+0x7c5/0x1950 net/core/dev.c:6294
__do_softirq+0x30b/0xad8 kernel/softirq.c:292
run_ksoftirqd+0x94/0x100 kernel/softirq.c:653
smpboot_thread_fn+0x68b/0xa00 kernel/smpboot.c:164
kthread+0x35a/0x420 kernel/kthread.c:246
ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:413
Allocated by task 3559:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
kasan_kmalloc+0xc7/0xe0 mm/kasan/kasan.c:553
kmem_cache_alloc_trace+0x152/0x750 mm/slab.c:3620
kmalloc include/linux/slab.h:513 [inline]
kzalloc include/linux/slab.h:707 [inline]
kernfs_fop_open+0x358/0xf90 fs/kernfs/file.c:648
do_dentry_open+0x499/0x1250 fs/open.c:771
vfs_open+0xa0/0xd0 fs/open.c:880
do_last fs/namei.c:3418 [inline]
path_openat+0x12bf/0x5160 fs/namei.c:3534
do_filp_open+0x255/0x380 fs/namei.c:3564
do_sys_open+0x568/0x700 fs/open.c:1063
__do_sys_open fs/open.c:1081 [inline]
__se_sys_open fs/open.c:1076 [inline]
__x64_sys_open+0x7e/0xc0 fs/open.c:1076
do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
Freed by task 3559:
save_stack+0x43/0xd0 mm/kasan/kasan.c:448
set_track mm/kasan/kasan.c:460 [inline]
__kasan_slab_free+0x102/0x150 mm/kasan/kasan.c:521
kasan_slab_free+0xe/0x10 mm/kasan/kasan.c:528
__cache_free mm/slab.c:3498 [inline]
kfree+0xcf/0x230 mm/slab.c:3813
kernfs_fop_release+0x12b/0x1a0 fs/kernfs/file.c:783
__fput+0x385/0xa30 fs/file_table.c:278
____fput+0x15/0x20 fs/file_table.c:309
task_work_run+0x1e8/0x2a0 kernel/task_work.c:113
tracehook_notify_resume include/linux/tracehook.h:193 [inline]
exit_to_usermode_loop+0x318/0x380 arch/x86/entry/common.c:166
prepare_exit_to_usermode arch/x86/entry/common.c:197 [inline]
syscall_return_slowpath arch/x86/entry/common.c:268 [inline]
do_syscall_64+0x6be/0x820 arch/x86/entry/common.c:293
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff8801bc3c9c80
which belongs to the cache kmalloc-512 of size 512
The buggy address is located 368 bytes to the right of
512-byte region [ffff8801bc3c9c80, ffff8801bc3c9e80)
The buggy address belongs to the page:
page:ffffea0006f0f240 count:1 mapcount:0 mapping:ffff8801da800940 index:0x0
flags: 0x2fffc0000000100(slab)
raw: 02fffc0000000100 ffffea0006ee1408 ffffea0007619c08 ffff8801da800940
raw: 0000000000000000 ffff8801bc3c9000 0000000100000006 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff8801bc3c9e80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff8801bc3c9f00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> ffff8801bc3c9f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
^
ffff8801bc3ca000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff8801bc3ca080: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
==================================================================
---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this bug report. See:
https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with
syzbot.
syzbot can test patches for this bug, for details see:
https://goo.gl/tpsmEJ#testing-patches
^ permalink raw reply
* Re: [PATCH net-next] tls: Fixed a memory leak during socket close
From: David Miller @ 2018-09-25 17:52 UTC (permalink / raw)
To: vakul.garg; +Cc: netdev, borisp, aviadye, davejwatson, doronrk
In-Reply-To: <20180925145151.10992-1-vakul.garg@nxp.com>
From: Vakul Garg <vakul.garg@nxp.com>
Date: Tue, 25 Sep 2018 20:21:51 +0530
> During socket close, if there is a open record with tx context, it needs
> to be be freed apart from freeing up plaintext and encrypted scatter
> lists. This patch frees up the open record if present in tx context.
>
> Also tls_free_both_sg() has been renamed to tls_free_open_rec() to
> indicate that the free record in tx context is being freed inside the
> function.
>
> Fixes: a42055e8d2c3 ("net/tls: Add support for async encryption")
> Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Applied.
^ permalink raw reply
* Re: [net 1/1] tipc: fix flow control accounting for implicit connect
From: David Miller @ 2018-09-25 17:53 UTC (permalink / raw)
To: jon.maloy
Cc: netdev, gordan.mihaljevic, tung.q.nguyen, hoang.h.le, canh.d.luu,
ying.xue, tipc-discussion
In-Reply-To: <1537892518-30438-1-git-send-email-jon.maloy@ericsson.com>
From: Jon Maloy <jon.maloy@ericsson.com>
Date: Tue, 25 Sep 2018 18:21:58 +0200
> From: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
>
> In the case of implicit connect message with data > 1K, the flow
> control accounting is incorrect. At this state, the socket does not
> know the peer nodes capability and falls back to legacy flow control
> by return 1, however the receiver of this message will perform the
> new block accounting. This leads to a slack and eventually traffic
> disturbance.
>
> In this commit, we perform tipc_node_get_capabilities() at implicit
> connect and perform accounting based on the peer's capability.
>
> Signed-off-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Applied and queued up for -stable, thank you.
^ permalink raw reply
* Re: [PATCH 0/3] mac80211_hwsim: radio destruction fixes
From: Benjamin Beichler @ 2018-09-25 18:00 UTC (permalink / raw)
To: Martin Willi, Johannes Berg; +Cc: linux-wireless, netdev
In-Reply-To: <20180925074115.18169-1-martin@strongswan.org>
Am 25.09.2018 um 09:41 schrieb Martin Willi:
> This small series fixes two issues for cleaning up hwsim radios. The
> first one is rather easy to hit when terminating namespaces with many
> hwsim radios. The second one affects destroy-on-close users only.
>
> Given that the use of a work-queue for deferred cleanup with namespaces
> has been and still is tricky to get right, this series switches these
> users to a synchronous cleanup in hwsim; The removal of that work-queue
> is in a dedicated commit in case we want to skip that in backports.
Indeed, this is a much better solution. I wasn't that happy with the
workqueue thing, but I didn't know a better solution :-)
I see no errors at review, but I currently cannot test it quickly.
> Martin Willi (3):
> mac80211_hwsim: fix locking when iterating radios during ns exit
> mac80211_hwsim: fix race in radio destruction from netlink notifier
> mac80211_hwsim: drop now unused work-queue from hwsim
>
> drivers/net/wireless/mac80211_hwsim.c | 44 +++++++++++----------------
> 1 file changed, 17 insertions(+), 27 deletions(-)
>
kind regards
Benjamin
--
M.Sc. Benjamin Beichler
Universität Rostock, Fakultät für Informatik und Elektrotechnik
Institut für Angewandte Mikroelektronik und Datentechnik
University of Rostock, Department of CS and EE
Institute of Applied Microelectronics and CE
Richard-Wagner-Straße 31
18119 Rostock
Deutschland/Germany
phone: +49 (0) 381 498 - 7278
email: Benjamin.Beichler@uni-rostock.de
www: http://www.imd.uni-rostock.de/
^ permalink raw reply
* Re: [PATCH net-next v3 00/10] Refactor classifier API to work with Qdisc/blocks without rtnl lock
From: Cong Wang @ 2018-09-25 18:16 UTC (permalink / raw)
To: Vlad Buslov
Cc: Linux Kernel Network Developers, Jamal Hadi Salim, Jiri Pirko,
David Miller, Stephen Hemminger, Kirill Tkhai, Nicolas Dichtel,
Greg KH, mark.rutland, Leon Romanovsky, Paul E. McKenney,
Florian Westphal, David Ahern, christian, lucien xin,
Jakub Kicinski, Jiri Benc
In-Reply-To: <1537806178-10944-1-git-send-email-vladbu@mellanox.com>
On Mon, Sep 24, 2018 at 9:23 AM Vlad Buslov <vladbu@mellanox.com> wrote:
>
> Currently, all netlink protocol handlers for updating rules, actions and
> qdiscs are protected with single global rtnl lock which removes any
> possibility for parallelism. This patch set is a third step to remove
> rtnl lock dependency from TC rules update path.
>
> Recently, new rtnl registration flag RTNL_FLAG_DOIT_UNLOCKED was added.
> Handlers registered with this flag are called without RTNL taken. End
> goal is to have rule update handlers(RTM_NEWTFILTER, RTM_DELTFILTER,
> etc.) to be registered with UNLOCKED flag to allow parallel execution.
> However, there is no intention to completely remove or split rtnl lock
> itself. This patch set addresses specific problems in implementation of
> classifiers API that prevent its control path from being executed
> concurrently. Additional changes are required to refactor classifiers
> API and individual classifiers for parallel execution. This patch set
> lays groundwork to eventually register rule update handlers as
> rtnl-unlocked by modifying code in cls API that works with Qdiscs and
> blocks. Following patch set does the same for chains and classifiers.
>
> The goal of this change is to refactor tcf_block_find() and its
> dependencies to allow concurrent execution:
> - Extend Qdisc API with rcu to lookup and take reference to Qdisc
> without relying on rtnl lock.
> - Extend tcf_block with atomic reference counting and rcu.
> - Always take reference to tcf_block while working with it.
> - Implement tcf_block_release() to release resources obtained by
> tcf_block_find()
> - Create infrastructure to allow registering Qdiscs with class ops that
> do not require the caller to hold rtnl lock.
>
> All three netlink rule update handlers use tcf_block_find() to lookup
> Qdisc and block, and this patch set introduces additional means of
> synchronization to substitute rtnl lock in cls API.
>
> Some functions in cls and sch APIs have historic names that no longer
> clearly describe their intent. In order not make this code even more
> confusing when introducing their concurrency-friendly versions, rename
> these functions to describe actual implementation.
>
> Changes from V2 to V3:
> - Patch 1:
> - Explicitly include refcount.h in rtnetlink.h.
> - Patch 3:
> - Move rcu_head field to the end of struct Qdisc.
> - Rearrange local variable declarations in qdisc_lookup_rcu().
> - Patch 5:
> - Remove tcf_qdisc_put() and inline its content to callers.
Overall looks good to me,
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
There are some minor issues like qdisc_free_cb() can be static,
please send follow-up patch to address it.
Thanks.
^ permalink raw reply
* Re: [PATCH] net/ncsi: Add NCSI OEM command for FB Tiogapass
From: Vijay Khemka @ 2018-09-25 18:16 UTC (permalink / raw)
To: Joel Stanley, Sam Mendoza-Jonas
Cc: linux-aspeed@lists.ozlabs.org, OpenBMC Maillist, Sai Dasari,
Amithash Prasad, netdev@vger.kernel.org
In-Reply-To: <CACPK8XcDExGvCNBcFqOOP+1zQFFs6pMao+7rsZrJFqxPgcY+1Q@mail.gmail.com>
Hi Joel,
Thanks, I am adding netdev mailing list here.
Yes, this command is supported for all Mellanox card. It is as per Mellanox specification.
Regards
-Vijay
On 9/24/18, 5:30 PM, "Joel Stanley" <joel@jms.id.au> wrote:
Hi Vijay,
On Tue, 25 Sep 2018 at 09:39, Vijay Khemka <vijaykhemka@fb.com> wrote:
>
> This patch adds OEM command to get mac address from NCSI device and and
> configure the same to the network card.
>
> ncsi_cmd_arg - Modified this structure to include bigger payload data.
> ncsi_cmd_handler_oem: This function handes oem command request
> ncsi_rsp_handler_oem: This function handles response for OEM command.
> get_mac_address_oem_mlx: This function will send OEM command to get
> mac address for Mellanox card
> set_mac_affinity_mlx: This will send OEM command to set Mac affinity
> for Mellanox card
Thanks for the patch. The code looks okay, but I wanted to get some
input from our NCSI maintainer as to how OEM commands would be
structured. Sam, can you please provide some review here?
Is the command supported on all melanox cards, just some, or does
TiogaPass have a special firmware that enables it?
We should include the netdev mailing list in this discussion as the
patch needs to be acceptable for upstream.
Cheers,
Joel
>
> Signed-off-by: Vijay Khemka <vijaykhemka@fb.com>
> ---
> net/ncsi/Kconfig | 3 ++
> net/ncsi/internal.h | 11 +++++--
> net/ncsi/ncsi-cmd.c | 24 +++++++++++++--
> net/ncsi/ncsi-manage.c | 68 ++++++++++++++++++++++++++++++++++++++++++
> net/ncsi/ncsi-pkt.h | 16 ++++++++++
> net/ncsi/ncsi-rsp.c | 33 +++++++++++++++++++-
> 6 files changed, 149 insertions(+), 6 deletions(-)
>
> diff --git a/net/ncsi/Kconfig b/net/ncsi/Kconfig
> index 08a8a6031fd7..b8bf89fea7c8 100644
> --- a/net/ncsi/Kconfig
> +++ b/net/ncsi/Kconfig
> @@ -10,3 +10,6 @@ config NET_NCSI
> support. Enable this only if your system connects to a network
> device via NCSI and the ethernet driver you're using supports
> the protocol explicitly.
> +config NCSI_OEM_CMD_GET_MAC
> + bool "Get NCSI OEM MAC Address"
> + depends on NET_NCSI
> diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
> index 8055e3965cef..da17958e6a4b 100644
> --- a/net/ncsi/internal.h
> +++ b/net/ncsi/internal.h
> @@ -68,6 +68,10 @@ enum {
> NCSI_MODE_MAX
> };
>
> +#define NCSI_OEM_MFR_MLX_ID 0x8119
> +#define NCSI_OEM_MLX_CMD_GET_MAC 0x1b00
> +#define NCSI_OEM_MLX_CMD_SET_AFFINITY 0x010700
> +
> struct ncsi_channel_version {
> u32 version; /* Supported BCD encoded NCSI version */
> u32 alpha2; /* Supported BCD encoded NCSI version */
> @@ -236,6 +240,7 @@ enum {
> ncsi_dev_state_probe_dp,
> ncsi_dev_state_config_sp = 0x0301,
> ncsi_dev_state_config_cis,
> + ncsi_dev_state_config_oem_gma,
> ncsi_dev_state_config_clear_vids,
> ncsi_dev_state_config_svf,
> ncsi_dev_state_config_ev,
> @@ -301,9 +306,9 @@ struct ncsi_cmd_arg {
> unsigned short payload; /* Command packet payload length */
> unsigned int req_flags; /* NCSI request properties */
> union {
> - unsigned char bytes[16]; /* Command packet specific data */
> - unsigned short words[8];
> - unsigned int dwords[4];
> + unsigned char bytes[64]; /* Command packet specific data */
> + unsigned short words[32];
> + unsigned int dwords[16];
> };
> };
>
> diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c
> index 7567ca63aae2..3205e22c1734 100644
> --- a/net/ncsi/ncsi-cmd.c
> +++ b/net/ncsi/ncsi-cmd.c
> @@ -211,6 +211,25 @@ static int ncsi_cmd_handler_snfc(struct sk_buff *skb,
> return 0;
> }
>
> +static int ncsi_cmd_handler_oem(struct sk_buff *skb,
> + struct ncsi_cmd_arg *nca)
> +{
> + struct ncsi_cmd_oem_pkt *cmd;
> + unsigned int len;
> +
> + len = sizeof(struct ncsi_cmd_pkt_hdr) + 4;
> + if (nca->payload < 26)
> + len += 26;
> + else
> + len += nca->payload;
> +
> + cmd = skb_put_zero(skb, len);
> + memcpy(cmd->data, nca->bytes, nca->payload);
> + ncsi_cmd_build_header(&cmd->cmd.common, nca);
> +
> + return 0;
> +}
> +
> static struct ncsi_cmd_handler {
> unsigned char type;
> int payload;
> @@ -244,7 +263,7 @@ static struct ncsi_cmd_handler {
> { NCSI_PKT_CMD_GNS, 0, ncsi_cmd_handler_default },
> { NCSI_PKT_CMD_GNPTS, 0, ncsi_cmd_handler_default },
> { NCSI_PKT_CMD_GPS, 0, ncsi_cmd_handler_default },
> - { NCSI_PKT_CMD_OEM, 0, NULL },
> + { NCSI_PKT_CMD_OEM, -1, ncsi_cmd_handler_oem },
> { NCSI_PKT_CMD_PLDM, 0, NULL },
> { NCSI_PKT_CMD_GPUUID, 0, ncsi_cmd_handler_default }
> };
> @@ -317,7 +336,8 @@ int ncsi_xmit_cmd(struct ncsi_cmd_arg *nca)
> }
>
> /* Get packet payload length and allocate the request */
> - nca->payload = nch->payload;
> + if (nch->payload >= 0)
> + nca->payload = nch->payload;
> nr = ncsi_alloc_command(nca);
> if (!nr)
> return -ENOMEM;
> diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
> index 091284760d21..3b2b86560cc8 100644
> --- a/net/ncsi/ncsi-manage.c
> +++ b/net/ncsi/ncsi-manage.c
> @@ -635,6 +635,58 @@ static int set_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,
> return 0;
> }
>
> +#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
> +/* NCSI Facebook OEM APIs */
> +static void get_mac_address_oem_mlx(struct ncsi_dev_priv *ndp)
> +{
> + struct ncsi_cmd_arg nca;
> + int ret = 0;
> +
> + memset(&nca, 0, sizeof(struct ncsi_cmd_arg));
> + nca.ndp = ndp;
> + nca.channel = ndp->active_channel->id;
> + nca.package = ndp->active_package->id;
> + nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN;
> + nca.type = NCSI_PKT_CMD_OEM;
> + nca.payload = 8;
> +
> + nca.dwords[0] = ntohl(NCSI_OEM_MFR_MLX_ID);
> + nca.dwords[1] = ntohl(NCSI_OEM_MLX_CMD_GET_MAC);
> +
> + ret = ncsi_xmit_cmd(&nca);
> + if (ret)
> + netdev_err(ndp->ndev.dev,
> + "NCSI: Failed to transmit cmd 0x%x during probe\n",
> + nca.type);
> +}
> +
> +static void set_mac_affinity_mlx(struct ncsi_dev_priv *ndp)
> +{
> + struct ncsi_cmd_arg nca;
> + int ret = 0;
> +
> + memset(&nca, 0, sizeof(struct ncsi_cmd_arg));
> + nca.ndp = ndp;
> + nca.channel = ndp->active_channel->id;
> + nca.package = ndp->active_package->id;
> + nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN;
> + nca.type = NCSI_PKT_CMD_OEM;
> + nca.payload = 60;
> +
> + nca.dwords[0] = ntohl(NCSI_OEM_MFR_MLX_ID);
> + nca.dwords[1] = ntohl(NCSI_OEM_MLX_CMD_SET_AFFINITY);
> +
> + memcpy(&(nca.bytes[8]), ndp->ndev.dev->dev_addr, ETH_ALEN);
> + nca.bytes[14] = 0x09;
> +
> + ret = ncsi_xmit_cmd(&nca);
> + if (ret)
> + netdev_err(ndp->ndev.dev,
> + "NCSI: Failed to transmit cmd 0x%x during probe\n",
> + nca.type);
> +}
> +#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
> +
> static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
> {
> struct ncsi_dev *nd = &ndp->ndev;
> @@ -685,6 +737,22 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
> goto error;
> }
>
> +#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
> + /* Check Manufacture id if it is Mellanox then
> + * get and set mac address. To Do: Add code for
> + * other types of card if required
> + */
> + if (nc->version.mf_id == NCSI_OEM_MFR_MLX_ID)
> + nd->state = ncsi_dev_state_config_oem_gma;
> + else
> + nd->state = ncsi_dev_state_config_clear_vids;
> + break;
> + case ncsi_dev_state_config_oem_gma:
> + ndp->pending_req_num = 2;
> + get_mac_address_oem_mlx(ndp);
> + msleep(500);
> + set_mac_affinity_mlx(ndp);
> +#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
> nd->state = ncsi_dev_state_config_clear_vids;
> break;
> case ncsi_dev_state_config_clear_vids:
> diff --git a/net/ncsi/ncsi-pkt.h b/net/ncsi/ncsi-pkt.h
> index 91b4b66438df..0653a893eb12 100644
> --- a/net/ncsi/ncsi-pkt.h
> +++ b/net/ncsi/ncsi-pkt.h
> @@ -151,6 +151,22 @@ struct ncsi_cmd_snfc_pkt {
> unsigned char pad[22];
> };
>
> +/* Oem Request Command */
> +struct ncsi_cmd_oem_pkt {
> + struct ncsi_cmd_pkt_hdr cmd; /* Command header */
> + unsigned char data[64]; /* OEM Payload Data */
> + __be32 checksum; /* Checksum */
> +};
> +
> +/* Oem Response Packet */
> +struct ncsi_rsp_oem_pkt {
> + struct ncsi_rsp_pkt_hdr rsp; /* Command header */
> + __be32 mfr_id; /* Manufacture ID */
> + __be32 oem_cmd; /* oem command */
> + unsigned char data[32]; /* Payload data */
> + __be32 checksum; /* Checksum */
> +};
> +
> /* Get Link Status */
> struct ncsi_rsp_gls_pkt {
> struct ncsi_rsp_pkt_hdr rsp; /* Response header */
> diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
> index 930c1d3796f0..3b94c96b9c7f 100644
> --- a/net/ncsi/ncsi-rsp.c
> +++ b/net/ncsi/ncsi-rsp.c
> @@ -596,6 +596,37 @@ static int ncsi_rsp_handler_snfc(struct ncsi_request *nr)
> return 0;
> }
>
> +static int ncsi_rsp_handler_oem(struct ncsi_request *nr)
> +{
> + struct ncsi_rsp_oem_pkt *rsp;
> + struct ncsi_dev_priv *ndp = nr->ndp;
> + struct net_device *ndev = ndp->ndev.dev;
> + int ret = 0;
> + unsigned int oem_cmd, mfr_id;
> + const struct net_device_ops *ops = ndev->netdev_ops;
> + struct sockaddr saddr;
> +
> + /* Get the response header */
> + rsp = (struct ncsi_rsp_oem_pkt *)skb_network_header(nr->rsp);
> +
> + oem_cmd = ntohl(rsp->oem_cmd);
> + mfr_id = ntohl(rsp->mfr_id);
> +
> + /* Check for Mellanox manufacturer id */
> + if (mfr_id != NCSI_OEM_MFR_MLX_ID)
> + return 0;
> +
> + if (oem_cmd == NCSI_OEM_MLX_CMD_GET_MAC) {
> + saddr.sa_family = ndev->type;
> + ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
> + memcpy(saddr.sa_data, &(rsp->data[4]), ETH_ALEN);
> + ret = ops->ndo_set_mac_address(ndev, &saddr);
> + if (ret < 0)
> + netdev_warn(ndev, "NCSI: 'Writing mac address to device failed\n");
> + }
> + return ret;
> +}
> +
> static int ncsi_rsp_handler_gvi(struct ncsi_request *nr)
> {
> struct ncsi_rsp_gvi_pkt *rsp;
> @@ -932,7 +963,7 @@ static struct ncsi_rsp_handler {
> { NCSI_PKT_RSP_GNS, 172, ncsi_rsp_handler_gns },
> { NCSI_PKT_RSP_GNPTS, 172, ncsi_rsp_handler_gnpts },
> { NCSI_PKT_RSP_GPS, 8, ncsi_rsp_handler_gps },
> - { NCSI_PKT_RSP_OEM, 0, NULL },
> + { NCSI_PKT_RSP_OEM, -1, ncsi_rsp_handler_oem },
> { NCSI_PKT_RSP_PLDM, 0, NULL },
> { NCSI_PKT_RSP_GPUUID, 20, ncsi_rsp_handler_gpuuid }
> };
> --
> 2.17.1
>
^ permalink raw reply
* Re: [PATCH net 00/15] netpoll: avoid capture effects for NAPI drivers
From: Song Liu @ 2018-09-25 18:25 UTC (permalink / raw)
To: Michael Chan
Cc: Eric Dumazet, David Miller, Netdev, Ariel Elior, Eric Dumazet,
tariqt@mellanox.com, Saeed Mahameed, jeffrey.t.kirsher@intel.com,
Jakub Kicinski, j.vosburgh@gmail.com, vfalico@gmail.com,
Andy Gospodarek
In-Reply-To: <CACKFLin1samKmyTJSYnZxEUGMue7SPWaFcv=ZrSvK-DrHhuxJA@mail.gmail.com>
> On Sep 25, 2018, at 7:43 AM, Michael Chan <michael.chan@broadcom.com> wrote:
>
> On Tue, Sep 25, 2018 at 7:20 AM Eric Dumazet <edumazet@google.com> wrote:
>>
>> On Tue, Sep 25, 2018 at 7:02 AM Michael Chan <michael.chan@broadcom.com> wrote:
>>>
>>> On Mon, Sep 24, 2018 at 2:18 PM Song Liu <songliubraving@fb.com> wrote:
>>>>
>>>>
>>>>
>>>>> On Sep 24, 2018, at 2:05 PM, Eric Dumazet <edumazet@google.com> wrote:
>>>>>
>>>>>>
>>>>>> Interesting, maybe a bnxt specific issue.
>>>>>>
>>>>>> It seems their model is to process TX/RX notification in the same queue,
>>>>>> they throw away RX events if budget == 0
>>>>>>
>>>>>> It means commit e7b9569102995ebc26821789628eef45bd9840d8 is wrong and
>>>>>> must be reverted.
>>>>>>
>>>>>> Otherwise, we have a possibility of blocking a queue under netpoll pressure.
>>>>>
>>>>> Hmm, actually a revert might not be enough, since code at lines 2030-2031
>>>>> would fire and we might not call napi_complete_done() anyway.
>>>>>
>>>>> Unfortunately this driver logic is quite complex.
>>>>>
>>>>> Could you test on other NIC eventually ?
>>>>>
>>>>
>>>> It actually runs OK on ixgbe.
>>>>
>>>> @Michael, could you please help us with this?
>>>>
>>> I've taken a quick look using today's net tree plus Eric's
>>> poll_one_napi() patch. The problem I'm seeing is that netpoll calls
>>> bnxt_poll() with budget 0. And since work_done >= budget of 0, we
>>> return without calling napi_complete_done() and without arming the
>>> interrupt. netpoll doesn't always call us back until we call
>>> napi_complete_done(), right? So I think if there are in-flight TX
>>> completions, we'll miss those.
>>
>> That's the whole point of netpoll :
>>
>> We drain the TX queues, without interrupts being involved at all,
>> by calling ->napi() with a zero budget.
>>
>> napi_complete(), even if called from ->napi() while budget was zero,
>> should do nothing but return early.
>>
>> budget==0 means that ->napi() should process all TX completions.
>
> All TX completions that we can see. We cannot see the in-flight ones.
>
> If budget is exceeded, I think the assumption is that poll will always
> be called again.
>
>>
>> So it looks like bnxt has a bug, that is showing up after the latest
>> poll_one_napi() patch.
>> This latest patch is needed otherwise the cpu attempting the
>> netpoll-TX-drain might drain nothing at all,
>> since it does not anymore call ndo_poll_controller() that was grabbing
>> SCHED bits on all queues (napi_schedule() like calls)
>
> I think the latest patch is preventing the normal interrupt -> NAPI
> path from coming in and cleaning the remaining TX completions and
> arming the interrupt.
Hi Michael,
This may not be related. But I am looking at this:
bnxt_poll_work() {
while (1) {
....
if (rx_pkts == budget)
return
}
}
With budget of 0, the loop will terminate after processing one packet.
But I think the expectation is to finish all tx packets. So it doesn't
feel right. Could you please confirm?
Thanks,
Song
^ permalink raw reply
* Re: r8169 hang on 4.18
From: Heiner Kallweit @ 2018-09-25 18:44 UTC (permalink / raw)
To: Ortwin Glück, linux-kernel@vger.kernel.org, netdev
In-Reply-To: <4584fb8e-32f8-7375-8481-fe35c3cf693e@odi.ch>
On 25.09.2018 11:53, Ortwin Glück wrote:
> On 24.09.18 22:21, Heiner Kallweit wrote:
>> Thanks for the report. Here come a few inquiries:
>>
>> You say the box has one on-board network port and four network ports on
>> an extension card, all five driven by r8169. The on-board chip is a
>> RTL8168h, what's the type of the chips on the extension card?
>
> This is the card:
> 03:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:8168] (rev 0c)
> Subsystem: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:0123]
> Flags: bus master, fast devsel, latency 0, IRQ 17
> I/O ports at d000 [size=256]
> Memory at f7300000 (64-bit, non-prefetchable) [size=4K]
> Memory at f0300000 (64-bit, prefetchable) [size=16K]
> Capabilities: [40] Power Management version 3
> Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
> Capabilities: [70] Express Endpoint, MSI 01
> Capabilities: [b0] MSI-X: Enable- Count=4 Masked-
> Capabilities: [d0] Vital Product Data
> Capabilities: [100] Advanced Error Reporting
> Capabilities: [140] Virtual Channel
> Capabilities: [160] Device Serial Number 01-00-00-00-68-4c-e0-00
> Capabilities: [170] Latency Tolerance Reporting
> Kernel driver in use: r8169
>
> 04:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:8168] (rev 0c)
> Subsystem: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:0123]
> Flags: bus master, fast devsel, latency 0, IRQ 18
> I/O ports at c000 [size=256]
> Memory at f7200000 (64-bit, non-prefetchable) [size=4K]
> Memory at f0200000 (64-bit, prefetchable) [size=16K]
> Capabilities: [40] Power Management version 3
> Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
> Capabilities: [70] Express Endpoint, MSI 01
> Capabilities: [b0] MSI-X: Enable- Count=4 Masked-
> Capabilities: [d0] Vital Product Data
> Capabilities: [100] Advanced Error Reporting
> Capabilities: [140] Virtual Channel
> Capabilities: [160] Device Serial Number 01-00-00-00-68-4c-e0-00
> Capabilities: [170] Latency Tolerance Reporting
> Kernel driver in use: r8169
>
> 05:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:8168] (rev 0c)
> Subsystem: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:0123]
> Flags: bus master, fast devsel, latency 0, IRQ 19
> I/O ports at b000 [size=256]
> Memory at f7100000 (64-bit, non-prefetchable) [size=4K]
> Memory at f0100000 (64-bit, prefetchable) [size=16K]
> Capabilities: [40] Power Management version 3
> Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
> Capabilities: [70] Express Endpoint, MSI 01
> Capabilities: [b0] MSI-X: Enable- Count=4 Masked-
> Capabilities: [d0] Vital Product Data
> Capabilities: [100] Advanced Error Reporting
> Capabilities: [140] Virtual Channel
> Capabilities: [160] Device Serial Number 01-00-00-00-68-4c-e0-00
> Capabilities: [170] Latency Tolerance Reporting
> Kernel driver in use: r8169
>
> 06:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:8168] (rev 0c)
> Subsystem: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:0123]
> Flags: bus master, fast devsel, latency 0, IRQ 16
> I/O ports at a000 [size=256]
> Memory at f7000000 (64-bit, non-prefetchable) [size=4K]
> Memory at f0000000 (64-bit, prefetchable) [size=16K]
> Capabilities: [40] Power Management version 3
> Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
> Capabilities: [70] Express Endpoint, MSI 01
> Capabilities: [b0] MSI-X: Enable- Count=4 Masked-
> Capabilities: [d0] Vital Product Data
> Capabilities: [100] Advanced Error Reporting
> Capabilities: [140] Virtual Channel
> Capabilities: [160] Device Serial Number 01-00-00-00-68-4c-e0-00
> Capabilities: [170] Latency Tolerance Reporting
> Kernel driver in use: r8169
>
Unfortunately the lspci info doesn't allow to determine the exact chip type.
Relevant would be the syslog info as you provided it in your first mail:
r8169 0000:07:00.0 eth4: RTL8168h/8111h, 50:9a:4c:2e:92:be, XID 54100800, IRQ 16
Are the chips on the extension card the same as the on-board chip?
>
>
>> I'm asking because r8169 supports ~ 50 chip variants of the RTL8169/8
>> family.
>> Are the problems the same on all five ports?
>
> Yes, I see the WARN_ON also on the other ports. Here is one from the separate card:
> [Mon Sep 24 15:47:21 2018] ------------[ cut here ]------------
> [Mon Sep 24 15:47:21 2018] NETDEV WATCHDOG: lan (r8169): transmit queue 0 timed out
> [Mon Sep 24 15:47:21 2018] WARNING: CPU: 2 PID: 0 at net/sched/sch_generic.c:461 dev_watchdog+0x215/0x220
> [Mon Sep 24 15:47:21 2018] CPU: 2 PID: 0 Comm: swapper/2 Not tainted 4.18.8 #70
> [Mon Sep 24 15:47:21 2018] Hardware name: Dell Inc. OptiPlex 3050/0W0CHX, BIOS 1.6.5 09/09/2017
> [Mon Sep 24 15:47:21 2018] RIP: 0010:dev_watchdog+0x215/0x220
> [Mon Sep 24 15:47:21 2018] Code: 49 63 4c 24 e8 eb 8c 4c 89 ef c6 05 1a 19 ca 00 01 e8 5f 52 fd ff 89 d9 4c 89 ee 48 c7 c7 78 ab 67 af 48 89 c2 e8 1b 2b 49 ff <0f> 0b eb be 0f 1f 80 00 00 00 00 41 57 45 89 cf 41 56 49 89 d6 41
> [Mon Sep 24 15:47:21 2018] RSP: 0018:ffff8a205dd03e98 EFLAGS: 00010282
> [Mon Sep 24 15:47:21 2018] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000006
> [Mon Sep 24 15:47:21 2018] RDX: 0000000000000007 RSI: 0000000000000096 RDI: ffff8a205dd15350
> [Mon Sep 24 15:47:21 2018] RBP: ffff8a2045de041c R08: 0000000000000001 R09: 0000000000000763
> [Mon Sep 24 15:47:21 2018] R10: 0000000000000082 R11: 0000000000000000 R12: ffff8a2045de0438
> [Mon Sep 24 15:47:21 2018] R13: ffff8a2045de0000 R14: 0000000000000001 R15: ffff8a20455e1480
> [Mon Sep 24 15:47:21 2018] FS: 0000000000000000(0000) GS:ffff8a205dd00000(0000) knlGS:0000000000000000
> [Mon Sep 24 15:47:21 2018] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [Mon Sep 24 15:47:21 2018] CR2: 00007ff598642c38 CR3: 000000001f80a004 CR4: 00000000003606e0
> [Mon Sep 24 15:47:21 2018] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [Mon Sep 24 15:47:21 2018] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> [Mon Sep 24 15:47:21 2018] Call Trace:
> [Mon Sep 24 15:47:21 2018] <IRQ>
> [Mon Sep 24 15:47:21 2018] ? pfifo_fast_reset+0x130/0x130
> [Mon Sep 24 15:47:21 2018] ? pfifo_fast_reset+0x130/0x130
> [Mon Sep 24 15:47:21 2018] call_timer_fn+0x11/0x70
> [Mon Sep 24 15:47:21 2018] expire_timers+0x8e/0xa0
> [Mon Sep 24 15:47:21 2018] run_timer_softirq+0xb9/0x160
> [Mon Sep 24 15:47:21 2018] ? __hrtimer_run_queues+0x135/0x1a0
> [Mon Sep 24 15:47:21 2018] ? hw_breakpoint_pmu_read+0x10/0x10
> [Mon Sep 24 15:47:21 2018] ? ktime_get+0x39/0x90
> [Mon Sep 24 15:47:21 2018] ? lapic_next_event+0x20/0x20
> [Mon Sep 24 15:47:21 2018] __do_softirq+0xcb/0x1f8
> [Mon Sep 24 15:47:21 2018] irq_exit+0xa9/0xb0
> [Mon Sep 24 15:47:21 2018] smp_apic_timer_interrupt+0x59/0x90
> [Mon Sep 24 15:47:21 2018] apic_timer_interrupt+0xf/0x20
> [Mon Sep 24 15:47:21 2018] </IRQ>
> [Mon Sep 24 15:47:21 2018] RIP: 0010:cpuidle_enter_state+0x129/0x200
> [Mon Sep 24 15:47:21 2018] Code: 45 00 89 c3 e8 d8 3b 55 ff 65 8b 3d b1 eb 45 51 e8 8c 3a 55 ff 31 ff 49 89 c4 e8 72 43 55 ff fb 48 ba cf f7 53 e3 a5 9b c4 20 <4c> 89 e1 4c 29 e9 48 89 c8 48 c1 f9 3f 48 f7 ea b8 ff ff ff 7f 48
> [Mon Sep 24 15:47:21 2018] RSP: 0018:ffff9f46806e7ea8 EFLAGS: 00000286 ORIG_RAX: ffffffffffffff13
> [Mon Sep 24 15:47:21 2018] RAX: ffff8a205dd1f800 RBX: 0000000000000004 RCX: 000000000000001f
> [Mon Sep 24 15:47:21 2018] RDX: 20c49ba5e353f7cf RSI: 00000000258f0602 RDI: 0000000000000000
> [Mon Sep 24 15:47:21 2018] RBP: ffff8a205dd25ee0 R08: 00000000000003ee R09: 00000000ffffffff
> [Mon Sep 24 15:47:21 2018] R10: ffff9f46806e7e90 R11: 00000000000003d5 R12: 00000752028ec2d0
> [Mon Sep 24 15:47:21 2018] R13: 000007520282ea18 R14: 0000000000000004 R15: 0000000000000000
> [Mon Sep 24 15:47:21 2018] ? cpuidle_enter_state+0x11e/0x200
> [Mon Sep 24 15:47:21 2018] do_idle+0x1c0/0x200
> [Mon Sep 24 15:47:21 2018] cpu_startup_entry+0x6a/0x70
> [Mon Sep 24 15:47:21 2018] start_secondary+0x18a/0x1c0
> [Mon Sep 24 15:47:21 2018] secondary_startup_64+0xa5/0xb0
> [Mon Sep 24 15:47:21 2018] ---[ end trace 7ea59db719c41930 ]---
> [Mon Sep 24 15:47:21 2018] r8169 0000:06:00.0 lan: link up
>
>
>> Can you reproduce the problem (how)? Any specific network usage
>> triggering the problem?
>
> Actually the WARN_ON seems not to be causing the hang but to be rather a side effect of an "unstable" port. The WARN_ON occurs every few days but the port works fine most of the time. But when the port hangs (no more traffic) only a reboot fixes it.
>
> These looks suspicious:
>
> [ 8048.829832] r8169 0000:06:00.0 lan: link up
> [64114.535455] r8169 0000:07:00.0 wan: link up
> [74726.396319] r8169 0000:07:00.0 wan: link up
>
> The ports seem to go up at random times (without "link down" message). This is also what we saw with MSI enabled: links thrashing in down/up cycles.
>
>> The root cause of the problem not necessarily is in r8169, some other
>> change could have broken it too. Can you test using r8169 from 4.18
>> on top of 4.17?
>
> Unfortunately I am not able to do that.
>
>> When stating "behaves erratic" you refer to the network hangs
>> mentioned before? Or to some other issue?
>
> please see above: links thrashing in down/up cycles.
> I see that MSI/MSI-X has been disabled on quite a few chip versions (e.g. lately commit 72a579b8).
> Does pci=nomsi disable MSI-X as well, or just MSI?
Kernel treats MSI-X as a sub-feature of MSI, therefore nomsi disables MSI-X too.
> I could try adding my chip versions to these quirk sections. I couldn't find a way to disable MSI/MSI-X per device.
>
It turned out that the MSI-X problems are caused by a nasty small bug in certain PCI bridges.
As soon as the fix for it appears in mainline we'll revert the workarounds in r8169.
And the MSI-X issue resulted in non-functional network after resume from suspend, therefore
I think your problem isn't related.
>> A similar report is here:
>> https://bugzilla.kernel.org/show_bug.cgi?id=201109
>
> Also that report has the "link up" message after the WARN_ON.
>
>> There the problem seems to start with the upgrade from 4.18.4 to 4.18.5.
>> Can you try with 4.18.4 ?
>>
>> The diff between 4.18.4 and 4.18.5 shows nothing related to r8169.
>
> Exactly. I think the incident is just so rare that correlating it with a specific upgrade is hard.
>
As I said, you could try running 4.18.4 instead of 4.18.8 for a while (if you have this option).
You faced the hang roughly once per day, so after a few days you should be sure.
> Thanks,
>
> Ortwin
>
Rgds, Heiner
^ permalink raw reply
* [PATCH RFC,net-next 00/10] add flow_rule infrastructure
From: Pablo Neira Ayuso @ 2018-09-25 19:19 UTC (permalink / raw)
To: netdev
Cc: davem, thomas.lendacky, f.fainelli, ariel.elior, michael.chan,
santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, ganeshgr,
jakub.kicinski, linux-net-drivers, peppe.cavallaro,
alexandre.torgue, joabreu, grygorii.strashko, andrew,
vivien.didelot
Hi,
This patchset spins over the existing kernel representation for network
driver offloads based on the existing cls_flower dissector use for the
rule matching side and the TC action infrastructure to represent the
action side.
The proposed object that represent rules looks like this:
struct flow_rule {
struct flow_match match;
struct flow_action action;
};
The flow_match structure wraps Jiri Pirko's existing representation
available in cls_flower based on dissectors to represent the matching
side:
struct flow_match {
struct flow_dissector *dissector;
void *mask;
void *key;
};
The mask and key layouts are opaque, given the dissector object provides
the used_keys flags - to check for rule selectors that are being used -
and the offset to the corresponding key and mask in the opaque
container structures.
Then, the actions to be performs on the matching packets is represented
through the flow_action object:
struct flow_action {
int num_keys;
struct flow_action_key *keys;
};
This object comes with a num_keys field that specifies the number of
actions - this supports an arbitrary number of actions, the driver
will impose its own restrictions on this - and the array that stores
flow_action_key structures (keys). Each flow action key looks like this:
struct flow_action_key {
enum flow_action_key_id id;
union {
u32 chain_index; /* FLOW_ACTION_KEY_GOTO */
struct net_device *dev; /* FLOW_ACTION_KEY_REDIRECT */
struct { /* FLOW_ACTION_KEY_VLAN */
u16 vid;
__be16 proto;
u8 prio;
} vlan;
struct { /* FLOW_ACTION_KEY_PACKET_EDIT */
enum flow_act_mangle_base htype;
u32 offset;
u32 mask;
u32 val;
} mangle;
const struct ip_tunnel_info *tunnel; /* FLOW_ACTION_KEY_TUNNEL_ENCAP */
u32 csum_flags; /* FLOW_ACTION_KEY_CSUM */
u32 mark; /* FLOW_ACTION_KEY_MARK */
u32 queue_index; /* FLOW_ACTION_KEY_QUEUE */
};
};
Possible actions in this patchset are:
enum flow_action_key_id {
FLOW_ACTION_KEY_ACCEPT = 0,
FLOW_ACTION_KEY_DROP,
FLOW_ACTION_KEY_TRAP,
FLOW_ACTION_KEY_GOTO,
FLOW_ACTION_KEY_REDIRECT,
FLOW_ACTION_KEY_MIRRED,
FLOW_ACTION_KEY_VLAN_PUSH,
FLOW_ACTION_KEY_VLAN_POP,
FLOW_ACTION_KEY_VLAN_MANGLE,
FLOW_ACTION_KEY_TUNNEL_ENCAP,
FLOW_ACTION_KEY_TUNNEL_DECAP,
FLOW_ACTION_KEY_MANGLE,
FLOW_ACTION_KEY_ADD,
FLOW_ACTION_KEY_CSUM,
FLOW_ACTION_KEY_MARK,
FLOW_ACTION_KEY_WAKE,
FLOW_ACTION_KEY_QUEUE,
};
which are based on what existing drivers can do from the existing TC
actions.
Common code pattern from the drivers to populate the hardware
intermediate representation looks like this:
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
struct flow_match_ipv4_addrs match;
flow_rule_match_ipv4_addrs(rule, &match);
flow->l3_key.ipv4.daddr.s_addr = match.key->dst;
flow->l3_mask.ipv4.daddr.s_addr = match.mask->dst;
flow->l3_key.ipv4.saddr.s_addr = match.key->src;
flow->l3_mask.ipv4.saddr.s_addr = match.mask->src;
}
Then, flow action code parser should look like:
flow_action_for_each(i, act, flow_action) {
switch (act->id) {
case FLOW_ACTION_KEY_DROP:
actions->flags |= DRIVER_XYZ_ACTION_FLAG_DROP;
break;
case ...:
break;
default:
return -EOPNOTSUPP;
}
}
A quick description of the patches:
Patch #1 introduces the flow_match structure and two new interfaces to
check for rule selectors that are used and to fetch the key
and the mask with one single function call. This patch also
introduces the flow_rule structure to avoid a follow up patch
that would very much update the same LoCs.
Patch #2 Preparation patch for mlx5e driver, for the packet edit parser.
Patch #3 Introduce flow_action infrastructure, as described above.
Patch #4 Add function to translate TC action to flow_action from
cls_flower.
Patch #5 Add infrastructure to fetch statistics into container structure
and synchronize them to TC actions from cls_flower. Another
preparation patch before patch #7.
Patch #6 Use flow_action infrastructure from drivers.
Patch #7 Do not expose TC actions to drivers anymore, now that drivers
have been converted to use the flow_action infrastructure after
patch #5.
Patch #8 Support to wake-up-on-lan and queue actions for the flow_action
infrastructure, which are another two common actions supported
by network interfaces, from the ethtool_rx_flow interface.
Patch #9 Add a function to translate from ethtool_rx_flow_spec structure
to the flow_action structure. This is a simple one, basic
enough for the first client, the bcm_sf2 driver. It can
be easily extended to support more selectors in case driver
needs it.
Patch #10 Update bcm_sf2 to use this new translator function and
update codebase to configure hardware IR using the
flow_action representation. This will allow later development
of cls_flower using the same backend code from the driver.
This patchset is adding a new layer between drivers and the existing
software frontends, so it's a bit more code, but it is core
infrastructure common to everyone and this comes with benefits for
driver developers:
1) No need to make ad-hoc driver code for each supported front-end,
one single codebase to populate the native hardware intermediate
representation for each existing specific purpose packet classifiers
such as TC, OVS, ethtool-rx-flow and net...
2) Independent API for drivers offloads, the use of the existing TC
action infrastructure makes it slightly hard to visibilize what drivers
are currently supporting in terms of features. Moreover, no more
exposure of TC software representation to drivers, so future
software changes to TC won't need to be propagated to drivers, which
might accidentally break existing hardware offload codebase in case
the software frontend gets extended with some new features.
There is still room for more future work, such as introduce more common
infrastructure: Most drivers use a hashtable to represent the hardware
table indexed by the cookie, it should be possible to share this.
I made basic testing for this initial RFC, so more extensive to ensure
things don't break might be needed still. That would happen in a later
stage if feedback is positive.
Comments welcome as usual, thanks.
Pablo Neira Ayuso (10):
flow_dissector: add flow_rule and flow_match structures and use them
net/mlx5e: allow two independent packet edit actions
flow_dissector: add flow action infrastructure
cls_flower: add translator to flow_action representation
cls_flower: add statistics retrieval infrastructure and use it
drivers: net: use flow action infrastructure
cls_flower: don't expose TC actions to drivers anymore
flow_dissector: add wake-up-on-lan and queue to flow_action
flow_dissector: add basic ethtool_rx_flow_spec to flow_rule structure translator
dsa: bcm_sf2: use flow_rule infrastructure
drivers/net/dsa/bcm_sf2_cfp.c | 311 ++++-----
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 256 +++-----
.../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c | 451 ++++++-------
drivers/net/ethernet/intel/i40e/i40e_main.c | 178 ++---
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 194 +++---
drivers/net/ethernet/intel/igb/igb_main.c | 64 +-
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 725 ++++++++++-----------
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 2 +-
.../net/ethernet/mellanox/mlxsw/spectrum_flower.c | 260 ++++----
drivers/net/ethernet/netronome/nfp/flower/action.c | 194 +++---
drivers/net/ethernet/netronome/nfp/flower/match.c | 416 ++++++------
.../net/ethernet/netronome/nfp/flower/offload.c | 150 ++---
drivers/net/ethernet/qlogic/qede/qede_filter.c | 93 ++-
include/net/flow_dissector.h | 185 ++++++
include/net/pkt_cls.h | 20 +-
net/core/flow_dissector.c | 341 ++++++++++
net/sched/cls_flower.c | 151 ++++-
17 files changed, 2199 insertions(+), 1792 deletions(-)
^ permalink raw reply
* [PATCH RFC,net-next 02/10] net/mlx5e: allow two independent packet edit actions
From: Pablo Neira Ayuso @ 2018-09-25 19:19 UTC (permalink / raw)
To: netdev
Cc: davem, thomas.lendacky, f.fainelli, ariel.elior, michael.chan,
santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, ganeshgr,
jakub.kicinski, linux-net-drivers, peppe.cavallaro,
alexandre.torgue, joabreu, grygorii.strashko, andrew,
vivien.didelot
In-Reply-To: <20180925192001.2482-1-pablo@netfilter.org>
Although the packet edit infrastructure allows an arbitrary number of
packet mangling in the same action, it is still possible to define a
rule with two or more packet edit instances. This would result in the
last packet mangling action being applied to the mlx5e driver.
This patch adds pedit_headers_action struct that annotates the headers
mangling configuration that is used to configure hardware. Then,
alloc_tc_pedit_action() is called to populate the mlx5e hardware
intermediate representation once all actions have been parsed.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 77 +++++++++++++++++--------
1 file changed, 54 insertions(+), 23 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index c9d541944a14..5139e63daa74 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -1600,6 +1600,12 @@ struct pedit_headers {
struct udphdr udp;
};
+struct pedit_headers_action {
+ struct pedit_headers vals;
+ struct pedit_headers masks;
+ u32 pedits;
+};
+
static int pedit_header_offsets[] = {
[TCA_PEDIT_KEY_EX_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth),
[TCA_PEDIT_KEY_EX_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4),
@@ -1611,16 +1617,15 @@ static int pedit_header_offsets[] = {
#define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype])
static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
- struct pedit_headers *masks,
- struct pedit_headers *vals)
+ struct pedit_headers_action *hdrs)
{
u32 *curr_pmask, *curr_pval;
if (hdr_type >= __PEDIT_HDR_TYPE_MAX)
goto out_err;
- curr_pmask = (u32 *)(pedit_header(masks, hdr_type) + offset);
- curr_pval = (u32 *)(pedit_header(vals, hdr_type) + offset);
+ curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset);
+ curr_pval = (u32 *)(pedit_header(&hdrs->vals, hdr_type) + offset);
if (*curr_pmask & mask) /* disallow acting twice on the same location */
goto out_err;
@@ -1676,8 +1681,7 @@ static struct mlx5_fields fields[] = {
* max from the SW pedit action. On success, it says how many HW actions were
* actually parsed.
*/
-static int offload_pedit_fields(struct pedit_headers *masks,
- struct pedit_headers *vals,
+static int offload_pedit_fields(struct pedit_headers_action *hdrs,
struct mlx5e_tc_flow_parse_attr *parse_attr)
{
struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
@@ -1691,10 +1695,10 @@ static int offload_pedit_fields(struct pedit_headers *masks,
__be16 mask_be16;
void *action;
- set_masks = &masks[TCA_PEDIT_KEY_EX_CMD_SET];
- add_masks = &masks[TCA_PEDIT_KEY_EX_CMD_ADD];
- set_vals = &vals[TCA_PEDIT_KEY_EX_CMD_SET];
- add_vals = &vals[TCA_PEDIT_KEY_EX_CMD_ADD];
+ set_masks = &hdrs[TCA_PEDIT_KEY_EX_CMD_SET].masks;
+ add_masks = &hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].masks;
+ set_vals = &hdrs[TCA_PEDIT_KEY_EX_CMD_SET].vals;
+ add_vals = &hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].vals;
action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
action = parse_attr->mod_hdr_actions;
@@ -1784,12 +1788,12 @@ static int offload_pedit_fields(struct pedit_headers *masks,
}
static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
- const struct tc_action *a, int namespace,
+ u32 pedits, int namespace,
struct mlx5e_tc_flow_parse_attr *parse_attr)
{
int nkeys, action_size, max_actions;
- nkeys = tcf_pedit_nkeys(a);
+ nkeys = pedits;
action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
if (namespace == MLX5_FLOW_NAMESPACE_FDB) /* FDB offloading */
@@ -1812,17 +1816,15 @@ static const struct pedit_headers zero_masks = {};
static int parse_tc_pedit_action(struct mlx5e_priv *priv,
const struct tc_action *a, int namespace,
- struct mlx5e_tc_flow_parse_attr *parse_attr)
+ struct mlx5e_tc_flow_parse_attr *parse_attr,
+ struct pedit_headers_action *hdrs)
{
- struct pedit_headers masks[__PEDIT_CMD_MAX], vals[__PEDIT_CMD_MAX], *cmd_masks;
int nkeys, i, err = -EOPNOTSUPP;
u32 mask, val, offset;
u8 cmd, htype;
nkeys = tcf_pedit_nkeys(a);
-
- memset(masks, 0, sizeof(struct pedit_headers) * __PEDIT_CMD_MAX);
- memset(vals, 0, sizeof(struct pedit_headers) * __PEDIT_CMD_MAX);
+ hdrs->pedits += nkeys;
for (i = 0; i < nkeys; i++) {
htype = tcf_pedit_htype(a, i);
@@ -1843,21 +1845,34 @@ static int parse_tc_pedit_action(struct mlx5e_priv *priv,
val = tcf_pedit_val(a, i);
offset = tcf_pedit_offset(a, i);
- err = set_pedit_val(htype, ~mask, val, offset, &masks[cmd], &vals[cmd]);
+ err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd]);
if (err)
goto out_err;
}
- err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
+ return 0;
+out_err:
+ return err;
+}
+
+static int alloc_tc_pedit_action(struct mlx5e_priv *priv, int namespace,
+ struct mlx5e_tc_flow_parse_attr *parse_attr,
+ struct pedit_headers_action *hdrs)
+{
+ struct pedit_headers *cmd_masks;
+ int err;
+ u8 cmd;
+
+ err = alloc_mod_hdr_actions(priv, hdrs->pedits, namespace, parse_attr);
if (err)
goto out_err;
- err = offload_pedit_fields(masks, vals, parse_attr);
+ err = offload_pedit_fields(hdrs, parse_attr);
if (err < 0)
goto out_dealloc_parsed_actions;
for (cmd = 0; cmd < __PEDIT_CMD_MAX; cmd++) {
- cmd_masks = &masks[cmd];
+ cmd_masks = &hdrs[cmd].masks;
if (memcmp(cmd_masks, &zero_masks, sizeof(zero_masks))) {
netdev_warn(priv->netdev, "attempt to offload an unsupported field (cmd %d)\n", cmd);
print_hex_dump(KERN_WARNING, "mask: ", DUMP_PREFIX_ADDRESS,
@@ -1984,6 +1999,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
struct mlx5e_tc_flow_parse_attr *parse_attr,
struct mlx5e_tc_flow *flow)
{
+ struct pedit_headers_action hdrs[__PEDIT_CMD_MAX] = {};
struct mlx5_nic_flow_attr *attr = flow->nic_attr;
const struct tc_action *a;
LIST_HEAD(actions);
@@ -2006,7 +2022,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
if (is_tcf_pedit(a)) {
err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_KERNEL,
- parse_attr);
+ parse_attr, hdrs);
if (err)
return err;
@@ -2057,6 +2073,13 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
return -EINVAL;
}
+ if (hdrs->pedits) {
+ err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL,
+ parse_attr, hdrs);
+ if (err)
+ return err;
+ }
+
attr->action = action;
if (!actions_match_supported(priv, exts, parse_attr, flow))
return -EOPNOTSUPP;
@@ -2593,6 +2616,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
struct mlx5e_tc_flow_parse_attr *parse_attr,
struct mlx5e_tc_flow *flow)
{
+ struct pedit_headers_action hdrs[__PEDIT_CMD_MAX] = {};
struct mlx5_esw_flow_attr *attr = flow->esw_attr;
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct ip_tunnel_info *info = NULL;
@@ -2617,7 +2641,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
if (is_tcf_pedit(a)) {
err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_FDB,
- parse_attr);
+ parse_attr, hdrs);
if (err)
return err;
@@ -2699,6 +2723,13 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
return -EINVAL;
}
+ if (hdrs->pedits) {
+ err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL,
+ parse_attr, hdrs);
+ if (err)
+ return err;
+ }
+
attr->action = action;
if (!actions_match_supported(priv, exts, parse_attr, flow))
return -EOPNOTSUPP;
--
2.11.0
^ permalink raw reply related
* [PATCH RFC,net-next 03/10] flow_dissector: add flow action infrastructure
From: Pablo Neira Ayuso @ 2018-09-25 19:19 UTC (permalink / raw)
To: netdev
Cc: davem, thomas.lendacky, f.fainelli, ariel.elior, michael.chan,
santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, ganeshgr,
jakub.kicinski, linux-net-drivers, peppe.cavallaro,
alexandre.torgue, joabreu, grygorii.strashko, andrew,
vivien.didelot
In-Reply-To: <20180925192001.2482-1-pablo@netfilter.org>
This patch adds new infrastructure that defines actions that you can
perform in existing network drivers. This infrastructure allows us to
avoid the direct dependency with the software TC action infrastructure.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/flow_dissector.h | 70 ++++++++++++++++++++++++++++++++++++++++++++
net/core/flow_dissector.c | 18 ++++++++++++
2 files changed, 88 insertions(+)
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index 965a82b8d881..925c208816f1 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -402,8 +402,78 @@ void flow_rule_match_enc_keyid(const struct flow_rule *rule,
void flow_rule_match_enc_opts(const struct flow_rule *rule,
struct flow_match_enc_opts *out);
+enum flow_action_key_id {
+ FLOW_ACTION_KEY_ACCEPT = 0,
+ FLOW_ACTION_KEY_DROP,
+ FLOW_ACTION_KEY_TRAP,
+ FLOW_ACTION_KEY_GOTO,
+ FLOW_ACTION_KEY_REDIRECT,
+ FLOW_ACTION_KEY_MIRRED,
+ FLOW_ACTION_KEY_VLAN_PUSH,
+ FLOW_ACTION_KEY_VLAN_POP,
+ FLOW_ACTION_KEY_VLAN_MANGLE,
+ FLOW_ACTION_KEY_TUNNEL_ENCAP,
+ FLOW_ACTION_KEY_TUNNEL_DECAP,
+ FLOW_ACTION_KEY_MANGLE,
+ FLOW_ACTION_KEY_ADD,
+ FLOW_ACTION_KEY_CSUM,
+ FLOW_ACTION_KEY_MARK,
+};
+
+/* This is mirroring enum pedit_header_type definition for easy mapping between
+ * tc pedit action. Legacy TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK is mapped to
+ * FLOW_ACT_MANGLE_UNSPEC, which is supported by no driver.
+ */
+enum flow_act_mangle_base {
+ FLOW_ACT_MANGLE_UNSPEC = 0,
+ FLOW_ACT_MANGLE_HDR_TYPE_ETH,
+ FLOW_ACT_MANGLE_HDR_TYPE_IP4,
+ FLOW_ACT_MANGLE_HDR_TYPE_IP6,
+ FLOW_ACT_MANGLE_HDR_TYPE_TCP,
+ FLOW_ACT_MANGLE_HDR_TYPE_UDP,
+};
+
+struct flow_action_key {
+ enum flow_action_key_id id;
+ union {
+ u32 chain_index; /* FLOW_ACTION_KEY_GOTO */
+ struct net_device *dev; /* FLOW_ACTION_KEY_REDIRECT */
+ struct { /* FLOW_ACTION_KEY_VLAN */
+ u16 vid;
+ __be16 proto;
+ u8 prio;
+ } vlan;
+ struct { /* FLOW_ACTION_KEY_PACKET_EDIT */
+ enum flow_act_mangle_base htype;
+ u32 offset;
+ u32 mask;
+ u32 val;
+ } mangle;
+ const struct ip_tunnel_info *tunnel; /* FLOW_ACTION_KEY_TUNNEL_ENCAP */
+ u32 csum_flags; /* FLOW_ACTION_KEY_CSUM */
+ u32 mark; /* FLOW_ACTION_KEY_MARK */
+ };
+};
+
+struct flow_action {
+ int num_keys;
+ struct flow_action_key *keys;
+};
+
+int flow_action_init(struct flow_action *flow_action, int num_acts);
+void flow_action_free(struct flow_action *flow_action);
+
+static inline bool flow_action_has_keys(const struct flow_action *action)
+{
+ return action->num_keys;
+}
+
+#define flow_action_for_each(__i, __act, __actions) \
+ for (__i = 0, __act = &(__actions)->keys[0]; __i < (__actions)->num_keys; __act = &(__actions)->keys[++__i])
+
struct flow_rule {
struct flow_match match;
+ struct flow_action action;
};
static inline bool flow_rule_match_key(const struct flow_rule *rule,
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 5a22381efccc..e25b235a8e10 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -195,6 +195,24 @@ void flow_rule_match_enc_opts(const struct flow_rule *rule,
}
EXPORT_SYMBOL(flow_rule_match_enc_opts);
+int flow_action_init(struct flow_action *flow_action, int num_acts)
+{
+ flow_action->keys = kmalloc(sizeof(struct flow_action_key) * num_acts,
+ GFP_KERNEL);
+ if (!flow_action->keys)
+ return -ENOMEM;
+
+ flow_action->num_keys = num_acts;
+ return 0;
+}
+EXPORT_SYMBOL(flow_action_init);
+
+void flow_action_free(struct flow_action *flow_action)
+{
+ kfree(flow_action->keys);
+}
+EXPORT_SYMBOL(flow_action_free);
+
/**
* skb_flow_get_be16 - extract be16 entity
* @skb: sk_buff to extract from
--
2.11.0
^ permalink raw reply related
* [PATCH RFC,net-next 04/10] cls_flower: add translator to flow_action representation
From: Pablo Neira Ayuso @ 2018-09-25 19:19 UTC (permalink / raw)
To: netdev
Cc: davem, thomas.lendacky, f.fainelli, ariel.elior, michael.chan,
santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, ganeshgr,
jakub.kicinski, linux-net-drivers, peppe.cavallaro,
alexandre.torgue, joabreu, grygorii.strashko, andrew,
vivien.didelot
In-Reply-To: <20180925192001.2482-1-pablo@netfilter.org>
This implements TC action to flow_action translation from cls_flower.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/sched/cls_flower.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 123 insertions(+), 1 deletion(-)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index e1dd60a2ecb8..a96a80f01c6d 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -28,6 +28,14 @@
#include <net/dst.h>
#include <net/dst_metadata.h>
+#include <net/tc_act/tc_mirred.h>
+#include <net/tc_act/tc_vlan.h>
+#include <net/tc_act/tc_tunnel_key.h>
+#include <net/tc_act/tc_pedit.h>
+#include <net/tc_act/tc_csum.h>
+#include <net/tc_act/tc_gact.h>
+#include <net/tc_act/tc_skbedit.h>
+#include <net/tc_act/tc_mirred.h>
struct fl_flow_key {
int indev_ifindex;
@@ -101,6 +109,7 @@ struct cls_fl_filter {
u32 in_hw_count;
struct rcu_work rwork;
struct net_device *hw_dev;
+ struct flow_action action;
};
static const struct rhashtable_params mask_ht_params = {
@@ -294,6 +303,107 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f,
tcf_block_offload_dec(block, &f->flags);
}
+static int fl_hw_setup_action(struct flow_action *flow_action,
+ const struct tcf_exts *exts)
+{
+ const struct tc_action *act;
+ int num_acts = 0, i, j, k;
+
+ if (!exts)
+ return 0;
+
+ tcf_exts_for_each_action(i, act, exts) {
+ if (is_tcf_pedit(act))
+ num_acts += tcf_pedit_nkeys(act);
+ else
+ num_acts++;
+ }
+
+ if (!num_acts)
+ return 0;
+
+ if (flow_action_init(flow_action, num_acts) < 0)
+ return -ENOMEM;
+
+ j = 0;
+ tcf_exts_for_each_action(i, act, exts) {
+ struct flow_action_key *key;
+
+ key = &flow_action->keys[j];
+ if (is_tcf_gact_ok(act)) {
+ key->id = FLOW_ACTION_KEY_ACCEPT;
+ } else if (is_tcf_gact_shot(act)) {
+ key->id = FLOW_ACTION_KEY_DROP;
+ } else if (is_tcf_gact_trap(act)) {
+ key->id = FLOW_ACTION_KEY_TRAP;
+ } else if (is_tcf_gact_goto_chain(act)) {
+ key->id = FLOW_ACTION_KEY_GOTO;
+ key->chain_index = tcf_gact_goto_chain_index(act);
+ } else if (is_tcf_mirred_egress_redirect(act)) {
+ key->id = FLOW_ACTION_KEY_REDIRECT;
+ key->dev = tcf_mirred_dev(act);
+ } else if (is_tcf_mirred_egress_mirror(act)) {
+ key->id = FLOW_ACTION_KEY_MIRRED;
+ key->dev = tcf_mirred_dev(act);
+ } else if (is_tcf_vlan(act)) {
+ switch (tcf_vlan_action(act)) {
+ case TCA_VLAN_ACT_PUSH:
+ key->id = FLOW_ACTION_KEY_VLAN_PUSH;
+ key->vlan.vid = tcf_vlan_push_vid(act);
+ key->vlan.proto = tcf_vlan_push_proto(act);
+ key->vlan.prio = tcf_vlan_push_prio(act);
+ break;
+ case TCA_VLAN_ACT_POP:
+ key->id = FLOW_ACTION_KEY_VLAN_POP;
+ break;
+ case TCA_VLAN_ACT_MODIFY:
+ key->id = FLOW_ACTION_KEY_VLAN_MANGLE;
+ key->vlan.vid = tcf_vlan_push_vid(act);
+ key->vlan.proto = tcf_vlan_push_proto(act);
+ key->vlan.prio = tcf_vlan_push_prio(act);
+ break;
+ }
+ } else if (is_tcf_tunnel_set(act)) {
+ key->id = FLOW_ACTION_KEY_TUNNEL_ENCAP;
+ key->tunnel = tcf_tunnel_info(act);
+ } else if (is_tcf_tunnel_release(act)) {
+ key->id = FLOW_ACTION_KEY_TUNNEL_DECAP;
+ key->tunnel = tcf_tunnel_info(act);
+ } else if (is_tcf_pedit(act)) {
+ for (k = 0; k < tcf_pedit_nkeys(act); k++) {
+ switch (tcf_pedit_cmd(act, k)) {
+ case TCA_PEDIT_KEY_EX_CMD_SET:
+ key->id = FLOW_ACTION_KEY_MANGLE;
+ break;
+ case TCA_PEDIT_KEY_EX_CMD_ADD:
+ key->id = FLOW_ACTION_KEY_ADD;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ key->mangle.htype = tcf_pedit_htype(act, k);
+ key->mangle.mask = tcf_pedit_mask(act, k);
+ key->mangle.val = tcf_pedit_val(act, k);
+ key->mangle.offset = tcf_pedit_offset(act, k);
+ key = &flow_action->keys[++j];
+ }
+ } else if (is_tcf_csum(act)) {
+ key->id = FLOW_ACTION_KEY_CSUM;
+ key->csum_flags = tcf_csum_update_flags(act);
+ } else if (is_tcf_skbedit_mark(act)) {
+ key->id = FLOW_ACTION_KEY_MARK;
+ key->mark = tcf_skbedit_mark(act);
+ }
+
+ if (!is_tcf_pedit(act))
+ j++;
+ }
+
+ return 0;
+}
+
static int fl_hw_replace_filter(struct tcf_proto *tp,
struct cls_fl_filter *f,
struct netlink_ext_ack *extack)
@@ -312,18 +422,27 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
cls_flower.exts = &f->exts;
cls_flower.classid = f->res.classid;
+ if (fl_hw_setup_action(&f->action, &f->exts) < 0)
+ return -ENOMEM;
+
+ cls_flower.rule.action.keys = f->action.keys;
+ cls_flower.rule.action.num_keys = f->action.num_keys;
+
err = tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
&cls_flower, skip_sw);
if (err < 0) {
fl_hw_destroy_filter(tp, f, NULL);
+ flow_action_free(&f->action);
return err;
} else if (err > 0) {
f->in_hw_count = err;
tcf_block_offload_inc(block, &f->flags);
}
- if (skip_sw && !(f->flags & TCA_CLS_FLAGS_IN_HW))
+ if (skip_sw && !(f->flags & TCA_CLS_FLAGS_IN_HW)) {
+ flow_action_free(&f->action);
return -EINVAL;
+ }
return 0;
}
@@ -350,6 +469,7 @@ static bool __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f,
bool async = tcf_exts_get_net(&f->exts);
bool last;
+ flow_action_free(&f->action);
idr_remove(&head->handle_idr, f->handle);
list_del_rcu(&f->list);
last = fl_mask_put(head, f->mask, async);
@@ -1341,6 +1461,8 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
cls_flower.rule.match.mask = &mask->key;
cls_flower.rule.match.key = &f->mkey;
cls_flower.exts = &f->exts;
+ cls_flower.rule.action.num_keys = f->action.num_keys;
+ cls_flower.rule.action.keys = f->action.keys;
cls_flower.classid = f->res.classid;
err = cb(TC_SETUP_CLSFLOWER, &cls_flower, cb_priv);
--
2.11.0
^ permalink raw reply related
* [PATCH RFC,net-next 05/10] cls_flower: add statistics retrieval infrastructure and use it
From: Pablo Neira Ayuso @ 2018-09-25 19:19 UTC (permalink / raw)
To: netdev
Cc: davem, thomas.lendacky, f.fainelli, ariel.elior, michael.chan,
santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, ganeshgr,
jakub.kicinski, linux-net-drivers, peppe.cavallaro,
alexandre.torgue, joabreu, grygorii.strashko, andrew,
vivien.didelot
In-Reply-To: <20180925192001.2482-1-pablo@netfilter.org>
Provide a tc_cls_flower_stats structure that acts as container for
tc_cls_flower_offload, then restore stats on the TC actions. Hence
tcf_exts_stats_update() is not used from drivers.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 4 ++--
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c | 6 +++---
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c | 2 +-
drivers/net/ethernet/netronome/nfp/flower/offload.c | 4 ++--
include/net/pkt_cls.h | 15 +++++++++++++++
net/sched/cls_flower.c | 4 ++++
7 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index 62652ffc8221..3505791777e7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -1358,8 +1358,8 @@ static int bnxt_tc_get_flow_stats(struct bnxt *bp,
lastused = flow->lastused;
spin_unlock(&flow->stats_lock);
- tcf_exts_stats_update(tc_flow_cmd->exts, stats.bytes, stats.packets,
- lastused);
+ tc_cls_flower_stats_update(tc_flow_cmd, stats.bytes, stats.packets,
+ lastused);
return 0;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index cff9d854bf51..74fe2ee4636e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -807,9 +807,9 @@ int cxgb4_tc_flower_stats(struct net_device *dev,
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);
+ tc_cls_flower_stats_update(cls, bytes - ofld_stats->byte_count,
+ packets - ofld_stats->packet_count,
+ ofld_stats->last_used);
ofld_stats->packet_count = packets;
ofld_stats->byte_count = bytes;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 5139e63daa74..bb29060c0351 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -2906,7 +2906,7 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
- tcf_exts_stats_update(f->exts, bytes, packets, lastuse);
+ tc_cls_flower_stats_update(f, bytes, packets, lastuse);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
index 773dba2067ed..b3668b578e84 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
@@ -461,7 +461,7 @@ int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_rule_get_stats;
- tcf_exts_stats_update(f->exts, bytes, packets, lastuse);
+ tc_cls_flower_stats_update(f, bytes, packets, lastuse);
mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset);
return 0;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index 5a9986fccfa4..fbfec64767fb 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -577,8 +577,8 @@ nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev,
return 0;
spin_lock_bh(&nfp_flow->lock);
- tcf_exts_stats_update(flow->exts, nfp_flow->stats.bytes,
- nfp_flow->stats.pkts, nfp_flow->stats.used);
+ tc_cls_flower_stats_update(flow, nfp_flow->stats.bytes,
+ nfp_flow->stats.pkts, nfp_flow->stats.used);
nfp_flow->stats.pkts = 0;
nfp_flow->stats.bytes = 0;
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index bc145265ebd5..c8e61e8b0257 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -731,6 +731,12 @@ enum tc_fl_command {
TC_CLSFLOWER_TMPLT_DESTROY,
};
+struct tc_cls_flower_stats {
+ u64 pkts;
+ u64 bytes;
+ u64 lastused;
+};
+
struct tc_cls_flower_offload {
struct tc_cls_common_offload common;
enum tc_fl_command command;
@@ -738,8 +744,17 @@ struct tc_cls_flower_offload {
struct flow_rule rule;
struct tcf_exts *exts;
u32 classid;
+ struct tc_cls_flower_stats stats;
};
+static inline void tc_cls_flower_stats_update(struct tc_cls_flower_offload *cls_flower,
+ u64 pkts, u64 bytes, u64 lastused)
+{
+ cls_flower->stats.pkts = pkts;
+ cls_flower->stats.bytes = bytes;
+ cls_flower->stats.lastused = lastused;
+}
+
enum tc_matchall_command {
TC_CLSMATCHALL_REPLACE,
TC_CLSMATCHALL_DESTROY,
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index a96a80f01c6d..a89f3370718f 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -460,6 +460,10 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
&cls_flower, false);
+
+ tcf_exts_stats_update(&f->exts, cls_flower.stats.bytes,
+ cls_flower.stats.pkts,
+ cls_flower.stats.lastused);
}
static bool __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f,
--
2.11.0
^ permalink raw reply related
* [PATCH RFC,net-next 08/10] flow_dissector: add wake-up-on-lan and queue to flow_action
From: Pablo Neira Ayuso @ 2018-09-25 19:19 UTC (permalink / raw)
To: netdev
Cc: davem, thomas.lendacky, f.fainelli, ariel.elior, michael.chan,
santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, ganeshgr,
jakub.kicinski, linux-net-drivers, peppe.cavallaro,
alexandre.torgue, joabreu, grygorii.strashko, andrew,
vivien.didelot
In-Reply-To: <20180925192001.2482-1-pablo@netfilter.org>
These actions need to be added to support bcm sf2 features available
through the ethtool_rx_flow interface.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/flow_dissector.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index 925c208816f1..7a4683646d5a 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -418,6 +418,8 @@ enum flow_action_key_id {
FLOW_ACTION_KEY_ADD,
FLOW_ACTION_KEY_CSUM,
FLOW_ACTION_KEY_MARK,
+ FLOW_ACTION_KEY_WAKE,
+ FLOW_ACTION_KEY_QUEUE,
};
/* This is mirroring enum pedit_header_type definition for easy mapping between
@@ -452,6 +454,7 @@ struct flow_action_key {
const struct ip_tunnel_info *tunnel; /* FLOW_ACTION_KEY_TUNNEL_ENCAP */
u32 csum_flags; /* FLOW_ACTION_KEY_CSUM */
u32 mark; /* FLOW_ACTION_KEY_MARK */
+ u32 queue_index; /* FLOW_ACTION_KEY_QUEUE */
};
};
--
2.11.0
^ permalink raw reply related
* [PATCH RFC,net-next 07/10] cls_flower: don't expose TC actions to drivers anymore
From: Pablo Neira Ayuso @ 2018-09-25 19:19 UTC (permalink / raw)
To: netdev
Cc: davem, thomas.lendacky, f.fainelli, ariel.elior, michael.chan,
santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, ganeshgr,
jakub.kicinski, linux-net-drivers, peppe.cavallaro,
alexandre.torgue, joabreu, grygorii.strashko, andrew,
vivien.didelot
In-Reply-To: <20180925192001.2482-1-pablo@netfilter.org>
Now that drivers have been converted to use the flow action
infrastructure, remove this field from the tc_cls_flower_offload
structure.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/pkt_cls.h | 1 -
net/sched/cls_flower.c | 5 -----
2 files changed, 6 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index c8e61e8b0257..a6317baff462 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -742,7 +742,6 @@ struct tc_cls_flower_offload {
enum tc_fl_command command;
unsigned long cookie;
struct flow_rule rule;
- struct tcf_exts *exts;
u32 classid;
struct tc_cls_flower_stats stats;
};
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index a89f3370718f..e7fcd5e9ba1e 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -419,7 +419,6 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
cls_flower.rule.match.dissector = &f->mask->dissector;
cls_flower.rule.match.mask = &f->mask->key;
cls_flower.rule.match.key = &f->mkey;
- cls_flower.exts = &f->exts;
cls_flower.classid = f->res.classid;
if (fl_hw_setup_action(&f->action, &f->exts) < 0)
@@ -455,7 +454,6 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
tc_cls_common_offload_init(&cls_flower.common, tp, f->flags, NULL);
cls_flower.command = TC_CLSFLOWER_STATS;
cls_flower.cookie = (unsigned long) f;
- cls_flower.exts = &f->exts;
cls_flower.classid = f->res.classid;
tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
@@ -1464,7 +1462,6 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
cls_flower.rule.match.dissector = &mask->dissector;
cls_flower.rule.match.mask = &mask->key;
cls_flower.rule.match.key = &f->mkey;
- cls_flower.exts = &f->exts;
cls_flower.rule.action.num_keys = f->action.num_keys;
cls_flower.rule.action.keys = f->action.keys;
cls_flower.classid = f->res.classid;
@@ -1489,7 +1486,6 @@ static void fl_hw_create_tmplt(struct tcf_chain *chain,
{
struct tc_cls_flower_offload cls_flower = {};
struct tcf_block *block = chain->block;
- struct tcf_exts dummy_exts = { 0, };
cls_flower.common.chain_index = chain->index;
cls_flower.command = TC_CLSFLOWER_TMPLT_CREATE;
@@ -1497,7 +1493,6 @@ static void fl_hw_create_tmplt(struct tcf_chain *chain,
cls_flower.rule.match.dissector = &tmplt->dissector;
cls_flower.rule.match.mask = &tmplt->mask;
cls_flower.rule.match.key = &tmplt->dummy_key;
- cls_flower.exts = &dummy_exts;
/* We don't care if driver (any of them) fails to handle this
* call. It serves just as a hint for it.
--
2.11.0
^ permalink raw reply related
* [PATCH RFC,net-next 09/10] flow_dissector: add basic ethtool_rx_flow_spec to flow_rule structure translator
From: Pablo Neira Ayuso @ 2018-09-25 19:20 UTC (permalink / raw)
To: netdev
Cc: davem, thomas.lendacky, f.fainelli, ariel.elior, michael.chan,
santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, ganeshgr,
jakub.kicinski, linux-net-drivers, peppe.cavallaro,
alexandre.torgue, joabreu, grygorii.strashko, andrew,
vivien.didelot
In-Reply-To: <20180925192001.2482-1-pablo@netfilter.org>
This patch adds a function to translate the ethtool_rx_flow_spec
structure to the flow_rule representation.
This allows us to reuse code from the driver side given the flower and
the ethtool_rx_flow interface use the same representation.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/flow_dissector.h | 5 ++
net/core/flow_dissector.c | 190 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 195 insertions(+)
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index 7a4683646d5a..ec9036232538 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -485,4 +485,9 @@ static inline bool flow_rule_match_key(const struct flow_rule *rule,
return dissector_uses_key(rule->match.dissector, key);
}
+struct ethtool_rx_flow_spec;
+
+struct flow_rule *ethtool_rx_flow_rule(const struct ethtool_rx_flow_spec *fs);
+void ethtool_rx_flow_rule_free(struct flow_rule *rule);
+
#endif
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index e25b235a8e10..73c9c7d29cd3 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -25,6 +25,7 @@
#include <net/flow_dissector.h>
#include <scsi/fc/fc_fcoe.h>
#include <uapi/linux/batadv_packet.h>
+#include <uapi/linux/ethtool.h>
static void dissector_set_key(struct flow_dissector *flow_dissector,
enum flow_dissector_key_id key_id)
@@ -213,6 +214,195 @@ void flow_action_free(struct flow_action *flow_action)
}
EXPORT_SYMBOL(flow_action_free);
+struct ethtool_rx_flow_key {
+ struct flow_dissector_key_basic basic;
+ union {
+ struct flow_dissector_key_ipv4_addrs ipv4;
+ struct flow_dissector_key_ipv6_addrs ipv6;
+ };
+ struct flow_dissector_key_ports tp;
+ struct flow_dissector_key_ip ip;
+} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
+
+struct ethtool_rx_flow_match {
+ struct flow_dissector dissector;
+ struct ethtool_rx_flow_key key;
+ struct ethtool_rx_flow_key mask;
+};
+
+struct flow_rule *ethtool_rx_flow_rule(const struct ethtool_rx_flow_spec *fs)
+{
+ static struct in6_addr zero_addr = {};
+ struct ethtool_rx_flow_match *match;
+ struct flow_action_key *act;
+ struct flow_rule *rule;
+
+ rule = kmalloc(sizeof(struct flow_rule), GFP_KERNEL);
+ if (!rule)
+ return NULL;
+
+ match = kzalloc(sizeof(struct ethtool_rx_flow_match), GFP_KERNEL);
+ if (!match)
+ goto err_match;
+
+ rule->match.dissector = &match->dissector;
+ rule->match.mask = &match->mask;
+ rule->match.key = &match->key;
+
+ match->mask.basic.n_proto = 0xffff;
+
+ switch (fs->flow_type & ~FLOW_EXT) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW: {
+ const struct ethtool_tcpip4_spec *v4_spec, *v4_m_spec;
+
+ match->key.basic.n_proto = htons(ETH_P_IP);
+
+ v4_spec = &fs->h_u.tcp_ip4_spec;
+ v4_m_spec = &fs->m_u.tcp_ip4_spec;
+
+ if (v4_m_spec->ip4src) {
+ match->key.ipv4.src = v4_spec->ip4src;
+ match->mask.ipv4.src = v4_m_spec->ip4src;
+ }
+ if (v4_m_spec->ip4dst) {
+ match->key.ipv4.dst = v4_spec->ip4dst;
+ match->mask.ipv4.dst = v4_m_spec->ip4dst;
+ }
+ if (v4_m_spec->ip4src ||
+ v4_m_spec->ip4dst) {
+ match->dissector.used_keys |=
+ FLOW_DISSECTOR_KEY_IPV4_ADDRS;
+ match->dissector.offset[FLOW_DISSECTOR_KEY_IPV4_ADDRS] =
+ offsetof(struct ethtool_rx_flow_key, ipv4);
+ }
+ if (v4_m_spec->psrc) {
+ match->key.tp.src = v4_spec->psrc;
+ match->mask.tp.src = v4_m_spec->psrc;
+ }
+ if (v4_m_spec->pdst) {
+ match->key.tp.dst = v4_spec->pdst;
+ match->mask.tp.dst = v4_m_spec->pdst;
+ }
+ if (v4_m_spec->psrc ||
+ v4_m_spec->pdst) {
+ match->dissector.used_keys |= FLOW_DISSECTOR_KEY_PORTS;
+ match->dissector.offset[FLOW_DISSECTOR_KEY_PORTS] =
+ offsetof(struct ethtool_rx_flow_key, tp);
+ }
+ if (v4_m_spec->tos) {
+ match->key.ip.tos = v4_spec->pdst;
+ match->mask.ip.tos = v4_m_spec->pdst;
+ match->dissector.used_keys |= FLOW_DISSECTOR_KEY_IP;
+ match->dissector.offset[FLOW_DISSECTOR_KEY_IP] =
+ offsetof(struct ethtool_rx_flow_key, ip);
+ }
+ }
+ break;
+ case TCP_V6_FLOW:
+ case UDP_V6_FLOW: {
+ const struct ethtool_tcpip6_spec *v6_spec, *v6_m_spec;
+
+ match->key.basic.n_proto = htons(ETH_P_IPV6);
+
+ v6_spec = &fs->h_u.tcp_ip6_spec;
+ v6_m_spec = &fs->m_u.tcp_ip6_spec;
+ if (memcmp(v6_m_spec->ip6src, &zero_addr, sizeof(zero_addr))) {
+ memcpy(&match->key.ipv6.src, v6_spec->ip6src,
+ sizeof(match->key.ipv6.src));
+ memcpy(&match->mask.ipv6.src, v6_m_spec->ip6src,
+ sizeof(match->mask.ipv6.src));
+ }
+ if (memcmp(v6_m_spec->ip6dst, &zero_addr, sizeof(zero_addr))) {
+ memcpy(&match->key.ipv6.dst, v6_spec->ip6dst,
+ sizeof(match->key.ipv6.dst));
+ memcpy(&match->mask.ipv6.dst, v6_m_spec->ip6dst,
+ sizeof(match->mask.ipv6.dst));
+ }
+ if (memcmp(v6_m_spec->ip6src, &zero_addr, sizeof(zero_addr)) ||
+ memcmp(v6_m_spec->ip6src, &zero_addr, sizeof(zero_addr))) {
+ match->dissector.used_keys |=
+ FLOW_DISSECTOR_KEY_IPV6_ADDRS;
+ match->dissector.offset[FLOW_DISSECTOR_KEY_IPV6_ADDRS] =
+ offsetof(struct ethtool_rx_flow_key, ipv6);
+ }
+ if (v6_m_spec->psrc) {
+ match->key.tp.src = v6_spec->psrc;
+ match->mask.tp.src = v6_m_spec->psrc;
+ }
+ if (v6_m_spec->pdst) {
+ match->key.tp.dst = v6_spec->pdst;
+ match->mask.tp.dst = v6_m_spec->pdst;
+ }
+ if (v6_m_spec->psrc ||
+ v6_m_spec->pdst) {
+ match->dissector.used_keys |= FLOW_DISSECTOR_KEY_PORTS;
+ match->dissector.offset[FLOW_DISSECTOR_KEY_PORTS] =
+ offsetof(struct ethtool_rx_flow_key, tp);
+ }
+ if (v6_m_spec->tclass) {
+ match->key.ip.tos = v6_spec->tclass;
+ match->mask.ip.tos = v6_m_spec->tclass;
+ match->dissector.used_keys |= FLOW_DISSECTOR_KEY_IP;
+ match->dissector.offset[FLOW_DISSECTOR_KEY_IP] =
+ offsetof(struct ethtool_rx_flow_key, ip);
+ }
+ }
+ break;
+ }
+
+ switch (fs->flow_type & ~FLOW_EXT) {
+ case TCP_V4_FLOW:
+ case TCP_V6_FLOW:
+ match->key.basic.ip_proto = IPPROTO_TCP;
+ break;
+ case UDP_V4_FLOW:
+ case UDP_V6_FLOW:
+ match->key.basic.ip_proto = IPPROTO_UDP;
+ break;
+ }
+ match->mask.basic.ip_proto = 0xff;
+
+ match->dissector.used_keys |= FLOW_DISSECTOR_KEY_BASIC;
+ match->dissector.offset[FLOW_DISSECTOR_KEY_BASIC] =
+ offsetof(struct ethtool_rx_flow_key, basic);
+
+ /* ethtool_rx supports only one single action per rule. */
+ if (flow_action_init(&rule->action, 1) < 0)
+ goto err_action;
+
+ act = &rule->action.keys[0];
+ switch (fs->ring_cookie) {
+ case RX_CLS_FLOW_DISC:
+ act->id = FLOW_ACTION_KEY_DROP;
+ break;
+ case RX_CLS_FLOW_WAKE:
+ act->id = FLOW_ACTION_KEY_WAKE;
+ break;
+ default:
+ act->id = FLOW_ACTION_KEY_QUEUE;
+ act->queue_index = fs->ring_cookie;
+ break;
+ }
+
+ return rule;
+
+err_action:
+ kfree(match);
+err_match:
+ kfree(rule);
+ return NULL;
+}
+EXPORT_SYMBOL(ethtool_rx_flow_rule);
+
+void ethtool_rx_flow_rule_free(struct flow_rule *rule)
+{
+ kfree((struct flow_match *)rule->match.dissector);
+ flow_action_free(&rule->action);
+ kfree(rule);
+}
+EXPORT_SYMBOL(ethtool_rx_flow_rule_free);
+
/**
* skb_flow_get_be16 - extract be16 entity
* @skb: sk_buff to extract from
--
2.11.0
^ permalink raw reply related
* [PATCH RFC,net-next 10/10] dsa: bcm_sf2: use flow_rule infrastructure
From: Pablo Neira Ayuso @ 2018-09-25 19:20 UTC (permalink / raw)
To: netdev
Cc: davem, thomas.lendacky, f.fainelli, ariel.elior, michael.chan,
santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, ganeshgr,
jakub.kicinski, linux-net-drivers, peppe.cavallaro,
alexandre.torgue, joabreu, grygorii.strashko, andrew,
vivien.didelot
In-Reply-To: <20180925192001.2482-1-pablo@netfilter.org>
Update this driver to use the flow_rule infrastructure, hence the same
code to populate hardware IR can be used from ethtool_rx_flow and the
cls_flower interfaces.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
drivers/net/dsa/bcm_sf2_cfp.c | 311 ++++++++++++++++++++++--------------------
1 file changed, 166 insertions(+), 145 deletions(-)
diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c
index 47c5f272a084..9dace0e25a3a 100644
--- a/drivers/net/dsa/bcm_sf2_cfp.c
+++ b/drivers/net/dsa/bcm_sf2_cfp.c
@@ -251,10 +251,12 @@ static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv,
}
static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
- struct ethtool_tcpip4_spec *v4_spec,
+ struct flow_rule *flow_rule,
unsigned int slice_num,
bool mask)
{
+ struct flow_match_ipv4_addrs ipv4;
+ struct flow_match_ports ports;
u32 reg, offset;
/* C-Tag [31:24]
@@ -268,41 +270,54 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
offset = CORE_CFP_DATA_PORT(4);
core_writel(priv, reg, offset);
+ flow_rule_match_ipv4_addrs(flow_rule, &ipv4);
+ flow_rule_match_ports(flow_rule, &ports);
+
/* UDF_n_A7 [31:24]
* UDF_n_A6 [23:8]
* UDF_n_A5 [7:0]
*/
- reg = be16_to_cpu(v4_spec->pdst) >> 8;
- if (mask)
+ if (mask) {
+ reg = be16_to_cpu(ports.mask->dst) >> 8;
offset = CORE_CFP_MASK_PORT(3);
- else
+ } else {
+ reg = be16_to_cpu(ports.key->dst) >> 8;
offset = CORE_CFP_DATA_PORT(3);
+ }
core_writel(priv, reg, offset);
/* UDF_n_A5 [31:24]
* UDF_n_A4 [23:8]
* UDF_n_A3 [7:0]
*/
- reg = (be16_to_cpu(v4_spec->pdst) & 0xff) << 24 |
- (u32)be16_to_cpu(v4_spec->psrc) << 8 |
- (be32_to_cpu(v4_spec->ip4dst) & 0x0000ff00) >> 8;
- if (mask)
+ if (mask) {
+ reg = (be16_to_cpu(ports.mask->dst) & 0xff) << 24 |
+ (u32)be16_to_cpu(ports.mask->src) << 8 |
+ (be32_to_cpu(ipv4.mask->dst) & 0x0000ff00) >> 8;
offset = CORE_CFP_MASK_PORT(2);
- else
+ } else {
+ reg = (be16_to_cpu(ports.key->dst) & 0xff) << 24 |
+ (u32)be16_to_cpu(ports.key->src) << 8 |
+ (be32_to_cpu(ipv4.key->dst) & 0x0000ff00) >> 8;
offset = CORE_CFP_DATA_PORT(2);
+ }
core_writel(priv, reg, offset);
/* UDF_n_A3 [31:24]
* UDF_n_A2 [23:8]
* UDF_n_A1 [7:0]
*/
- reg = (u32)(be32_to_cpu(v4_spec->ip4dst) & 0xff) << 24 |
- (u32)(be32_to_cpu(v4_spec->ip4dst) >> 16) << 8 |
- (be32_to_cpu(v4_spec->ip4src) & 0x0000ff00) >> 8;
- if (mask)
+ if (mask) {
+ reg = (u32)(be32_to_cpu(ipv4.mask->dst) & 0xff) << 24 |
+ (u32)(be32_to_cpu(ipv4.mask->dst) >> 16) << 8 |
+ (be32_to_cpu(ipv4.mask->src) & 0x0000ff00) >> 8;
offset = CORE_CFP_MASK_PORT(1);
- else
+ } else {
+ reg = (u32)(be32_to_cpu(ipv4.key->dst) & 0xff) << 24 |
+ (u32)(be32_to_cpu(ipv4.key->dst) >> 16) << 8 |
+ (be32_to_cpu(ipv4.key->src) & 0x0000ff00) >> 8;
offset = CORE_CFP_DATA_PORT(1);
+ }
core_writel(priv, reg, offset);
/* UDF_n_A1 [31:24]
@@ -311,56 +326,34 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
* Slice ID [3:2]
* Slice valid [1:0]
*/
- reg = (u32)(be32_to_cpu(v4_spec->ip4src) & 0xff) << 24 |
- (u32)(be32_to_cpu(v4_spec->ip4src) >> 16) << 8 |
- SLICE_NUM(slice_num) | SLICE_VALID;
- if (mask)
+ if (mask) {
+ reg = (u32)(be32_to_cpu(ipv4.mask->src) & 0xff) << 24 |
+ (u32)(be32_to_cpu(ipv4.mask->src) >> 16) << 8 |
+ SLICE_NUM(slice_num) | SLICE_VALID;
offset = CORE_CFP_MASK_PORT(0);
- else
+ } else {
+ reg = (u32)(be32_to_cpu(ipv4.key->src) & 0xff) << 24 |
+ (u32)(be32_to_cpu(ipv4.key->src) >> 16) << 8 |
+ SLICE_NUM(slice_num) | SLICE_VALID;
offset = CORE_CFP_DATA_PORT(0);
+ }
core_writel(priv, reg, offset);
}
static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
unsigned int port_num,
unsigned int queue_num,
- struct ethtool_rx_flow_spec *fs)
+ struct flow_rule *flow_rule,
+ unsigned int rule_index, u8 ip_frag)
{
- struct ethtool_tcpip4_spec *v4_spec, *v4_m_spec;
const struct cfp_udf_layout *layout;
- unsigned int slice_num, rule_index;
- u8 ip_proto, ip_frag;
+ struct flow_match_basic basic;
+ struct flow_match_ip ip;
+ unsigned int slice_num;
u8 num_udf;
u32 reg;
int ret;
- switch (fs->flow_type & ~FLOW_EXT) {
- case TCP_V4_FLOW:
- ip_proto = IPPROTO_TCP;
- v4_spec = &fs->h_u.tcp_ip4_spec;
- v4_m_spec = &fs->m_u.tcp_ip4_spec;
- break;
- case UDP_V4_FLOW:
- ip_proto = IPPROTO_UDP;
- v4_spec = &fs->h_u.udp_ip4_spec;
- v4_m_spec = &fs->m_u.udp_ip4_spec;
- break;
- default:
- return -EINVAL;
- }
-
- ip_frag = be32_to_cpu(fs->m_ext.data[0]);
-
- /* Locate the first rule available */
- if (fs->location == RX_CLS_LOC_ANY)
- rule_index = find_first_zero_bit(priv->cfp.used,
- priv->num_cfp_rules);
- else
- rule_index = fs->location;
-
- if (rule_index > bcm_sf2_cfp_rule_size(priv))
- return -ENOSPC;
-
layout = &udf_tcpip4_layout;
/* We only use one UDF slice for now */
slice_num = bcm_sf2_get_slice_number(layout, 0);
@@ -378,6 +371,9 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
/* Source port map match */
core_writel(priv, 0xff, CORE_CFP_MASK_PORT(7));
+ flow_rule_match_basic(flow_rule, &basic);
+ flow_rule_match_ip(flow_rule, &ip);
+
/* S-Tag status [31:30]
* C-Tag status [29:28]
* L2 framing [27:26]
@@ -392,8 +388,9 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
* Reserved [1]
* UDF_Valid[8] [0]
*/
- core_writel(priv, v4_spec->tos << IPTOS_SHIFT |
- ip_proto << IPPROTO_SHIFT | ip_frag << IP_FRAG_SHIFT |
+ core_writel(priv, ip.key->tos << IPTOS_SHIFT |
+ basic.key->n_proto << IPPROTO_SHIFT |
+ ip_frag << IP_FRAG_SHIFT |
udf_upper_bits(num_udf),
CORE_CFP_DATA_PORT(6));
@@ -411,8 +408,8 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5));
/* Program the match and the mask */
- bcm_sf2_cfp_slice_ipv4(priv, v4_spec, slice_num, false);
- bcm_sf2_cfp_slice_ipv4(priv, v4_m_spec, SLICE_NUM_MASK, true);
+ bcm_sf2_cfp_slice_ipv4(priv, flow_rule, slice_num, false);
+ bcm_sf2_cfp_slice_ipv4(priv, flow_rule, SLICE_NUM_MASK, true);
/* Insert into TCAM now */
bcm_sf2_cfp_rule_addr_set(priv, rule_index);
@@ -437,9 +434,8 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
/* Flag the rule as being used and return it */
set_bit(rule_index, priv->cfp.used);
set_bit(rule_index, priv->cfp.unique);
- fs->location = rule_index;
- return 0;
+ return rule_index;
}
static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv,
@@ -518,33 +514,18 @@ static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv,
static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
unsigned int port_num,
unsigned int queue_num,
- struct ethtool_rx_flow_spec *fs)
+ struct flow_rule *flow_rule,
+ unsigned int *rule_index, u8 ip_frag)
{
- struct ethtool_tcpip6_spec *v6_spec, *v6_m_spec;
- unsigned int slice_num, rule_index[2];
const struct cfp_udf_layout *layout;
- u8 ip_proto, ip_frag;
+ struct flow_match_ipv6_addrs ipv6;
+ struct flow_match_ports ports;
+ struct flow_match_basic basic;
+ unsigned int slice_num;
int ret = 0;
u8 num_udf;
u32 reg;
- switch (fs->flow_type & ~FLOW_EXT) {
- case TCP_V6_FLOW:
- ip_proto = IPPROTO_TCP;
- v6_spec = &fs->h_u.tcp_ip6_spec;
- v6_m_spec = &fs->m_u.tcp_ip6_spec;
- break;
- case UDP_V6_FLOW:
- ip_proto = IPPROTO_UDP;
- v6_spec = &fs->h_u.udp_ip6_spec;
- v6_m_spec = &fs->m_u.udp_ip6_spec;
- break;
- default:
- return -EINVAL;
- }
-
- ip_frag = be32_to_cpu(fs->m_ext.data[0]);
-
layout = &udf_tcpip6_layout;
slice_num = bcm_sf2_get_slice_number(layout, 0);
if (slice_num == UDF_NUM_SLICES)
@@ -552,38 +533,6 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices);
- /* Negotiate two indexes, one for the second half which we are chained
- * from, which is what we will return to user-space, and a second one
- * which is used to store its first half. That first half does not
- * allow any choice of placement, so it just needs to find the next
- * available bit. We return the second half as fs->location because
- * that helps with the rule lookup later on since the second half is
- * chained from its first half, we can easily identify IPv6 CFP rules
- * by looking whether they carry a CHAIN_ID.
- *
- * We also want the second half to have a lower rule_index than its
- * first half because the HW search is by incrementing addresses.
- */
- if (fs->location == RX_CLS_LOC_ANY)
- rule_index[1] = find_first_zero_bit(priv->cfp.used,
- priv->num_cfp_rules);
- else
- rule_index[1] = fs->location;
- if (rule_index[1] > bcm_sf2_cfp_rule_size(priv))
- return -ENOSPC;
-
- /* Flag it as used (cleared on error path) such that we can immediately
- * obtain a second one to chain from.
- */
- set_bit(rule_index[1], priv->cfp.used);
-
- rule_index[0] = find_first_zero_bit(priv->cfp.used,
- priv->num_cfp_rules);
- if (rule_index[0] > bcm_sf2_cfp_rule_size(priv)) {
- ret = -ENOSPC;
- goto out_err;
- }
-
/* Apply the UDF layout for this filter */
bcm_sf2_cfp_udf_set(priv, layout, slice_num);
@@ -593,6 +542,8 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
/* Source port map match */
core_writel(priv, 0xff, CORE_CFP_MASK_PORT(7));
+ flow_rule_match_basic(flow_rule, &basic);
+
/* S-Tag status [31:30]
* C-Tag status [29:28]
* L2 framing [27:26]
@@ -607,7 +558,7 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
* Reserved [1]
* UDF_Valid[8] [0]
*/
- reg = 1 << L3_FRAMING_SHIFT | ip_proto << IPPROTO_SHIFT |
+ reg = 1 << L3_FRAMING_SHIFT | basic.key->n_proto << IPPROTO_SHIFT |
ip_frag << IP_FRAG_SHIFT | udf_upper_bits(num_udf);
core_writel(priv, reg, CORE_CFP_DATA_PORT(6));
@@ -626,11 +577,14 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
/* Mask all but valid UDFs */
core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5));
+ flow_rule_match_ipv6_addrs(flow_rule, &ipv6);
+ flow_rule_match_ports(flow_rule, &ports);
+
/* Slice the IPv6 source address and port */
- bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6src, v6_spec->psrc,
- slice_num, false);
- bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6src, v6_m_spec->psrc,
- SLICE_NUM_MASK, true);
+ bcm_sf2_cfp_slice_ipv6(priv, ipv6.key->src.in6_u.u6_addr32,
+ ports.key->src, slice_num, false);
+ bcm_sf2_cfp_slice_ipv6(priv, ipv6.mask->src.in6_u.u6_addr32,
+ ports.mask->src, SLICE_NUM_MASK, true);
/* Insert into TCAM now because we need to insert a second rule */
bcm_sf2_cfp_rule_addr_set(priv, rule_index[0]);
@@ -638,21 +592,19 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
if (ret) {
pr_err("TCAM entry at addr %d failed\n", rule_index[0]);
- goto out_err;
+ return ret;
}
/* Insert into Action and policer RAMs now */
ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[0], port_num,
queue_num, false);
if (ret)
- goto out_err;
+ return ret;
/* Now deal with the second slice to chain this rule */
slice_num = bcm_sf2_get_slice_number(layout, slice_num + 1);
- if (slice_num == UDF_NUM_SLICES) {
- ret = -EINVAL;
- goto out_err;
- }
+ if (slice_num == UDF_NUM_SLICES)
+ return -EINVAL;
num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices);
@@ -687,10 +639,10 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
/* Mask all */
core_writel(priv, 0, CORE_CFP_MASK_PORT(5));
- bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6dst, v6_spec->pdst, slice_num,
- false);
- bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6dst, v6_m_spec->pdst,
- SLICE_NUM_MASK, true);
+ bcm_sf2_cfp_slice_ipv6(priv, ipv6.key->dst.in6_u.u6_addr32,
+ ports.key->dst, slice_num, false);
+ bcm_sf2_cfp_slice_ipv6(priv, ipv6.mask->dst.in6_u.u6_addr32,
+ ports.key->dst, SLICE_NUM_MASK, true);
/* Insert into TCAM now */
bcm_sf2_cfp_rule_addr_set(priv, rule_index[1]);
@@ -698,7 +650,7 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
if (ret) {
pr_err("TCAM entry at addr %d failed\n", rule_index[1]);
- goto out_err;
+ return ret;
}
/* Insert into Action and policer RAMs now, set chain ID to
@@ -707,7 +659,7 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[1], port_num,
queue_num, true);
if (ret)
- goto out_err;
+ return ret;
/* Turn on CFP for this rule now */
reg = core_readl(priv, CORE_CFP_CTL_REG);
@@ -719,13 +671,8 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
*/
set_bit(rule_index[0], priv->cfp.used);
set_bit(rule_index[1], priv->cfp.unique);
- fs->location = rule_index[1];
-
- return ret;
-out_err:
- clear_bit(rule_index[1], priv->cfp.used);
- return ret;
+ return rule_index[1];
}
static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
@@ -735,7 +682,10 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
s8 cpu_port = ds->ports[port].cpu_dp->index;
__u64 ring_cookie = fs->ring_cookie;
unsigned int queue_num, port_num;
+ struct flow_rule *flow_rule;
+ unsigned int rule_index[2];
int ret = -EINVAL;
+ u8 ip_frag;
/* Check for unsupported extensions */
if ((fs->flow_type & FLOW_EXT) && (fs->m_ext.vlan_etype ||
@@ -750,23 +700,38 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
fs->location > bcm_sf2_cfp_rule_size(priv))
return -EINVAL;
- /* This rule is a Wake-on-LAN filter and we must specifically
- * target the CPU port in order for it to be working.
- */
- if (ring_cookie == RX_CLS_FLOW_WAKE)
- ring_cookie = cpu_port * SF2_NUM_EGRESS_QUEUES;
-
- /* We do not support discarding packets, check that the
- * destination port is enabled and that we are within the
+ /* Check that the destination port is enabled and that we are within the
* number of ports supported by the switch
*/
port_num = ring_cookie / SF2_NUM_EGRESS_QUEUES;
-
- if (ring_cookie == RX_CLS_FLOW_DISC ||
- !(dsa_is_user_port(ds, port_num) ||
+ if (!(dsa_is_user_port(ds, port_num) ||
dsa_is_cpu_port(ds, port_num)) ||
port_num >= priv->hw_params.num_ports)
return -EINVAL;
+
+ /* User-defined data semantics depends on each driver. */
+ ip_frag = be32_to_cpu(fs->m_ext.data[0]);
+
+ flow_rule = ethtool_rx_flow_rule(fs);
+ if (!flow_rule)
+ return -ENOMEM;
+
+ switch (flow_rule->action.keys[0].id) {
+ case FLOW_ACTION_KEY_WAKE:
+ /* This rule is a Wake-on-LAN filter and we must specifically
+ * target the CPU port in order for it to be working.
+ */
+ ring_cookie = cpu_port * SF2_NUM_EGRESS_QUEUES;
+ break;
+ case FLOW_ACTION_KEY_QUEUE:
+ ring_cookie = flow_rule->action.keys[0].queue_index;
+ break;
+ default:
+ /* We do not support discarding packets. */
+ ret = -EINVAL;
+ goto err_out;
+ }
+
/*
* We have a small oddity where Port 6 just does not have a
* valid bit here (so we substract by one).
@@ -778,17 +743,73 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
switch (fs->flow_type & ~FLOW_EXT) {
case TCP_V4_FLOW:
case UDP_V4_FLOW:
+ /* Locate the first rule available */
+ if (fs->location == RX_CLS_LOC_ANY)
+ rule_index[0] = find_first_zero_bit(priv->cfp.used,
+ priv->num_cfp_rules);
+ else
+ rule_index[0] = fs->location;
+
+ if (rule_index[0] > bcm_sf2_cfp_rule_size(priv)) {
+ ret = -ENOSPC;
+ goto err_out;
+ }
+
ret = bcm_sf2_cfp_ipv4_rule_set(priv, port, port_num,
- queue_num, fs);
+ queue_num, flow_rule,
+ rule_index[0], ip_frag);
break;
case TCP_V6_FLOW:
case UDP_V6_FLOW:
+ /* Negotiate two indexes, one for the second half which we are
+ * chained from, which is what we will return to user-space, and
+ * a second one which is used to store its first half. That
+ * first half does not allow any choice of placement, so it just
+ * needs to find the next available bit. We return the second
+ * half as fs->location because that helps with the rule lookup
+ * later on since the second half is chained from its first
+ * half, we can easily identify IPv6 CFP rules by looking
+ * whether they carry a CHAIN_ID.
+ *
+ * We also want the second half to have a lower rule_index than
+ * its first half because the HW search is by incrementing
+ * addresses.
+ */
+ if (fs->location == RX_CLS_LOC_ANY)
+ rule_index[1] = find_first_zero_bit(priv->cfp.used,
+ priv->num_cfp_rules);
+ else
+ rule_index[1] = fs->location;
+
+ if (rule_index[1] > bcm_sf2_cfp_rule_size(priv)) {
+ ret = -ENOSPC;
+ goto err_out;
+ }
+
+ /* Flag it as used (cleared on error path) such that we can
+ * immediately obtain a second one to chain from.
+ */
+ set_bit(rule_index[1], priv->cfp.used);
+
+ rule_index[0] = find_first_zero_bit(priv->cfp.used,
+ priv->num_cfp_rules);
+ if (rule_index[0] > bcm_sf2_cfp_rule_size(priv)) {
+ clear_bit(rule_index[1], priv->cfp.used);
+ ret = -ENOSPC;
+ goto err_out;
+ }
+
ret = bcm_sf2_cfp_ipv6_rule_set(priv, port, port_num,
- queue_num, fs);
+ queue_num, flow_rule,
+ rule_index, ip_frag);
break;
default:
break;
}
+ if (ret >= 0)
+ fs->location = ret;
+err_out:
+ ethtool_rx_flow_rule_free(flow_rule);
return ret;
}
--
2.11.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox