From 38a1f50a5efb5a941f3491d4d2353d12a87d04a0 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 6 Nov 2024 13:18:17 +0000 Subject: [PATCH 01/16] phonet: do not call synchronize_rcu() from phonet_route_del() Calling synchronize_rcu() while holding rcu_read_lock() is not permitted [1] Move the synchronize_rcu() + dev_put() to route_doit(). Alternative would be to not use rcu_read_lock() in route_doit(). [1] WARNING: suspicious RCU usage 6.12.0-rc5-syzkaller-01056-gf07a6e6ceb05 #0 Not tainted ----------------------------- kernel/rcu/tree.c:4092 Illegal synchronize_rcu() in RCU read-side critical section! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 1 lock held by syz-executor427/5840: #0: ffffffff8e937da0 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:337 [inline] #0: ffffffff8e937da0 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:849 [inline] #0: ffffffff8e937da0 (rcu_read_lock){....}-{1:2}, at: route_doit+0x3d6/0x640 net/phonet/pn_netlink.c:264 stack backtrace: CPU: 1 UID: 0 PID: 5840 Comm: syz-executor427 Not tainted 6.12.0-rc5-syzkaller-01056-gf07a6e6ceb05 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 Call Trace: __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 lockdep_rcu_suspicious+0x226/0x340 kernel/locking/lockdep.c:6821 synchronize_rcu+0xea/0x360 kernel/rcu/tree.c:4089 phonet_route_del+0xc6/0x140 net/phonet/pn_dev.c:409 route_doit+0x514/0x640 net/phonet/pn_netlink.c:275 rtnetlink_rcv_msg+0x791/0xcf0 net/core/rtnetlink.c:6790 netlink_rcv_skb+0x1e3/0x430 net/netlink/af_netlink.c:2551 netlink_unicast_kernel net/netlink/af_netlink.c:1331 [inline] netlink_unicast+0x7f6/0x990 net/netlink/af_netlink.c:1357 netlink_sendmsg+0x8e4/0xcb0 net/netlink/af_netlink.c:1901 sock_sendmsg_nosec net/socket.c:729 [inline] __sock_sendmsg+0x221/0x270 net/socket.c:744 sock_write_iter+0x2d7/0x3f0 net/socket.c:1165 new_sync_write fs/read_write.c:590 [inline] vfs_write+0xaeb/0xd30 fs/read_write.c:683 ksys_write+0x183/0x2b0 fs/read_write.c:736 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f Fixes: 17a1ac0018ae ("phonet: Don't hold RTNL for route_doit().") Reported-by: syzbot Signed-off-by: Eric Dumazet Reviewed-by: Kuniyuki Iwashima Cc: Remi Denis-Courmont Reviewed-by: Jiri Pirko Link: https://patch.msgid.link/20241106131818.1240710-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- net/phonet/pn_dev.c | 5 +++-- net/phonet/pn_netlink.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 19234d664c4f..5c36bae37b8f 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -406,8 +406,9 @@ int phonet_route_del(struct net_device *dev, u8 daddr) if (!dev) return -ENOENT; - synchronize_rcu(); - dev_put(dev); + + /* Note : our caller must call synchronize_rcu() and dev_put(dev) */ + return 0; } diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index ca1f04e4a2d9..b9043c92dc24 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c @@ -233,6 +233,7 @@ static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh, { struct net *net = sock_net(skb->sk); struct nlattr *tb[RTA_MAX+1]; + bool sync_needed = false; struct net_device *dev; struct rtmsg *rtm; u32 ifindex; @@ -269,13 +270,20 @@ static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh, return -ENODEV; } - if (nlh->nlmsg_type == RTM_NEWROUTE) + if (nlh->nlmsg_type == RTM_NEWROUTE) { err = phonet_route_add(dev, dst); - else + } else { err = phonet_route_del(dev, dst); + if (!err) + sync_needed = true; + } rcu_read_unlock(); + if (sync_needed) { + synchronize_rcu(); + dev_put(dev); + } if (!err) rtm_phonet_notify(net, nlh->nlmsg_type, ifindex, dst); -- 2.51.0 From bc515ed06652b506794f323b9e53d89c01de7e4a Mon Sep 17 00:00:00 2001 From: Donald Hunter Date: Wed, 6 Nov 2024 09:07:17 +0000 Subject: [PATCH 02/16] netlink: specs: Add a spec for neighbor tables in rtnetlink Add a YNL spec for neighbour tables and neighbour entries in rtnetlink. ./tools/net/ynl/cli.py \ --spec Documentation/netlink/specs/rt_neigh.yaml \ --dump getneigh [{'cacheinfo': {'confirmed': 122664055, 'refcnt': 0, 'updated': 122658055, 'used': 122658055}, 'dst': '0.0.0.0', 'family': 2, 'flags': set(), 'ifindex': 5, 'lladr': '', 'probes': 0, 'state': {'noarp'}, 'type': 'broadcast'}, ...] Acked-by: Stanislav Fomichev Signed-off-by: Donald Hunter Link: https://patch.msgid.link/20241106090718.64713-2-donald.hunter@gmail.com Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/rt_neigh.yaml | 442 ++++++++++++++++++++++ 1 file changed, 442 insertions(+) create mode 100644 Documentation/netlink/specs/rt_neigh.yaml diff --git a/Documentation/netlink/specs/rt_neigh.yaml b/Documentation/netlink/specs/rt_neigh.yaml new file mode 100644 index 000000000000..e670b6dc07be --- /dev/null +++ b/Documentation/netlink/specs/rt_neigh.yaml @@ -0,0 +1,442 @@ +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +name: rt-neigh +protocol: netlink-raw +protonum: 0 + +doc: + IP neighbour management over rtnetlink. + +definitions: + - + name: ndmsg + type: struct + members: + - + name: family + type: u8 + - + name: pad + type: pad + len: 3 + - + name: ifindex + type: s32 + - + name: state + type: u16 + enum: nud-state + - + name: flags + type: u8 + enum: ntf-flags + - + name: type + type: u8 + enum: rtm-type + - + name: ndtmsg + type: struct + members: + - + name: family + type: u8 + - + name: pad + type: pad + len: 3 + - + name: nud-state + type: flags + entries: + - incomplete + - reachable + - stale + - delay + - probe + - failed + - noarp + - permanent + - + name: ntf-flags + type: flags + entries: + - use + - self + - master + - proxy + - ext-learned + - offloaded + - sticky + - router + - + name: ntf-ext-flags + type: flags + entries: + - managed + - locked + - + name: rtm-type + type: enum + entries: + - unspec + - unicast + - local + - broadcast + - anycast + - multicast + - blackhole + - unreachable + - prohibit + - throw + - nat + - xresolve + - + name: nda-cacheinfo + type: struct + members: + - + name: confirmed + type: u32 + - + name: used + type: u32 + - + name: updated + type: u32 + - + name: refcnt + type: u32 + - + name: ndt-config + type: struct + members: + - + name: key-len + type: u16 + - + name: entry-size + type: u16 + - + name: entries + type: u32 + - + name: last-flush + type: u32 + - + name: last-rand + type: u32 + - + name: hash-rnd + type: u32 + - + name: hash-mask + type: u32 + - + name: hash-chain-gc + type: u32 + - + name: proxy-qlen + type: u32 + - + name: ndt-stats + type: struct + members: + - + name: allocs + type: u64 + - + name: destroys + type: u64 + - + name: hash-grows + type: u64 + - + name: res-failed + type: u64 + - + name: lookups + type: u64 + - + name: hits + type: u64 + - + name: rcv-probes-mcast + type: u64 + - + name: rcv-probes-ucast + type: u64 + - + name: periodic-gc-runs + type: u64 + - + name: forced-gc-runs + type: u64 + - + name: table-fulls + type: u64 + +attribute-sets: + - + name: neighbour-attrs + attributes: + - + name: unspec + type: binary + value: 0 + - + name: dst + type: binary + display-hint: ipv4 + - + name: lladr + type: binary + display-hint: mac + - + name: cacheinfo + type: binary + struct: nda-cacheinfo + - + name: probes + type: u32 + - + name: vlan + type: u16 + - + name: port + type: u16 + - + name: vni + type: u32 + - + name: ifindex + type: u32 + - + name: master + type: u32 + - + name: link-netnsid + type: s32 + - + name: src-vni + type: u32 + - + name: protocol + type: u8 + - + name: nh-id + type: u32 + - + name: fdb-ext-attrs + type: binary + - + name: flags-ext + type: u32 + enum: ntf-ext-flags + - + name: ndm-state-mask + type: u16 + - + name: ndm-flags-mask + type: u8 + - + name: ndt-attrs + attributes: + - + name: name + type: string + - + name: thresh1 + type: u32 + - + name: thresh2 + type: u32 + - + name: thresh3 + type: u32 + - + name: config + type: binary + struct: ndt-config + - + name: parms + type: nest + nested-attributes: ndtpa-attrs + - + name: stats + type: binary + struct: ndt-stats + - + name: gc-interval + type: u64 + - + name: pad + type: pad + - + name: ndtpa-attrs + attributes: + - + name: ifindex + type: u32 + - + name: refcnt + type: u32 + - + name: reachable-time + type: u64 + - + name: base-reachable-time + type: u64 + - + name: retrans-time + type: u64 + - + name: gc-staletime + type: u64 + - + name: delay-probe-time + type: u64 + - + name: queue-len + type: u32 + - + name: app-probes + type: u32 + - + name: ucast-probes + type: u32 + - + name: mcast-probes + type: u32 + - + name: anycast-delay + type: u64 + - + name: proxy-delay + type: u64 + - + name: proxy-qlen + type: u32 + - + name: locktime + type: u64 + - + name: queue-lenbytes + type: u32 + - + name: mcast-reprobes + type: u32 + - + name: pad + type: pad + - + name: interval-probe-time-ms + type: u64 + +operations: + enum-model: directional + list: + - + name: newneigh + doc: Add new neighbour entry + fixed-header: ndmsg + attribute-set: neighbour-attrs + do: + request: + value: 28 + attributes: &neighbour-all + - dst + - lladdr + - probes + - vlan + - port + - vni + - ifindex + - master + - protocol + - nh-id + - flags-ext + - fdb-ext-attrs + - + name: delneigh + doc: Remove an existing neighbour entry + fixed-header: ndmsg + attribute-set: neighbour-attrs + do: + request: + value: 29 + attributes: + - dst + - ifindex + - + name: delneigh-ntf + doc: Notify a neighbour deletion + value: 29 + notify: delneigh + fixed-header: ndmsg + - + name: getneigh + doc: Get or dump neighbour entries + fixed-header: ndmsg + attribute-set: neighbour-attrs + do: + request: + value: 30 + attributes: + - dst + reply: + value: 28 + attributes: *neighbour-all + dump: + request: + attributes: + - ifindex + - master + reply: + attributes: *neighbour-all + - + name: newneigh-ntf + doc: Notify a neighbour creation + value: 28 + notify: getneigh + fixed-header: ndmsg + - + name: getneightbl + doc: Get or dump neighbour tables + fixed-header: ndtmsg + attribute-set: ndt-attrs + dump: + request: + value: 66 + reply: + value: 64 + attributes: + - name + - thresh1 + - thresh2 + - thresh3 + - config + - parms + - stats + - gc-interval + - + name: setneightbl + doc: Set neighbour tables + fixed-header: ndtmsg + attribute-set: ndt-attrs + do: + request: + value: 67 + attributes: + - name + - thresh1 + - thresh2 + - thresh3 + - parms + - gc-interval + +mcast-groups: + list: + - + name: rtnlgrp-neigh + value: 3 -- 2.51.0 From a852e3c356415f61d9329cb3a1a4c90c74570522 Mon Sep 17 00:00:00 2001 From: Donald Hunter Date: Wed, 6 Nov 2024 09:07:18 +0000 Subject: [PATCH 03/16] netlink: specs: Add a spec for FIB rule management Add a YNL spec for FIB rules: ./tools/net/ynl/cli.py \ --spec Documentation/netlink/specs/rt_rule.yaml \ --dump getrule --json '{"family": 2}' [{'action': 'to-tbl', 'dst-len': 0, 'family': 2, 'flags': 0, 'protocol': 2, 'src-len': 0, 'suppress-prefixlen': '0xffffffff', 'table': 255, 'tos': 0}, ... ] Acked-by: Stanislav Fomichev Reviewed-by: Ido Schimmel Signed-off-by: Donald Hunter Link: https://patch.msgid.link/20241106090718.64713-3-donald.hunter@gmail.com Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/rt_rule.yaml | 242 +++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 Documentation/netlink/specs/rt_rule.yaml diff --git a/Documentation/netlink/specs/rt_rule.yaml b/Documentation/netlink/specs/rt_rule.yaml new file mode 100644 index 000000000000..03a8eef7952e --- /dev/null +++ b/Documentation/netlink/specs/rt_rule.yaml @@ -0,0 +1,242 @@ +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +name: rt-rule +protocol: netlink-raw +protonum: 0 + +doc: + FIB rule management over rtnetlink. + +definitions: + - + name: rtgenmsg + type: struct + members: + - + name: family + type: u8 + - + name: pad + type: pad + len: 3 + - + name: fib-rule-hdr + type: struct + members: + - + name: family + type: u8 + - + name: dst-len + type: u8 + - + name: src-len + type: u8 + - + name: tos + type: u8 + - + name: table + type: u8 + - + name: res1 + type: pad + len: 1 + - + name: res2 + type: pad + len: 1 + - + name: action + type: u8 + enum: fr-act + - + name: flags + type: u32 + - + name: fr-act + type: enum + entries: + - unspec + - to-tbl + - goto + - nop + - res3 + - res4 + - blackhole + - unreachable + - prohibit + - + name: fib-rule-port-range + type: struct + members: + - + name: start + type: u16 + - + name: end + type: u16 + - + name: fib-rule-uid-range + type: struct + members: + - + name: start + type: u32 + - + name: end + type: u32 + +attribute-sets: + - + name: fib-rule-attrs + attributes: + - + name: dst + type: u32 + - + name: src + type: u32 + - + name: iifname + type: string + - + name: goto + type: u32 + - + name: unused2 + type: pad + - + name: priority + type: u32 + - + name: unused3 + type: pad + - + name: unused4 + type: pad + - + name: unused5 + type: pad + - + name: fwmark + type: u32 + display-hint: hex + - + name: flow + type: u32 + - + name: tun-id + type: u64 + - + name: suppress-ifgroup + type: u32 + - + name: suppress-prefixlen + type: u32 + display-hint: hex + - + name: table + type: u32 + - + name: fwmask + type: u32 + display-hint: hex + - + name: oifname + type: string + - + name: pad + type: pad + - + name: l3mdev + type: u8 + - + name: uid-range + type: binary + struct: fib-rule-uid-range + - + name: protocol + type: u8 + - + name: ip-proto + type: u8 + - + name: sport-range + type: binary + struct: fib-rule-port-range + - + name: dport-range + type: binary + struct: fib-rule-port-range + - + name: dscp + type: u8 + +operations: + enum-model: directional + fixed-header: fib-rule-hdr + list: + - + name: newrule + doc: Add new FIB rule + attribute-set: fib-rule-attrs + do: + request: + value: 32 + attributes: &fib-rule-all + - iifname + - oifname + - priority + - fwmark + - flow + - tun-id + - fwmask + - table + - suppress-prefixlen + - suppress-ifgroup + - goto + - l3mdev + - uid-range + - protocol + - ip-proto + - sport-range + - dport-range + - dscp + - + name: newrule-ntf + doc: Notify a rule creation + value: 32 + notify: newrule + - + name: delrule + doc: Remove an existing FIB rule + attribute-set: fib-rule-attrs + do: + request: + value: 33 + attributes: *fib-rule-all + - + name: delrule-ntf + doc: Notify a rule deletion + value: 33 + notify: delrule + - + name: getrule + doc: Dump all FIB rules + attribute-set: fib-rule-attrs + dump: + request: + value: 34 + reply: + value: 32 + attributes: *fib-rule-all + +mcast-groups: + list: + - + name: rtnlgrp-ipv4-rule + value: 8 + - + name: rtnlgrp-ipv6-rule + value: 19 -- 2.51.0 From 4861333b42178fa3d8fd1bb4e2cfb2fedc968dba Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Tue, 5 Nov 2024 21:27:21 +0200 Subject: [PATCH 04/16] bonding: add ESP offload features when slaves support Add NETIF_F_GSO_ESP bit to bond's gso_partial_features if all slaves support it, such that ESP segmentation is handled by hardware if possible. Signed-off-by: Jianbo Liu Reviewed-by: Boris Pismenny Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20241105192721.584822-1-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/bonding/bond_main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 5812e8eaccf1..9e8bdd0d0922 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1545,6 +1545,7 @@ static void bond_compute_features(struct bonding *bond) { unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM; + netdev_features_t gso_partial_features = NETIF_F_GSO_ESP; netdev_features_t vlan_features = BOND_VLAN_FEATURES; netdev_features_t enc_features = BOND_ENC_FEATURES; #ifdef CONFIG_XFRM_OFFLOAD @@ -1577,6 +1578,9 @@ static void bond_compute_features(struct bonding *bond) BOND_XFRM_FEATURES); #endif /* CONFIG_XFRM_OFFLOAD */ + if (slave->dev->hw_enc_features & NETIF_F_GSO_PARTIAL) + gso_partial_features &= slave->dev->gso_partial_features; + mpls_features = netdev_increment_features(mpls_features, slave->dev->mpls_features, BOND_MPLS_FEATURES); @@ -1590,6 +1594,11 @@ static void bond_compute_features(struct bonding *bond) } bond_dev->hard_header_len = max_hard_header_len; + if (gso_partial_features & NETIF_F_GSO_ESP) + bond_dev->gso_partial_features |= NETIF_F_GSO_ESP; + else + bond_dev->gso_partial_features &= ~NETIF_F_GSO_ESP; + done: bond_dev->vlan_features = vlan_features; bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL | -- 2.51.0 From 580db513b4a9d52f306580015a1872eea0a0894e Mon Sep 17 00:00:00 2001 From: Khang Nguyen Date: Tue, 5 Nov 2024 14:19:15 +0700 Subject: [PATCH 05/16] net: mctp: Expose transport binding identifier via IFLA attribute MCTP control protocol implementations are transport binding dependent. Endpoint discovery is mandatory based on transport binding. Message timing requirements are specified in each respective transport binding specification. However, we currently have no means to get this information from MCTP links. Add a IFLA_MCTP_PHYS_BINDING netlink link attribute, which represents the transport type using the DMTF DSP0239-defined type numbers, returned as part of RTM_GETLINK data. We get an IFLA_MCTP_PHYS_BINDING attribute for each MCTP link, for example: - 0x00 (unspec) for loopback interface; - 0x01 (SMBus/I2C) for mctpi2c%d interfaces; and - 0x05 (serial) for mctpserial%d interfaces. Signed-off-by: Khang Nguyen Reviewed-by: Matt Johnston Link: https://patch.msgid.link/20241105071915.821871-1-khangng@os.amperecomputing.com Signed-off-by: Jakub Kicinski --- drivers/net/mctp/mctp-i2c.c | 3 ++- drivers/net/mctp/mctp-i3c.c | 2 +- drivers/net/mctp/mctp-serial.c | 5 +++-- include/net/mctp.h | 18 ++++++++++++++++++ include/net/mctpdevice.h | 4 +++- include/uapi/linux/if_link.h | 1 + net/mctp/device.c | 12 +++++++++--- 7 files changed, 37 insertions(+), 8 deletions(-) diff --git a/drivers/net/mctp/mctp-i2c.c b/drivers/net/mctp/mctp-i2c.c index e70fb6687994..d2b3f5a59141 100644 --- a/drivers/net/mctp/mctp-i2c.c +++ b/drivers/net/mctp/mctp-i2c.c @@ -880,7 +880,8 @@ static int mctp_i2c_add_netdev(struct mctp_i2c_client *mcli, goto err; } - rc = mctp_register_netdev(ndev, &mctp_i2c_mctp_ops); + rc = mctp_register_netdev(ndev, &mctp_i2c_mctp_ops, + MCTP_PHYS_BINDING_SMBUS); if (rc < 0) { dev_err(&mcli->client->dev, "register netdev \"%s\" failed %d\n", diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c index 1bc87a062686..9adad59b8676 100644 --- a/drivers/net/mctp/mctp-i3c.c +++ b/drivers/net/mctp/mctp-i3c.c @@ -607,7 +607,7 @@ __must_hold(&busdevs_lock) goto err_free_uninit; } - rc = mctp_register_netdev(ndev, NULL); + rc = mctp_register_netdev(ndev, NULL, MCTP_PHYS_BINDING_I3C); if (rc < 0) { dev_warn(&ndev->dev, "netdev register failed: %d\n", rc); goto err_free_netdev; diff --git a/drivers/net/mctp/mctp-serial.c b/drivers/net/mctp/mctp-serial.c index e63720ec3238..26c9a33fd636 100644 --- a/drivers/net/mctp/mctp-serial.c +++ b/drivers/net/mctp/mctp-serial.c @@ -23,6 +23,7 @@ #include #include +#include #include #define MCTP_SERIAL_MTU 68 /* base mtu (64) + mctp header */ @@ -470,7 +471,7 @@ static int mctp_serial_open(struct tty_struct *tty) spin_lock_init(&dev->lock); INIT_WORK(&dev->tx_work, mctp_serial_tx_work); - rc = register_netdev(ndev); + rc = mctp_register_netdev(ndev, NULL, MCTP_PHYS_BINDING_SERIAL); if (rc) goto free_netdev; @@ -492,7 +493,7 @@ static void mctp_serial_close(struct tty_struct *tty) struct mctp_serial *dev = tty->disc_data; int idx = dev->idx; - unregister_netdev(dev->netdev); + mctp_unregister_netdev(dev->netdev); ida_free(&mctp_serial_ida, idx); } diff --git a/include/net/mctp.h b/include/net/mctp.h index 28d59ae94ca3..1ecbff7116f6 100644 --- a/include/net/mctp.h +++ b/include/net/mctp.h @@ -298,4 +298,22 @@ void mctp_routes_exit(void); int mctp_device_init(void); void mctp_device_exit(void); +/* MCTP IDs and Codes from DMTF specification + * "DSP0239 Management Component Transport Protocol (MCTP) IDs and Codes" + * https://www.dmtf.org/sites/default/files/standards/documents/DSP0239_1.11.1.pdf + */ +enum mctp_phys_binding { + MCTP_PHYS_BINDING_UNSPEC = 0x00, + MCTP_PHYS_BINDING_SMBUS = 0x01, + MCTP_PHYS_BINDING_PCIE_VDM = 0x02, + MCTP_PHYS_BINDING_USB = 0x03, + MCTP_PHYS_BINDING_KCS = 0x04, + MCTP_PHYS_BINDING_SERIAL = 0x05, + MCTP_PHYS_BINDING_I3C = 0x06, + MCTP_PHYS_BINDING_MMBI = 0x07, + MCTP_PHYS_BINDING_PCC = 0x08, + MCTP_PHYS_BINDING_UCIE = 0x09, + MCTP_PHYS_BINDING_VENDOR = 0xFF, +}; + #endif /* __NET_MCTP_H */ diff --git a/include/net/mctpdevice.h b/include/net/mctpdevice.h index 5c0d04b5c12c..957d9ef924c5 100644 --- a/include/net/mctpdevice.h +++ b/include/net/mctpdevice.h @@ -22,6 +22,7 @@ struct mctp_dev { refcount_t refs; unsigned int net; + enum mctp_phys_binding binding; const struct mctp_netdev_ops *ops; @@ -44,7 +45,8 @@ struct mctp_dev *mctp_dev_get_rtnl(const struct net_device *dev); struct mctp_dev *__mctp_dev_get(const struct net_device *dev); int mctp_register_netdev(struct net_device *dev, - const struct mctp_netdev_ops *ops); + const struct mctp_netdev_ops *ops, + enum mctp_phys_binding binding); void mctp_unregister_netdev(struct net_device *dev); void mctp_dev_hold(struct mctp_dev *mdev); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 8516c1ccd57a..2575e0cd9b48 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -1958,6 +1958,7 @@ struct ifla_rmnet_flags { enum { IFLA_MCTP_UNSPEC, IFLA_MCTP_NET, + IFLA_MCTP_PHYS_BINDING, __IFLA_MCTP_MAX, }; diff --git a/net/mctp/device.c b/net/mctp/device.c index 3d75b919995d..26ce34b7e88e 100644 --- a/net/mctp/device.c +++ b/net/mctp/device.c @@ -371,6 +371,8 @@ static int mctp_fill_link_af(struct sk_buff *skb, return -ENODATA; if (nla_put_u32(skb, IFLA_MCTP_NET, mdev->net)) return -EMSGSIZE; + if (nla_put_u8(skb, IFLA_MCTP_PHYS_BINDING, mdev->binding)) + return -EMSGSIZE; return 0; } @@ -385,6 +387,7 @@ static size_t mctp_get_link_af_size(const struct net_device *dev, if (!mdev) return 0; ret = nla_total_size(4); /* IFLA_MCTP_NET */ + ret += nla_total_size(1); /* IFLA_MCTP_PHYS_BINDING */ mctp_dev_put(mdev); return ret; } @@ -480,7 +483,8 @@ static int mctp_dev_notify(struct notifier_block *this, unsigned long event, } static int mctp_register_netdevice(struct net_device *dev, - const struct mctp_netdev_ops *ops) + const struct mctp_netdev_ops *ops, + enum mctp_phys_binding binding) { struct mctp_dev *mdev; @@ -489,17 +493,19 @@ static int mctp_register_netdevice(struct net_device *dev, return PTR_ERR(mdev); mdev->ops = ops; + mdev->binding = binding; return register_netdevice(dev); } int mctp_register_netdev(struct net_device *dev, - const struct mctp_netdev_ops *ops) + const struct mctp_netdev_ops *ops, + enum mctp_phys_binding binding) { int rc; rtnl_lock(); - rc = mctp_register_netdevice(dev, ops); + rc = mctp_register_netdevice(dev, ops, binding); rtnl_unlock(); return rc; -- 2.51.0 From 7d28f4fc868ccc26124d368e8d2ead9d21c23542 Mon Sep 17 00:00:00 2001 From: MoYuanhao Date: Wed, 6 Nov 2024 15:10:35 +0800 Subject: [PATCH 06/16] mptcp: remove the redundant assignment of 'new_ctx->tcp_sock' in subflow_ulp_clone() The variable has already been assigned in the subflow_create_ctx(), So we don't need to reassign this variable in the subflow_ulp_clone(). Signed-off-by: MoYuanhao Reviewed-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20241106071035.2591-1-moyuanhao3676@163.com Signed-off-by: Jakub Kicinski --- net/mptcp/subflow.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 07352b15f145..fd021cf8286e 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -2049,7 +2049,6 @@ static void subflow_ulp_clone(const struct request_sock *req, new_ctx->tcp_state_change = old_ctx->tcp_state_change; new_ctx->tcp_error_report = old_ctx->tcp_error_report; new_ctx->rel_write_seq = 1; - new_ctx->tcp_sock = newsk; if (subflow_req->mp_capable) { /* see comments in subflow_syn_recv_sock(), MPTCP connection -- 2.51.0 From 9dae59210556114562b49f6b909181443ebdbabe Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 5 Nov 2024 15:18:55 -0800 Subject: [PATCH 07/16] net: sfc: use ethtool string helpers The latter is the preferred way to copy ethtool strings. Avoids manually incrementing the pointer. Cleans up the code quite well. Signed-off-by: Rosen Penev Acked-by: Edward Cree Link: https://patch.msgid.link/20241105231855.235894-1-rosenp@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/sfc/ef10.c | 2 +- drivers/net/ethernet/sfc/ef100_nic.c | 2 +- drivers/net/ethernet/sfc/ethtool_common.c | 46 ++++++++----------- drivers/net/ethernet/sfc/falcon/ethtool.c | 34 ++++++-------- drivers/net/ethernet/sfc/falcon/falcon.c | 2 +- drivers/net/ethernet/sfc/falcon/net_driver.h | 2 +- drivers/net/ethernet/sfc/falcon/nic.c | 9 ++-- drivers/net/ethernet/sfc/falcon/nic.h | 2 +- drivers/net/ethernet/sfc/net_driver.h | 2 +- drivers/net/ethernet/sfc/nic.c | 9 ++-- drivers/net/ethernet/sfc/nic_common.h | 2 +- drivers/net/ethernet/sfc/ptp.c | 2 +- drivers/net/ethernet/sfc/ptp.h | 2 +- .../net/ethernet/sfc/siena/ethtool_common.c | 46 ++++++++----------- drivers/net/ethernet/sfc/siena/net_driver.h | 2 +- drivers/net/ethernet/sfc/siena/nic.c | 14 +++--- drivers/net/ethernet/sfc/siena/nic_common.h | 5 +- drivers/net/ethernet/sfc/siena/ptp.c | 2 +- drivers/net/ethernet/sfc/siena/ptp.h | 2 +- drivers/net/ethernet/sfc/siena/siena.c | 2 +- 20 files changed, 83 insertions(+), 106 deletions(-) diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index de131fc5fa0b..452009ed7a43 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1751,7 +1751,7 @@ static void efx_ef10_get_stat_mask(struct efx_nic *efx, unsigned long *mask) #endif } -static size_t efx_ef10_describe_stats(struct efx_nic *efx, u8 *names) +static size_t efx_ef10_describe_stats(struct efx_nic *efx, u8 **names) { DECLARE_BITMAP(mask, EF10_STAT_COUNT); diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c index 6da06931187d..62e674d6ff60 100644 --- a/drivers/net/ethernet/sfc/ef100_nic.c +++ b/drivers/net/ethernet/sfc/ef100_nic.c @@ -583,7 +583,7 @@ static const struct efx_hw_stat_desc ef100_stat_desc[EF100_STAT_COUNT] = { EFX_GENERIC_SW_STAT(rx_noskb_drops), }; -static size_t ef100_describe_stats(struct efx_nic *efx, u8 *names) +static size_t ef100_describe_stats(struct efx_nic *efx, u8 **names) { DECLARE_BITMAP(mask, EF100_STAT_COUNT) = {}; diff --git a/drivers/net/ethernet/sfc/ethtool_common.c b/drivers/net/ethernet/sfc/ethtool_common.c index ae32e08540fa..2d734496733f 100644 --- a/drivers/net/ethernet/sfc/ethtool_common.c +++ b/drivers/net/ethernet/sfc/ethtool_common.c @@ -395,7 +395,7 @@ int efx_ethtool_fill_self_tests(struct efx_nic *efx, return n; } -static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings) +static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 **strings) { size_t n_stats = 0; struct efx_channel *channel; @@ -403,24 +403,22 @@ static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings) efx_for_each_channel(channel, efx) { if (efx_channel_has_tx_queues(channel)) { n_stats++; - if (strings != NULL) { - snprintf(strings, ETH_GSTRING_LEN, - "tx-%u.tx_packets", - channel->tx_queue[0].queue / - EFX_MAX_TXQ_PER_CHANNEL); + if (!strings) + continue; - strings += ETH_GSTRING_LEN; - } + ethtool_sprintf(strings, "tx-%u.tx_packets", + channel->tx_queue[0].queue / + EFX_MAX_TXQ_PER_CHANNEL); } } efx_for_each_channel(channel, efx) { if (efx_channel_has_rx_queue(channel)) { n_stats++; - if (strings != NULL) { - snprintf(strings, ETH_GSTRING_LEN, - "rx-%d.rx_packets", channel->channel); - strings += ETH_GSTRING_LEN; - } + if (!strings) + continue; + + ethtool_sprintf(strings, "rx-%d.rx_packets", + channel->channel); } } if (efx->xdp_tx_queue_count && efx->xdp_tx_queues) { @@ -428,11 +426,11 @@ static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings) for (xdp = 0; xdp < efx->xdp_tx_queue_count; xdp++) { n_stats++; - if (strings) { - snprintf(strings, ETH_GSTRING_LEN, - "tx-xdp-cpu-%hu.tx_packets", xdp); - strings += ETH_GSTRING_LEN; - } + if (!strings) + continue; + + ethtool_sprintf(strings, "tx-xdp-cpu-%hu.tx_packets", + xdp); } } @@ -464,15 +462,11 @@ void efx_ethtool_get_strings(struct net_device *net_dev, switch (string_set) { case ETH_SS_STATS: - strings += (efx->type->describe_stats(efx, strings) * - ETH_GSTRING_LEN); + efx->type->describe_stats(efx, &strings); for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++) - strscpy(strings + i * ETH_GSTRING_LEN, - efx_sw_stat_desc[i].name, ETH_GSTRING_LEN); - strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN; - strings += (efx_describe_per_queue_stats(efx, strings) * - ETH_GSTRING_LEN); - efx_ptp_describe_stats(efx, strings); + ethtool_puts(&strings, efx_sw_stat_desc[i].name); + efx_describe_per_queue_stats(efx, &strings); + efx_ptp_describe_stats(efx, &strings); break; case ETH_SS_TEST: efx_ethtool_fill_self_tests(efx, NULL, strings, NULL); diff --git a/drivers/net/ethernet/sfc/falcon/ethtool.c b/drivers/net/ethernet/sfc/falcon/ethtool.c index f4db683b80f7..04766448a545 100644 --- a/drivers/net/ethernet/sfc/falcon/ethtool.c +++ b/drivers/net/ethernet/sfc/falcon/ethtool.c @@ -353,7 +353,7 @@ static int ef4_ethtool_fill_self_tests(struct ef4_nic *efx, return n; } -static size_t ef4_describe_per_queue_stats(struct ef4_nic *efx, u8 *strings) +static size_t ef4_describe_per_queue_stats(struct ef4_nic *efx, u8 **strings) { size_t n_stats = 0; struct ef4_channel *channel; @@ -361,24 +361,22 @@ static size_t ef4_describe_per_queue_stats(struct ef4_nic *efx, u8 *strings) ef4_for_each_channel(channel, efx) { if (ef4_channel_has_tx_queues(channel)) { n_stats++; - if (strings != NULL) { - snprintf(strings, ETH_GSTRING_LEN, - "tx-%u.tx_packets", - channel->tx_queue[0].queue / - EF4_TXQ_TYPES); + if (!strings) + continue; - strings += ETH_GSTRING_LEN; - } + ethtool_sprintf(strings, "tx-%u.tx_packets", + channel->tx_queue[0].queue / + EF4_TXQ_TYPES); } } ef4_for_each_channel(channel, efx) { if (ef4_channel_has_rx_queue(channel)) { n_stats++; - if (strings != NULL) { - snprintf(strings, ETH_GSTRING_LEN, - "rx-%d.rx_packets", channel->channel); - strings += ETH_GSTRING_LEN; - } + if (!strings) + continue; + + ethtool_sprintf(strings, "rx-%d.rx_packets", + channel->channel); } } return n_stats; @@ -409,14 +407,10 @@ static void ef4_ethtool_get_strings(struct net_device *net_dev, switch (string_set) { case ETH_SS_STATS: - strings += (efx->type->describe_stats(efx, strings) * - ETH_GSTRING_LEN); + efx->type->describe_stats(efx, &strings); for (i = 0; i < EF4_ETHTOOL_SW_STAT_COUNT; i++) - strscpy(strings + i * ETH_GSTRING_LEN, - ef4_sw_stat_desc[i].name, ETH_GSTRING_LEN); - strings += EF4_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN; - strings += (ef4_describe_per_queue_stats(efx, strings) * - ETH_GSTRING_LEN); + ethtool_puts(&strings, ef4_sw_stat_desc[i].name); + ef4_describe_per_queue_stats(efx, &strings); break; case ETH_SS_TEST: ef4_ethtool_fill_self_tests(efx, NULL, strings, NULL); diff --git a/drivers/net/ethernet/sfc/falcon/falcon.c b/drivers/net/ethernet/sfc/falcon/falcon.c index 36114ce88034..4af56333ea49 100644 --- a/drivers/net/ethernet/sfc/falcon/falcon.c +++ b/drivers/net/ethernet/sfc/falcon/falcon.c @@ -2564,7 +2564,7 @@ static void falcon_remove_nic(struct ef4_nic *efx) efx->nic_data = NULL; } -static size_t falcon_describe_nic_stats(struct ef4_nic *efx, u8 *names) +static size_t falcon_describe_nic_stats(struct ef4_nic *efx, u8 **names) { return ef4_nic_describe_stats(falcon_stat_desc, FALCON_STAT_COUNT, falcon_stat_mask, names); diff --git a/drivers/net/ethernet/sfc/falcon/net_driver.h b/drivers/net/ethernet/sfc/falcon/net_driver.h index a2c7139f2b32..7ab0db44720d 100644 --- a/drivers/net/ethernet/sfc/falcon/net_driver.h +++ b/drivers/net/ethernet/sfc/falcon/net_driver.h @@ -1057,7 +1057,7 @@ struct ef4_nic_type { void (*finish_flush)(struct ef4_nic *efx); void (*prepare_flr)(struct ef4_nic *efx); void (*finish_flr)(struct ef4_nic *efx); - size_t (*describe_stats)(struct ef4_nic *efx, u8 *names); + size_t (*describe_stats)(struct ef4_nic *efx, u8 **names); size_t (*update_stats)(struct ef4_nic *efx, u64 *full_stats, struct rtnl_link_stats64 *core_stats); void (*start_stats)(struct ef4_nic *efx); diff --git a/drivers/net/ethernet/sfc/falcon/nic.c b/drivers/net/ethernet/sfc/falcon/nic.c index 1b91992e3698..a6304686bc90 100644 --- a/drivers/net/ethernet/sfc/falcon/nic.c +++ b/drivers/net/ethernet/sfc/falcon/nic.c @@ -444,18 +444,15 @@ void ef4_nic_get_regs(struct ef4_nic *efx, void *buf) * bits in the first @count bits of @mask for which a name is defined. */ size_t ef4_nic_describe_stats(const struct ef4_hw_stat_desc *desc, size_t count, - const unsigned long *mask, u8 *names) + const unsigned long *mask, u8 **names) { size_t visible = 0; size_t index; for_each_set_bit(index, mask, count) { if (desc[index].name) { - if (names) { - strscpy(names, desc[index].name, - ETH_GSTRING_LEN); - names += ETH_GSTRING_LEN; - } + if (names) + ethtool_puts(names, desc[index].name); ++visible; } } diff --git a/drivers/net/ethernet/sfc/falcon/nic.h b/drivers/net/ethernet/sfc/falcon/nic.h index ac10c12967df..bc6ef937d0fe 100644 --- a/drivers/net/ethernet/sfc/falcon/nic.h +++ b/drivers/net/ethernet/sfc/falcon/nic.h @@ -497,7 +497,7 @@ size_t ef4_nic_get_regs_len(struct ef4_nic *efx); void ef4_nic_get_regs(struct ef4_nic *efx, void *buf); size_t ef4_nic_describe_stats(const struct ef4_hw_stat_desc *desc, size_t count, - const unsigned long *mask, u8 *names); + const unsigned long *mask, u8 **names); void ef4_nic_update_stats(const struct ef4_hw_stat_desc *desc, size_t count, const unsigned long *mask, u64 *stats, const void *dma_buf, bool accumulate); diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index b54662d32f55..620ba6ef3514 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1408,7 +1408,7 @@ struct efx_nic_type { int (*fini_dmaq)(struct efx_nic *efx); void (*prepare_flr)(struct efx_nic *efx); void (*finish_flr)(struct efx_nic *efx); - size_t (*describe_stats)(struct efx_nic *efx, u8 *names); + size_t (*describe_stats)(struct efx_nic *efx, u8 **names); size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats, struct rtnl_link_stats64 *core_stats); size_t (*update_stats_atomic)(struct efx_nic *efx, u64 *full_stats, diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index a33ed473cc8a..80aa5e9c732a 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -299,18 +299,15 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf) * bits in the first @count bits of @mask for which a name is defined. */ size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count, - const unsigned long *mask, u8 *names) + const unsigned long *mask, u8 **names) { size_t visible = 0; size_t index; for_each_set_bit(index, mask, count) { if (desc[index].name) { - if (names) { - strscpy(names, desc[index].name, - ETH_GSTRING_LEN); - names += ETH_GSTRING_LEN; - } + if (names) + ethtool_puts(names, desc[index].name); ++visible; } } diff --git a/drivers/net/ethernet/sfc/nic_common.h b/drivers/net/ethernet/sfc/nic_common.h index 7ec4ac7b7ff5..821d91efda19 100644 --- a/drivers/net/ethernet/sfc/nic_common.h +++ b/drivers/net/ethernet/sfc/nic_common.h @@ -241,7 +241,7 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf); #define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1)) size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count, - const unsigned long *mask, u8 *names); + const unsigned long *mask, u8 **names); int efx_nic_copy_stats(struct efx_nic *efx, __le64 *dest); void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count, const unsigned long *mask, u64 *stats, diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 36bceeeb6483..4c7222bf26be 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -399,7 +399,7 @@ static const unsigned long efx_ptp_stat_mask[] = { [0 ... BITS_TO_LONGS(PTP_STAT_COUNT) - 1] = ~0UL, }; -size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 *strings) +size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 **strings) { if (!efx->ptp_data) return 0; diff --git a/drivers/net/ethernet/sfc/ptp.h b/drivers/net/ethernet/sfc/ptp.h index feab7bdd7889..cb9b077921e8 100644 --- a/drivers/net/ethernet/sfc/ptp.h +++ b/drivers/net/ethernet/sfc/ptp.h @@ -30,7 +30,7 @@ int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, unsigned int new_mode); int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); -size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 *strings); +size_t efx_ptp_describe_stats(struct efx_nic *efx, u8 **strings); size_t efx_ptp_update_stats(struct efx_nic *efx, u64 *stats); void efx_time_sync_event(struct efx_channel *channel, efx_qword_t *ev); void __efx_rx_skb_attach_timestamp(struct efx_channel *channel, diff --git a/drivers/net/ethernet/sfc/siena/ethtool_common.c b/drivers/net/ethernet/sfc/siena/ethtool_common.c index 075fef64de68..eeee676fdca7 100644 --- a/drivers/net/ethernet/sfc/siena/ethtool_common.c +++ b/drivers/net/ethernet/sfc/siena/ethtool_common.c @@ -395,7 +395,7 @@ fail: test->flags |= ETH_TEST_FL_FAILED; } -static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings) +static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 **strings) { size_t n_stats = 0; struct efx_channel *channel; @@ -403,24 +403,22 @@ static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings) efx_for_each_channel(channel, efx) { if (efx_channel_has_tx_queues(channel)) { n_stats++; - if (strings != NULL) { - snprintf(strings, ETH_GSTRING_LEN, - "tx-%u.tx_packets", - channel->tx_queue[0].queue / - EFX_MAX_TXQ_PER_CHANNEL); + if (!strings) + continue; - strings += ETH_GSTRING_LEN; - } + ethtool_sprintf(strings, "tx-%u.tx_packets", + channel->tx_queue[0].queue / + EFX_MAX_TXQ_PER_CHANNEL); } } efx_for_each_channel(channel, efx) { if (efx_channel_has_rx_queue(channel)) { n_stats++; - if (strings != NULL) { - snprintf(strings, ETH_GSTRING_LEN, - "rx-%d.rx_packets", channel->channel); - strings += ETH_GSTRING_LEN; - } + if (!strings) + continue; + + ethtool_sprintf(strings, "rx-%d.rx_packets", + channel->channel); } } if (efx->xdp_tx_queue_count && efx->xdp_tx_queues) { @@ -428,11 +426,11 @@ static size_t efx_describe_per_queue_stats(struct efx_nic *efx, u8 *strings) for (xdp = 0; xdp < efx->xdp_tx_queue_count; xdp++) { n_stats++; - if (strings) { - snprintf(strings, ETH_GSTRING_LEN, - "tx-xdp-cpu-%hu.tx_packets", xdp); - strings += ETH_GSTRING_LEN; - } + if (!strings) + continue; + + ethtool_sprintf(strings, "tx-xdp-cpu-%hu.tx_packets", + xdp); } } @@ -464,15 +462,11 @@ void efx_siena_ethtool_get_strings(struct net_device *net_dev, switch (string_set) { case ETH_SS_STATS: - strings += (efx->type->describe_stats(efx, strings) * - ETH_GSTRING_LEN); + efx->type->describe_stats(efx, &strings); for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++) - strscpy(strings + i * ETH_GSTRING_LEN, - efx_sw_stat_desc[i].name, ETH_GSTRING_LEN); - strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN; - strings += (efx_describe_per_queue_stats(efx, strings) * - ETH_GSTRING_LEN); - efx_siena_ptp_describe_stats(efx, strings); + ethtool_puts(&strings, efx_sw_stat_desc[i].name); + efx_describe_per_queue_stats(efx, &strings); + efx_siena_ptp_describe_stats(efx, &strings); break; case ETH_SS_TEST: efx_ethtool_fill_self_tests(efx, NULL, strings, NULL); diff --git a/drivers/net/ethernet/sfc/siena/net_driver.h b/drivers/net/ethernet/sfc/siena/net_driver.h index 3fa7c652ae9b..9785eff10607 100644 --- a/drivers/net/ethernet/sfc/siena/net_driver.h +++ b/drivers/net/ethernet/sfc/siena/net_driver.h @@ -1307,7 +1307,7 @@ struct efx_nic_type { void (*finish_flush)(struct efx_nic *efx); void (*prepare_flr)(struct efx_nic *efx); void (*finish_flr)(struct efx_nic *efx); - size_t (*describe_stats)(struct efx_nic *efx, u8 *names); + size_t (*describe_stats)(struct efx_nic *efx, u8 **names); size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats, struct rtnl_link_stats64 *core_stats); size_t (*update_stats_atomic)(struct efx_nic *efx, u64 *full_stats, diff --git a/drivers/net/ethernet/sfc/siena/nic.c b/drivers/net/ethernet/sfc/siena/nic.c index 0ea0433a6230..32fce70085e3 100644 --- a/drivers/net/ethernet/sfc/siena/nic.c +++ b/drivers/net/ethernet/sfc/siena/nic.c @@ -449,20 +449,20 @@ void efx_siena_get_regs(struct efx_nic *efx, void *buf) * Returns the number of visible statistics, i.e. the number of set * bits in the first @count bits of @mask for which a name is defined. */ -size_t efx_siena_describe_stats(const struct efx_hw_stat_desc *desc, size_t count, - const unsigned long *mask, u8 *names) +size_t efx_siena_describe_stats(const struct efx_hw_stat_desc *desc, + size_t count, const unsigned long *mask, + u8 **names) { size_t visible = 0; size_t index; for_each_set_bit(index, mask, count) { if (desc[index].name) { - if (names) { - strscpy(names, desc[index].name, - ETH_GSTRING_LEN); - names += ETH_GSTRING_LEN; - } ++visible; + if (!names) + continue; + + ethtool_puts(names, desc[index].name); } } diff --git a/drivers/net/ethernet/sfc/siena/nic_common.h b/drivers/net/ethernet/sfc/siena/nic_common.h index 3af0405eeaa4..b7fbe198008d 100644 --- a/drivers/net/ethernet/sfc/siena/nic_common.h +++ b/drivers/net/ethernet/sfc/siena/nic_common.h @@ -239,8 +239,9 @@ void efx_siena_get_regs(struct efx_nic *efx, void *buf); #define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1)) -size_t efx_siena_describe_stats(const struct efx_hw_stat_desc *desc, size_t count, - const unsigned long *mask, u8 *names); +size_t efx_siena_describe_stats(const struct efx_hw_stat_desc *desc, + size_t count, const unsigned long *mask, + u8 **names); void efx_siena_update_stats(const struct efx_hw_stat_desc *desc, size_t count, const unsigned long *mask, u64 *stats, const void *dma_buf, bool accumulate); diff --git a/drivers/net/ethernet/sfc/siena/ptp.c b/drivers/net/ethernet/sfc/siena/ptp.c index 85005196b4c5..062c77c92077 100644 --- a/drivers/net/ethernet/sfc/siena/ptp.c +++ b/drivers/net/ethernet/sfc/siena/ptp.c @@ -393,7 +393,7 @@ static const unsigned long efx_ptp_stat_mask[] = { [0 ... BITS_TO_LONGS(PTP_STAT_COUNT) - 1] = ~0UL, }; -size_t efx_siena_ptp_describe_stats(struct efx_nic *efx, u8 *strings) +size_t efx_siena_ptp_describe_stats(struct efx_nic *efx, u8 **strings) { if (!efx->ptp_data) return 0; diff --git a/drivers/net/ethernet/sfc/siena/ptp.h b/drivers/net/ethernet/sfc/siena/ptp.h index b6133e7c5608..54840036ab67 100644 --- a/drivers/net/ethernet/sfc/siena/ptp.h +++ b/drivers/net/ethernet/sfc/siena/ptp.h @@ -28,7 +28,7 @@ int efx_siena_ptp_change_mode(struct efx_nic *efx, bool enable_wanted, unsigned int new_mode); int efx_siena_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); void efx_siena_ptp_event(struct efx_nic *efx, efx_qword_t *ev); -size_t efx_siena_ptp_describe_stats(struct efx_nic *efx, u8 *strings); +size_t efx_siena_ptp_describe_stats(struct efx_nic *efx, u8 **strings); size_t efx_siena_ptp_update_stats(struct efx_nic *efx, u64 *stats); void efx_siena_time_sync_event(struct efx_channel *channel, efx_qword_t *ev); void __efx_siena_rx_skb_attach_timestamp(struct efx_channel *channel, diff --git a/drivers/net/ethernet/sfc/siena/siena.c b/drivers/net/ethernet/sfc/siena/siena.c index ca33dc08e555..49f0c8a1a90a 100644 --- a/drivers/net/ethernet/sfc/siena/siena.c +++ b/drivers/net/ethernet/sfc/siena/siena.c @@ -545,7 +545,7 @@ static const unsigned long siena_stat_mask[] = { [0 ... BITS_TO_LONGS(SIENA_STAT_COUNT) - 1] = ~0UL, }; -static size_t siena_describe_nic_stats(struct efx_nic *efx, u8 *names) +static size_t siena_describe_nic_stats(struct efx_nic *efx, u8 **names) { return efx_siena_describe_stats(siena_stat_desc, SIENA_STAT_COUNT, siena_stat_mask, names); -- 2.51.0 From e629295bd60abf4da1db85b82819ca6a4f6c1e79 Mon Sep 17 00:00:00 2001 From: Hyunwoo Kim Date: Wed, 6 Nov 2024 04:36:04 -0500 Subject: [PATCH 08/16] hv_sock: Initializing vsk->trans to NULL to prevent a dangling pointer When hvs is released, there is a possibility that vsk->trans may not be initialized to NULL, which could lead to a dangling pointer. This issue is resolved by initializing vsk->trans to NULL. Signed-off-by: Hyunwoo Kim Reviewed-by: Stefano Garzarella Acked-by: Michael S. Tsirkin Link: https://patch.msgid.link/Zys4hCj61V+mQfX2@v4bel-B760M-AORUS-ELITE-AX Signed-off-by: Jakub Kicinski --- net/vmw_vsock/hyperv_transport.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c index e2157e387217..56c232cf5b0f 100644 --- a/net/vmw_vsock/hyperv_transport.c +++ b/net/vmw_vsock/hyperv_transport.c @@ -549,6 +549,7 @@ static void hvs_destruct(struct vsock_sock *vsk) vmbus_hvsock_device_unregister(chan); kfree(hvs); + vsk->trans = NULL; } static int hvs_dgram_bind(struct vsock_sock *vsk, struct sockaddr_vm *addr) -- 2.51.0 From 2b08dfcc2ce7b013d89f58885e674fb7788c7ac9 Mon Sep 17 00:00:00 2001 From: Andrew Kreimer Date: Wed, 6 Nov 2024 13:24:20 +0200 Subject: [PATCH 09/16] mISDN: Fix typos Fix typos: - syncronized -> synchronized - interfacs -> interface - otherwhise -> otherwise - ony -> only - busses -> buses - maxinum -> maximum Via codespell. Reported-by: Simon Horman Signed-off-by: Andrew Kreimer Reviewed-by: Simon Horman Link: https://patch.msgid.link/20241106112513.9559-1-algonell@gmail.com Signed-off-by: Jakub Kicinski --- drivers/isdn/hardware/mISDN/hfcmulti.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index e5a483fd9ad8..45ff0e198f8f 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -25,8 +25,8 @@ * Bit 8 = 0x00100 = uLaw (instead of aLaw) * Bit 9 = 0x00200 = Disable DTMF detect on all B-channels via hardware * Bit 10 = spare - * Bit 11 = 0x00800 = Force PCM bus into slave mode. (otherwhise auto) - * or Bit 12 = 0x01000 = Force PCM bus into master mode. (otherwhise auto) + * Bit 11 = 0x00800 = Force PCM bus into slave mode. (otherwise auto) + * or Bit 12 = 0x01000 = Force PCM bus into master mode. (otherwise auto) * Bit 13 = spare * Bit 14 = 0x04000 = Use external ram (128K) * Bit 15 = 0x08000 = Use external ram (512K) @@ -41,7 +41,7 @@ * port: (optional or required for all ports on all installed cards) * HFC-4S/HFC-8S only bits: * Bit 0 = 0x001 = Use master clock for this S/T interface - * (ony once per chip). + * (only once per chip). * Bit 1 = 0x002 = transmitter line setup (non capacitive mode) * Don't use this unless you know what you are doing! * Bit 2 = 0x004 = Disable E-channel. (No E-channel processing) @@ -82,7 +82,7 @@ * By default (0), the PCM bus id is 100 for the card that is PCM master. * If multiple cards are PCM master (because they are not interconnected), * each card with PCM master will have increasing PCM id. - * All PCM busses with the same ID are expected to be connected and have + * All PCM buses with the same ID are expected to be connected and have * common time slots slots. * Only one chip of the PCM bus must be master, the others slave. * -1 means no support of PCM bus not even. @@ -930,7 +930,7 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) if (newmaster) { hc = newmaster; if (debug & DEBUG_HFCMULTI_PLXSD) - printk(KERN_DEBUG "id=%d (0x%p) = syncronized with " + printk(KERN_DEBUG "id=%d (0x%p) = synchronized with " "interface.\n", hc->id, hc); /* Enable new sync master */ plx_acc_32 = hc->plx_membase + PLX_GPIOC; @@ -949,7 +949,7 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) hc = pcmmaster; if (debug & DEBUG_HFCMULTI_PLXSD) printk(KERN_DEBUG - "id=%d (0x%p) = PCM master syncronized " + "id=%d (0x%p) = PCM master synchronized " "with QUARTZ\n", hc->id, hc); if (hc->ctype == HFC_TYPE_E1) { /* Use the crystal clock for the PCM @@ -2001,7 +2001,7 @@ next_frame: if (Zspace <= 0) Zspace += hc->Zlen; Zspace -= 4; /* keep not too full, so pointers will not overrun */ - /* fill transparent data only to maxinum transparent load (minus 4) */ + /* fill transparent data only to maximum transparent load (minus 4) */ if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags)) Zspace = Zspace - hc->Zlen + hc->max_trans; if (Zspace <= 0) /* no space of 4 bytes */ @@ -4672,7 +4672,7 @@ init_e1_port_hw(struct hfc_multi *hc, struct hm_map *m) if (debug & DEBUG_HFCMULTI_INIT) printk(KERN_DEBUG "%s: PORT set optical " - "interfacs: card(%d) " + "interface: card(%d) " "port(%d)\n", __func__, HFC_cnt + 1, 1); -- 2.51.0 From cf6d9fe09185aa7e296c24385940f29a1364e87d Mon Sep 17 00:00:00 2001 From: Abhinav Saxena Date: Fri, 8 Nov 2024 12:56:42 -0700 Subject: [PATCH 10/16] tc: fix typo probabilty in tc.yaml doc Fix spelling of "probability" in tc.yaml documentation. This corrects the max-P field description in struct tc_sfq_qopt_v1. Signed-off-by: Abhinav Saxena Link: https://patch.msgid.link/20241108195642.139315-1-xandfury@gmail.com Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/tc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/netlink/specs/tc.yaml b/Documentation/netlink/specs/tc.yaml index b02d59a0349c..aacccea5dfe4 100644 --- a/Documentation/netlink/specs/tc.yaml +++ b/Documentation/netlink/specs/tc.yaml @@ -622,7 +622,7 @@ definitions: - name: max-P type: u32 - doc: probabilty, high resolution + doc: probability, high resolution - name: stats type: binary -- 2.51.0 From c507e96b5763b36b63ad50ad804341f72ea000e4 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 6 Nov 2024 17:55:45 +0100 Subject: [PATCH 11/16] r8169: improve __rtl8169_set_wol Add helper r8169_mod_reg8_cond() what allows to significantly simplify __rtl8169_set_wol(). Signed-off-by: Heiner Kallweit Reviewed-by: Simon Horman Link: https://patch.msgid.link/697b197a-8eac-40c6-8847-27093cacec36@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/realtek/r8169_main.c | 55 ++++++++++------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index c7dc8b539b3e..2ff95fde4489 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -748,6 +748,20 @@ static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set) RTL_W8(tp, Config5, (val & ~clear) | set); } +static void r8169_mod_reg8_cond(struct rtl8169_private *tp, int reg, + u8 bits, bool cond) +{ + u8 val, old_val; + + old_val = RTL_R8(tp, reg); + if (cond) + val = old_val | bits; + else + val = old_val & ~bits; + if (val != old_val) + RTL_W8(tp, reg, val); +} + static bool rtl_is_8125(struct rtl8169_private *tp) { return tp->mac_version >= RTL_GIGA_MAC_VER_61; @@ -1538,58 +1552,37 @@ static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) { - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_PHY, Config3, LinkUp }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake }, - { WAKE_MAGIC, Config3, MagicPacket } - }; - unsigned int i, tmp = ARRAY_SIZE(cfg); - u8 options; - rtl_unlock_config_regs(tp); if (rtl_is_8168evl_up(tp)) { - tmp--; if (wolopts & WAKE_MAGIC) rtl_eri_set_bits(tp, 0x0dc, MagicPacket_v2); else rtl_eri_clear_bits(tp, 0x0dc, MagicPacket_v2); } else if (rtl_is_8125(tp)) { - tmp--; if (wolopts & WAKE_MAGIC) r8168_mac_ocp_modify(tp, 0xc0b6, 0, BIT(0)); else r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0); + } else { + r8169_mod_reg8_cond(tp, Config3, MagicPacket, + wolopts & WAKE_MAGIC); } - for (i = 0; i < tmp; i++) { - options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(tp, cfg[i].reg, options); - } + r8169_mod_reg8_cond(tp, Config3, LinkUp, wolopts & WAKE_PHY); + r8169_mod_reg8_cond(tp, Config5, UWF, wolopts & WAKE_UCAST); + r8169_mod_reg8_cond(tp, Config5, BWF, wolopts & WAKE_BCAST); + r8169_mod_reg8_cond(tp, Config5, MWF, wolopts & WAKE_MCAST); + r8169_mod_reg8_cond(tp, Config5, LanWake, wolopts); switch (tp->mac_version) { case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: - options = RTL_R8(tp, Config1) & ~PMEnable; - if (wolopts) - options |= PMEnable; - RTL_W8(tp, Config1, options); + r8169_mod_reg8_cond(tp, Config1, PMEnable, wolopts); break; case RTL_GIGA_MAC_VER_34: case RTL_GIGA_MAC_VER_37: case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_66: - if (wolopts) - rtl_mod_config2(tp, 0, PME_SIGNAL); - else - rtl_mod_config2(tp, PME_SIGNAL, 0); + r8169_mod_reg8_cond(tp, Config2, PME_SIGNAL, wolopts); break; default: break; -- 2.51.0 From 330dc2297c82953dff402e0b4176a5383a618538 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 6 Nov 2024 17:56:28 +0100 Subject: [PATCH 12/16] r8169: improve rtl_set_d3_pll_down Make use of new helper r8169_mod_reg8_cond() and move from a switch() to an if() clause. Benefit is that we don't have to touch this piece of code each time support for a new chip version is added. Signed-off-by: Heiner Kallweit Reviewed-by: Simon Horman Link: https://patch.msgid.link/e1ccdb85-a4ed-4800-89c2-89770ff06452@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/realtek/r8169_main.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 2ff95fde4489..43b03176c692 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -1431,19 +1431,11 @@ static enum rtl_dash_type rtl_get_dash_type(struct rtl8169_private *tp) static void rtl_set_d3_pll_down(struct rtl8169_private *tp, bool enable) { - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30: - case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_66: - if (enable) - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~D3_NO_PLL_DOWN); - else - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | D3_NO_PLL_DOWN); - break; - default: - break; - } + if (tp->mac_version >= RTL_GIGA_MAC_VER_25 && + tp->mac_version != RTL_GIGA_MAC_VER_28 && + tp->mac_version != RTL_GIGA_MAC_VER_31 && + tp->mac_version != RTL_GIGA_MAC_VER_38) + r8169_mod_reg8_cond(tp, PMCH, D3_NO_PLL_DOWN, !enable); } static void rtl_reset_packet_filter(struct rtl8169_private *tp) -- 2.51.0 From e3e9e9039fa6ae885c7d5c954d7b9f105fa23e8f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 6 Nov 2024 17:57:08 +0100 Subject: [PATCH 13/16] r8169: align WAKE_PHY handling with r8125/r8126 vendor drivers Vendor drivers r8125/r8126 apply this additional magic setting when enabling WAKE_PHY, so do the same here. Signed-off-by: Heiner Kallweit Reviewed-by: Simon Horman Link: https://patch.msgid.link/51130715-45be-4db5-abb7-05d87e1f5df9@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/realtek/r8169_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 43b03176c692..6578a9947b82 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -1562,6 +1562,9 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) } r8169_mod_reg8_cond(tp, Config3, LinkUp, wolopts & WAKE_PHY); + if (rtl_is_8125(tp)) + r8168_mac_ocp_modify(tp, 0xe0c6, 0x3f, + wolopts & WAKE_PHY ? 0x13 : 0); r8169_mod_reg8_cond(tp, Config5, UWF, wolopts & WAKE_UCAST); r8169_mod_reg8_cond(tp, Config5, BWF, wolopts & WAKE_BCAST); r8169_mod_reg8_cond(tp, Config5, MWF, wolopts & WAKE_MCAST); -- 2.51.0 From 41b3caa7c0761141aa6d508924b9d23db57a17bc Mon Sep 17 00:00:00 2001 From: Gilad Naaman Date: Thu, 7 Nov 2024 16:04:38 +0000 Subject: [PATCH 14/16] neighbour: Add hlist_node to struct neighbour Add a doubly-linked node to neighbours, so that they can be deleted without iterating the entire bucket they're in. Signed-off-by: Gilad Naaman Reviewed-by: Kuniyuki Iwashima Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20241107160444.2913124-2-gnaaman@drivenets.com Signed-off-by: Jakub Kicinski --- include/net/neighbour.h | 2 ++ net/core/neighbour.c | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 3887ed9e5026..0402447854c7 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -136,6 +136,7 @@ struct neigh_statistics { struct neighbour { struct neighbour __rcu *next; + struct hlist_node hash; struct neigh_table *tbl; struct neigh_parms *parms; unsigned long confirmed; @@ -191,6 +192,7 @@ struct pneigh_entry { struct neigh_hash_table { struct neighbour __rcu **hash_buckets; + struct hlist_head *hash_heads; unsigned int hash_shift; __u32 hash_rnd[NEIGH_NUM_HASH_RND]; struct rcu_head rcu; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 4b871cecd2ce..5552e6b05c82 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -216,6 +216,7 @@ static bool neigh_del(struct neighbour *n, struct neighbour __rcu **np, neigh = rcu_dereference_protected(n->next, lockdep_is_held(&tbl->lock)); rcu_assign_pointer(*np, neigh); + hlist_del_rcu(&n->hash); neigh_mark_dead(n); retval = true; } @@ -402,6 +403,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev, rcu_assign_pointer(*np, rcu_dereference_protected(n->next, lockdep_is_held(&tbl->lock))); + hlist_del_rcu(&n->hash); write_lock(&n->lock); neigh_del_timer(n); neigh_mark_dead(n); @@ -529,20 +531,30 @@ static void neigh_get_hash_rnd(u32 *x) static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift) { + size_t hash_heads_size = (1 << shift) * sizeof(struct hlist_head); size_t size = (1 << shift) * sizeof(struct neighbour *); - struct neigh_hash_table *ret; struct neighbour __rcu **buckets; + struct hlist_head *hash_heads; + struct neigh_hash_table *ret; int i; ret = kmalloc(sizeof(*ret), GFP_ATOMIC); if (!ret) return NULL; + buckets = kvzalloc(size, GFP_ATOMIC); if (!buckets) { kfree(ret); return NULL; } + hash_heads = kvzalloc(hash_heads_size, GFP_ATOMIC); + if (!hash_heads) { + kvfree(buckets); + kfree(ret); + return NULL; + } ret->hash_buckets = buckets; + ret->hash_heads = hash_heads; ret->hash_shift = shift; for (i = 0; i < NEIGH_NUM_HASH_RND; i++) neigh_get_hash_rnd(&ret->hash_rnd[i]); @@ -556,6 +568,7 @@ static void neigh_hash_free_rcu(struct rcu_head *head) rcu); kvfree(nht->hash_buckets); + kvfree(nht->hash_heads); kfree(nht); } @@ -592,6 +605,8 @@ static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl, new_nht->hash_buckets[hash], lockdep_is_held(&tbl->lock))); rcu_assign_pointer(new_nht->hash_buckets[hash], n); + hlist_del_rcu(&n->hash); + hlist_add_head_rcu(&n->hash, &new_nht->hash_heads[hash]); } } @@ -702,6 +717,7 @@ ___neigh_create(struct neigh_table *tbl, const void *pkey, rcu_dereference_protected(nht->hash_buckets[hash_val], lockdep_is_held(&tbl->lock))); rcu_assign_pointer(nht->hash_buckets[hash_val], n); + hlist_add_head_rcu(&n->hash, &nht->hash_heads[hash_val]); write_unlock_bh(&tbl->lock); neigh_dbg(2, "neigh %p is created\n", n); rc = n; @@ -987,6 +1003,7 @@ static void neigh_periodic_work(struct work_struct *work) rcu_assign_pointer(*np, rcu_dereference_protected(n->next, lockdep_is_held(&tbl->lock))); + hlist_del_rcu(&n->hash); neigh_mark_dead(n); write_unlock(&n->lock); neigh_cleanup_and_release(n); @@ -3116,6 +3133,7 @@ void __neigh_for_each_release(struct neigh_table *tbl, rcu_assign_pointer(*np, rcu_dereference_protected(n->next, lockdep_is_held(&tbl->lock))); + hlist_del_rcu(&n->hash); neigh_mark_dead(n); } else np = &n->next; -- 2.51.0 From d7ddee1a522ddf5b28e2a3f7093cf238c96f492a Mon Sep 17 00:00:00 2001 From: Gilad Naaman Date: Thu, 7 Nov 2024 16:04:39 +0000 Subject: [PATCH 15/16] neighbour: Define neigh_for_each_in_bucket Introduce neigh_for_each_in_bucket in neighbour.h, to help iterate over the neighbour table more succinctly. Signed-off-by: Gilad Naaman Reviewed-by: Kuniyuki Iwashima Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20241107160444.2913124-3-gnaaman@drivenets.com Signed-off-by: Jakub Kicinski --- include/net/neighbour.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 0402447854c7..4b9068c5e668 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -277,6 +277,12 @@ static inline void *neighbour_priv(const struct neighbour *n) extern const struct nla_policy nda_policy[]; +#define neigh_for_each_in_bucket(pos, head) hlist_for_each_entry(pos, head, hash) +#define neigh_for_each_in_bucket_rcu(pos, head) \ + hlist_for_each_entry_rcu(pos, head, hash) +#define neigh_for_each_in_bucket_safe(pos, tmp, head) \ + hlist_for_each_entry_safe(pos, tmp, head, hash) + static inline bool neigh_key_eq32(const struct neighbour *n, const void *pkey) { return *(const u32 *)n->primary_key == *(const u32 *)pkey; -- 2.51.0 From 00df5e1a3fdf36624d59ef6ab09010ebaee6e66a Mon Sep 17 00:00:00 2001 From: Gilad Naaman Date: Thu, 7 Nov 2024 16:04:40 +0000 Subject: [PATCH 16/16] neighbour: Convert seq_file functions to use hlist Convert seq_file-related neighbour functionality to use neighbour::hash and the related for_each macro. Signed-off-by: Gilad Naaman Reviewed-by: Kuniyuki Iwashima Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20241107160444.2913124-4-gnaaman@drivenets.com Signed-off-by: Jakub Kicinski --- net/core/neighbour.c | 104 ++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 56 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 5552e6b05c82..3485d6b3ba99 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -3193,43 +3193,53 @@ EXPORT_SYMBOL(neigh_xmit); #ifdef CONFIG_PROC_FS -static struct neighbour *neigh_get_first(struct seq_file *seq) +static struct neighbour *neigh_get_valid(struct seq_file *seq, + struct neighbour *n, + loff_t *pos) { struct neigh_seq_state *state = seq->private; struct net *net = seq_file_net(seq); + + if (!net_eq(dev_net(n->dev), net)) + return NULL; + + if (state->neigh_sub_iter) { + loff_t fakep = 0; + void *v; + + v = state->neigh_sub_iter(state, n, pos ? pos : &fakep); + if (!v) + return NULL; + if (pos) + return v; + } + + if (!(state->flags & NEIGH_SEQ_SKIP_NOARP)) + return n; + + if (READ_ONCE(n->nud_state) & ~NUD_NOARP) + return n; + + return NULL; +} + +static struct neighbour *neigh_get_first(struct seq_file *seq) +{ + struct neigh_seq_state *state = seq->private; struct neigh_hash_table *nht = state->nht; - struct neighbour *n = NULL; - int bucket; + struct neighbour *n, *tmp; state->flags &= ~NEIGH_SEQ_IS_PNEIGH; - for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) { - n = rcu_dereference(nht->hash_buckets[bucket]); - - while (n) { - if (!net_eq(dev_net(n->dev), net)) - goto next; - if (state->neigh_sub_iter) { - loff_t fakep = 0; - void *v; - v = state->neigh_sub_iter(state, n, &fakep); - if (!v) - goto next; - } - if (!(state->flags & NEIGH_SEQ_SKIP_NOARP)) - break; - if (READ_ONCE(n->nud_state) & ~NUD_NOARP) - break; -next: - n = rcu_dereference(n->next); + while (++state->bucket < (1 << nht->hash_shift)) { + neigh_for_each_in_bucket(n, &nht->hash_heads[state->bucket]) { + tmp = neigh_get_valid(seq, n, NULL); + if (tmp) + return tmp; } - - if (n) - break; } - state->bucket = bucket; - return n; + return NULL; } static struct neighbour *neigh_get_next(struct seq_file *seq, @@ -3237,46 +3247,28 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, loff_t *pos) { struct neigh_seq_state *state = seq->private; - struct net *net = seq_file_net(seq); - struct neigh_hash_table *nht = state->nht; + struct neighbour *tmp; if (state->neigh_sub_iter) { void *v = state->neigh_sub_iter(state, n, pos); + if (v) return n; } - n = rcu_dereference(n->next); - - while (1) { - while (n) { - if (!net_eq(dev_net(n->dev), net)) - goto next; - if (state->neigh_sub_iter) { - void *v = state->neigh_sub_iter(state, n, pos); - if (v) - return n; - goto next; - } - if (!(state->flags & NEIGH_SEQ_SKIP_NOARP)) - break; - if (READ_ONCE(n->nud_state) & ~NUD_NOARP) - break; -next: - n = rcu_dereference(n->next); + hlist_for_each_entry_continue(n, hash) { + tmp = neigh_get_valid(seq, n, pos); + if (tmp) { + n = tmp; + goto out; } - - if (n) - break; - - if (++state->bucket >= (1 << nht->hash_shift)) - break; - - n = rcu_dereference(nht->hash_buckets[state->bucket]); } + n = neigh_get_first(seq); +out: if (n && pos) --(*pos); + return n; } @@ -3379,7 +3371,7 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl struct neigh_seq_state *state = seq->private; state->tbl = tbl; - state->bucket = 0; + state->bucket = -1; state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH); rcu_read_lock(); -- 2.51.0