From 8279a8dacf9f975c37f3dc51634b6c4a8936c57b Mon Sep 17 00:00:00 2001 From: Charalampos Mitrodimas Date: Wed, 19 Feb 2025 12:41:55 +0000 Subject: [PATCH 01/16] net: phy: qt2025: Fix hardware revision check comment Correct the hardware revision check comment in the QT2025 driver. The revision value was documented as 0x3b instead of the correct 0xb3, which matches the actual comparison logic in the code. Reviewed-by: FUJITA Tomonori Signed-off-by: Charalampos Mitrodimas Reviewed-by: Andrew Lunn Reviewed-by: Trevor Gross Link: https://patch.msgid.link/20250219-qt2025-comment-fix-v2-1-029f67696516@posteo.net Signed-off-by: Jakub Kicinski --- drivers/net/phy/qt2025.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/qt2025.rs b/drivers/net/phy/qt2025.rs index 1ab065798175..7e754d5d7154 100644 --- a/drivers/net/phy/qt2025.rs +++ b/drivers/net/phy/qt2025.rs @@ -41,7 +41,7 @@ impl Driver for PhyQT2025 { fn probe(dev: &mut phy::Device) -> Result<()> { // Check the hardware revision code. - // Only 0x3b works with this driver and firmware. + // Only 0xb3 works with this driver and firmware. let hw_rev = dev.read(C45::new(Mmd::PMAPMD, 0xd001))?; if (hw_rev >> 8) != 0xb3 { return Err(code::ENODEV); -- 2.50.1 From ca57d1c56f4015d83fe7840b41d74783ee900b28 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 19 Feb 2025 17:21:14 +0100 Subject: [PATCH 02/16] octeontx2: hide unused label A previous patch introduces a build-time warning when CONFIG_DCB is disabled: drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c: In function 'otx2_probe': drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c:3217:1: error: label 'err_free_zc_bmap' defined but not used [-Werror=unused-label] drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c: In function 'otx2vf_probe': drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c:740:1: error: label 'err_free_zc_bmap' defined but not used [-Werror=unused-label] Add the same #ifdef check around it. Fixes: efabce290151 ("octeontx2-pf: AF_XDP zero copy receive support") Signed-off-by: Arnd Bergmann Reviewed-by: Suman Ghosh Link: https://patch.msgid.link/20250219162239.1376865-1-arnd@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 ++ drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index c7c562f0f5e5..cfed9ec5b157 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -3214,8 +3214,10 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; +#ifdef CONFIG_DCB err_free_zc_bmap: bitmap_free(pf->af_xdp_zc_qidx); +#endif err_sriov_cleannup: otx2_sriov_vfcfg_cleanup(pf); err_pf_sriov_init: diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c index 63ddd262d122..7ef3ba477d49 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c @@ -737,8 +737,10 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; +#ifdef CONFIG_DCB err_free_zc_bmap: bitmap_free(vf->af_xdp_zc_qidx); +#endif err_unreg_devlink: otx2_unregister_dl(vf); err_shutdown_tc: -- 2.50.1 From 846742f7e32f632166e3b2a106304b2bec7541a9 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Feb 2025 15:49:50 -0800 Subject: [PATCH 03/16] selftests: drv-net: add a warning for bkg + shell + terminate Joe Damato reports that some shells will fork before running the command when python does "sh -c $cmd", while bash on my machine does an exec of $cmd directly. This will have implications for our ability to terminate the child process on various configurations of bash and other shells. Warn about using bkg(... shell=True, termininate=True) most background commands can hopefully exit cleanly (exit_wait). Link: https://lore.kernel.org/Z7Yld21sv_Ip3gQx@LQ3V64L9R2 Acked-by: Stanislav Fomichev Acked-by: Joe Damato Tested-by: Joe Damato Link: https://patch.msgid.link/20250219234956.520599-2-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/testing/selftests/net/lib/py/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py index 9e3bcddcf3e8..33b153767d89 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -61,6 +61,10 @@ class bkg(cmd): self.terminate = not exit_wait self.check_fail = fail + if shell and self.terminate: + print("# Warning: combining shell and terminate is risky!") + print("# SIGTERM may not reach the child on zsh/ksh!") + def __enter__(self): return self -- 2.50.1 From dabd31baa3b55d90fcb4875db7c1971f5d638718 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Feb 2025 15:49:51 -0800 Subject: [PATCH 04/16] selftests: drv-net: use cfg.rpath() in netlink xsk attr test The cfg.rpath() helper was been recently added to make formatting paths for helper binaries easier. Acked-by: Stanislav Fomichev Reviewed-by: Joe Damato Tested-by: Joe Damato Link: https://patch.msgid.link/20250219234956.520599-3-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/queues.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/testing/selftests/drivers/net/queues.py b/tools/testing/selftests/drivers/net/queues.py index 5fdfebc6415f..b6896a57a5fd 100755 --- a/tools/testing/selftests/drivers/net/queues.py +++ b/tools/testing/selftests/drivers/net/queues.py @@ -25,8 +25,7 @@ def nl_get_queues(cfg, nl, qtype='rx'): return None def check_xdp(cfg, nl, xdp_queue_id=0) -> None: - test_dir = os.path.dirname(os.path.realpath(__file__)) - xdp = subprocess.Popen([f"{test_dir}/xdp_helper", f"{cfg.ifindex}", f"{xdp_queue_id}"], + xdp = subprocess.Popen([cfg.rpath("xdp_helper"), f"{cfg.ifindex}", f"{xdp_queue_id}"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=1, text=True) defer(xdp.kill) -- 2.50.1 From bab59dcf71fbe8f3e710a441f74dc9b76937c3e3 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Feb 2025 15:49:52 -0800 Subject: [PATCH 05/16] selftests: drv-net: add missing new line in xdp_helper Kurt and Joe report missing new line at the end of Usage. Reviewed-by: Kurt Kanzenbach Reviewed-by: Joe Damato Tested-by: Joe Damato Link: https://patch.msgid.link/20250219234956.520599-4-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/xdp_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/drivers/net/xdp_helper.c b/tools/testing/selftests/drivers/net/xdp_helper.c index cf06a88b830b..80f86c2fe1a5 100644 --- a/tools/testing/selftests/drivers/net/xdp_helper.c +++ b/tools/testing/selftests/drivers/net/xdp_helper.c @@ -35,7 +35,7 @@ int main(int argc, char **argv) char byte; if (argc != 3) { - fprintf(stderr, "Usage: %s ifindex queue_id", argv[0]); + fprintf(stderr, "Usage: %s ifindex queue_id\n", argv[0]); return 1; } -- 2.50.1 From d3726ab45c57d0ba26234e3b9e4d19903b740f97 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Feb 2025 15:49:53 -0800 Subject: [PATCH 06/16] selftests: drv-net: probe for AF_XDP sockets more explicitly Separate the support check from socket binding for easier refactoring. Use: ./helper - - just to probe if we can open the socket. Acked-by: Stanislav Fomichev Reviewed-by: Joe Damato Tested-by: Joe Damato Link: https://patch.msgid.link/20250219234956.520599-5-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/queues.py | 12 +++++++----- tools/testing/selftests/drivers/net/xdp_helper.c | 7 +++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/drivers/net/queues.py b/tools/testing/selftests/drivers/net/queues.py index b6896a57a5fd..0c959b2eb618 100755 --- a/tools/testing/selftests/drivers/net/queues.py +++ b/tools/testing/selftests/drivers/net/queues.py @@ -25,6 +25,13 @@ def nl_get_queues(cfg, nl, qtype='rx'): return None def check_xdp(cfg, nl, xdp_queue_id=0) -> None: + # Probe for support + xdp = cmd(cfg.rpath("xdp_helper") + ' - -', fail=False) + if xdp.ret == 255: + raise KsftSkipEx('AF_XDP unsupported') + elif xdp.ret > 0: + raise KsftFailEx('unable to create AF_XDP socket') + xdp = subprocess.Popen([cfg.rpath("xdp_helper"), f"{cfg.ifindex}", f"{xdp_queue_id}"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=1, text=True) @@ -33,11 +40,6 @@ def check_xdp(cfg, nl, xdp_queue_id=0) -> None: stdout, stderr = xdp.communicate(timeout=10) rx = tx = False - if xdp.returncode == 255: - raise KsftSkipEx('AF_XDP unsupported') - elif xdp.returncode > 0: - raise KsftFailEx('unable to create AF_XDP socket') - queues = nl.queue_get({'ifindex': cfg.ifindex}, dump=True) if not queues: raise KsftSkipEx("Netlink reports no queues") diff --git a/tools/testing/selftests/drivers/net/xdp_helper.c b/tools/testing/selftests/drivers/net/xdp_helper.c index 80f86c2fe1a5..2bad3b4d616c 100644 --- a/tools/testing/selftests/drivers/net/xdp_helper.c +++ b/tools/testing/selftests/drivers/net/xdp_helper.c @@ -50,6 +50,13 @@ int main(int argc, char **argv) return 1; } + /* "Probing mode", just checking if AF_XDP sockets are supported */ + if (!strcmp(argv[1], "-") && !strcmp(argv[2], "-")) { + printf("AF_XDP support detected\n"); + close(sock_fd); + return 0; + } + ifindex = atoi(argv[1]); queue = atoi(argv[2]); -- 2.50.1 From 71477137994f4ac8396504bf98346b316da38157 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Feb 2025 15:49:54 -0800 Subject: [PATCH 07/16] selftests: drv-net: add a way to wait for a local process We use wait_port_listen() extensively to wait for a process we spawned to be ready. Not all processes will open listening sockets. Add a method of explicitly waiting for a child to be ready. Pass a FD to the spawned process and wait for it to write a message to us. FD number is passed via KSFT_READY_FD env variable. Similarly use KSFT_WAIT_FD to let the child process for a sign that we are done and child should exit. Sending a signal to a child with shell=True can get tricky. Make use of this method in the queues test to make it less flaky. Acked-by: Stanislav Fomichev Acked-by: Joe Damato Tested-by: Joe Damato Link: https://patch.msgid.link/20250219234956.520599-6-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/queues.py | 49 +++++++------ .../selftests/drivers/net/xdp_helper.c | 54 +++++++++++++-- tools/testing/selftests/net/lib/py/utils.py | 68 +++++++++++++++++-- 3 files changed, 136 insertions(+), 35 deletions(-) diff --git a/tools/testing/selftests/drivers/net/queues.py b/tools/testing/selftests/drivers/net/queues.py index 0c959b2eb618..7af2adb61c25 100755 --- a/tools/testing/selftests/drivers/net/queues.py +++ b/tools/testing/selftests/drivers/net/queues.py @@ -5,13 +5,12 @@ from lib.py import ksft_disruptive, ksft_exit, ksft_run from lib.py import ksft_eq, ksft_raises, KsftSkipEx, KsftFailEx from lib.py import EthtoolFamily, NetdevFamily, NlError from lib.py import NetDrvEnv -from lib.py import cmd, defer, ip +from lib.py import bkg, cmd, defer, ip import errno import glob import os import socket import struct -import subprocess def sys_get_queues(ifname, qtype='rx') -> int: folders = glob.glob(f'/sys/class/net/{ifname}/queues/{qtype}-*') @@ -32,32 +31,30 @@ def check_xdp(cfg, nl, xdp_queue_id=0) -> None: elif xdp.ret > 0: raise KsftFailEx('unable to create AF_XDP socket') - xdp = subprocess.Popen([cfg.rpath("xdp_helper"), f"{cfg.ifindex}", f"{xdp_queue_id}"], - stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=1, - text=True) - defer(xdp.kill) + with bkg(f'{cfg.rpath("xdp_helper")} {cfg.ifindex} {xdp_queue_id}', + ksft_wait=3): - stdout, stderr = xdp.communicate(timeout=10) - rx = tx = False + rx = tx = False + + queues = nl.queue_get({'ifindex': cfg.ifindex}, dump=True) + if not queues: + raise KsftSkipEx("Netlink reports no queues") + + for q in queues: + if q['id'] == 0: + if q['type'] == 'rx': + rx = True + if q['type'] == 'tx': + tx = True + + ksft_eq(q['xsk'], {}) + else: + if 'xsk' in q: + _fail("Check failed: xsk attribute set.") + + ksft_eq(rx, True) + ksft_eq(tx, True) - queues = nl.queue_get({'ifindex': cfg.ifindex}, dump=True) - if not queues: - raise KsftSkipEx("Netlink reports no queues") - - for q in queues: - if q['id'] == 0: - if q['type'] == 'rx': - rx = True - if q['type'] == 'tx': - tx = True - - ksft_eq(q['xsk'], {}) - else: - if 'xsk' in q: - _fail("Check failed: xsk attribute set.") - - ksft_eq(rx, True) - ksft_eq(tx, True) def get_queues(cfg, nl) -> None: snl = NetdevFamily(recv_size=4096) diff --git a/tools/testing/selftests/drivers/net/xdp_helper.c b/tools/testing/selftests/drivers/net/xdp_helper.c index 2bad3b4d616c..aeed25914104 100644 --- a/tools/testing/selftests/drivers/net/xdp_helper.c +++ b/tools/testing/selftests/drivers/net/xdp_helper.c @@ -14,6 +14,54 @@ #define UMEM_SZ (1U << 16) #define NUM_DESC (UMEM_SZ / 2048) +/* Move this to a common header when reused! */ +static void ksft_ready(void) +{ + const char msg[7] = "ready\n"; + char *env_str; + int fd; + + env_str = getenv("KSFT_READY_FD"); + if (env_str) { + fd = atoi(env_str); + if (!fd) { + fprintf(stderr, "invalid KSFT_READY_FD = '%s'\n", + env_str); + return; + } + } else { + fd = STDOUT_FILENO; + } + + write(fd, msg, sizeof(msg)); + if (fd != STDOUT_FILENO) + close(fd); +} + +static void ksft_wait(void) +{ + char *env_str; + char byte; + int fd; + + env_str = getenv("KSFT_WAIT_FD"); + if (env_str) { + fd = atoi(env_str); + if (!fd) { + fprintf(stderr, "invalid KSFT_WAIT_FD = '%s'\n", + env_str); + return; + } + } else { + /* Not running in KSFT env, wait for input from STDIN instead */ + fd = STDIN_FILENO; + } + + read(fd, &byte, sizeof(byte)); + if (fd != STDIN_FILENO) + close(fd); +} + /* this is a simple helper program that creates an XDP socket and does the * minimum necessary to get bind() to succeed. * @@ -32,7 +80,6 @@ int main(int argc, char **argv) int ifindex; int sock_fd; int queue; - char byte; if (argc != 3) { fprintf(stderr, "Usage: %s ifindex queue_id\n", argv[0]); @@ -92,13 +139,12 @@ int main(int argc, char **argv) return 1; } - /* give the parent program some data when the socket is ready*/ - fprintf(stdout, "%d\n", sock_fd); + ksft_ready(); + ksft_wait(); /* parent program will write a byte to stdin when its ready for this * helper to exit */ - read(STDIN_FILENO, &byte, 1); close(sock_fd); return 0; diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py index 33b153767d89..d879700ef2b9 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -2,8 +2,10 @@ import errno import json as _json +import os import random import re +import select import socket import subprocess import time @@ -15,21 +17,56 @@ class CmdExitFailure(Exception): self.cmd = cmd_obj +def fd_read_timeout(fd, timeout): + rlist, _, _ = select.select([fd], [], [], timeout) + if rlist: + return os.read(fd, 1024) + else: + raise TimeoutError("Timeout waiting for fd read") + + class cmd: - def __init__(self, comm, shell=True, fail=True, ns=None, background=False, host=None, timeout=5): + """ + Execute a command on local or remote host. + + Use bkg() instead to run a command in the background. + """ + def __init__(self, comm, shell=True, fail=True, ns=None, background=False, + host=None, timeout=5, ksft_wait=None): if ns: comm = f'ip netns exec {ns} ' + comm self.stdout = None self.stderr = None self.ret = None + self.ksft_term_fd = None self.comm = comm if host: self.proc = host.cmd(comm) else: + # ksft_wait lets us wait for the background process to fully start, + # we pass an FD to the child process, and wait for it to write back. + # Similarly term_fd tells child it's time to exit. + pass_fds = () + env = os.environ.copy() + if ksft_wait is not None: + rfd, ready_fd = os.pipe() + wait_fd, self.ksft_term_fd = os.pipe() + pass_fds = (ready_fd, wait_fd, ) + env["KSFT_READY_FD"] = str(ready_fd) + env["KSFT_WAIT_FD"] = str(wait_fd) + self.proc = subprocess.Popen(comm, shell=shell, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + stderr=subprocess.PIPE, pass_fds=pass_fds, + env=env) + if ksft_wait is not None: + os.close(ready_fd) + os.close(wait_fd) + msg = fd_read_timeout(rfd, ksft_wait) + os.close(rfd) + if not msg: + raise Exception("Did not receive ready message") if not background: self.process(terminate=False, fail=fail, timeout=timeout) @@ -37,6 +74,8 @@ class cmd: if fail is None: fail = not terminate + if self.ksft_term_fd: + os.write(self.ksft_term_fd, b"1") if terminate: self.proc.terminate() stdout, stderr = self.proc.communicate(timeout) @@ -54,11 +93,30 @@ class cmd: class bkg(cmd): + """ + Run a command in the background. + + Examples usage: + + Run a command on remote host, and wait for it to finish. + This is usually paired with wait_port_listen() to make sure + the command has initialized: + + with bkg("socat ...", exit_wait=True, host=cfg.remote) as nc: + ... + + Run a command and expect it to let us know that it's ready + by writing to a special file descriptor passed via KSFT_READY_FD. + Command will be terminated when we exit the context manager: + + with bkg("my_binary", ksft_wait=5): + """ def __init__(self, comm, shell=True, fail=None, ns=None, host=None, - exit_wait=False): + exit_wait=False, ksft_wait=None): super().__init__(comm, background=True, - shell=shell, fail=fail, ns=ns, host=host) - self.terminate = not exit_wait + shell=shell, fail=fail, ns=ns, host=host, + ksft_wait=ksft_wait) + self.terminate = not exit_wait and not ksft_wait self.check_fail = fail if shell and self.terminate: -- 2.50.1 From 4fde8398462f4c07e765460203f6d1b529e3f17a Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Feb 2025 15:49:55 -0800 Subject: [PATCH 08/16] selftests: drv-net: improve the use of ksft helpers in XSK queue test Avoid exceptions when xsk attr is not present, and add a proper ksft helper for "not in" condition. Acked-by: Stanislav Fomichev Reviewed-by: Joe Damato Tested-by: Kurt Kanzenbach Tested-by: Joe Damato Link: https://patch.msgid.link/20250219234956.520599-7-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/queues.py | 9 +++++---- tools/testing/selftests/net/lib/py/ksft.py | 5 +++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/drivers/net/queues.py b/tools/testing/selftests/drivers/net/queues.py index 7af2adb61c25..a49f1a146e28 100755 --- a/tools/testing/selftests/drivers/net/queues.py +++ b/tools/testing/selftests/drivers/net/queues.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: GPL-2.0 from lib.py import ksft_disruptive, ksft_exit, ksft_run -from lib.py import ksft_eq, ksft_raises, KsftSkipEx, KsftFailEx +from lib.py import ksft_eq, ksft_not_in, ksft_raises, KsftSkipEx, KsftFailEx from lib.py import EthtoolFamily, NetdevFamily, NlError from lib.py import NetDrvEnv from lib.py import bkg, cmd, defer, ip @@ -47,10 +47,11 @@ def check_xdp(cfg, nl, xdp_queue_id=0) -> None: if q['type'] == 'tx': tx = True - ksft_eq(q['xsk'], {}) + ksft_eq(q.get('xsk', None), {}, + comment="xsk attr on queue we configured") else: - if 'xsk' in q: - _fail("Check failed: xsk attribute set.") + ksft_not_in('xsk', q, + comment="xsk attr on queue we didn't configure") ksft_eq(rx, True) ksft_eq(tx, True) diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py index 3efe005436cd..fd23349fa8ca 100644 --- a/tools/testing/selftests/net/lib/py/ksft.py +++ b/tools/testing/selftests/net/lib/py/ksft.py @@ -71,6 +71,11 @@ def ksft_in(a, b, comment=""): _fail("Check failed", a, "not in", b, comment) +def ksft_not_in(a, b, comment=""): + if a in b: + _fail("Check failed", a, "in", b, comment) + + def ksft_is(a, b, comment=""): if a is not b: _fail("Check failed", a, "is not", b, comment) -- 2.50.1 From 932a9249f71f88471045edd0c908f0683b10e88c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 19 Feb 2025 15:49:56 -0800 Subject: [PATCH 09/16] selftests: drv-net: rename queues check_xdp to check_xsk The test is for AF_XDP, we refer to AF_XDP as XSK. Acked-by: Stanislav Fomichev Reviewed-by: Joe Damato Tested-by: Joe Damato Link: https://patch.msgid.link/20250219234956.520599-8-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/queues.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/drivers/net/queues.py b/tools/testing/selftests/drivers/net/queues.py index a49f1a146e28..9040baf7b726 100755 --- a/tools/testing/selftests/drivers/net/queues.py +++ b/tools/testing/selftests/drivers/net/queues.py @@ -23,7 +23,8 @@ def nl_get_queues(cfg, nl, qtype='rx'): return len([q for q in queues if q['type'] == qtype]) return None -def check_xdp(cfg, nl, xdp_queue_id=0) -> None: + +def check_xsk(cfg, nl, xdp_queue_id=0) -> None: # Probe for support xdp = cmd(cfg.rpath("xdp_helper") + ' - -', fail=False) if xdp.ret == 255: @@ -116,7 +117,8 @@ def check_down(cfg, nl) -> None: def main() -> None: with NetDrvEnv(__file__, queue_count=100) as cfg: - ksft_run([get_queues, addremove_queues, check_down, check_xdp], args=(cfg, NetdevFamily())) + ksft_run([get_queues, addremove_queues, check_down, check_xsk], + args=(cfg, NetdevFamily())) ksft_exit() -- 2.50.1 From bb3bb6c92e5719c0f5d7adb9d34db7e76705ac33 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 19 Feb 2025 21:15:05 +0100 Subject: [PATCH 10/16] net: phy: remove unused feature array declarations After 12d5151be010 ("net: phy: remove leftovers from switch to linkmode bitmaps") the following declarations are unused and can be removed too. Signed-off-by: Heiner Kallweit Reviewed-by: Michal Swiatkowski Reviewed-by: Mateusz Polchlopek Reviewed-by: Russell King (Oracle) Link: https://patch.msgid.link/b2883c75-4108-48f2-ab73-e81647262bc2@gmail.com Signed-off-by: Jakub Kicinski --- include/linux/phy.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/phy.h b/include/linux/phy.h index 584710e084eb..13be48d3b8b3 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -37,10 +37,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_t1_features) __ro_after_init; extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_basic_t1s_p2mp_features) __ro_after_init; extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_features) __ro_after_init; extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_fibre_features) __ro_after_init; -extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_all_ports_features) __ro_after_init; extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init; -extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init; -extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init; extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_eee_cap1_features) __ro_after_init; extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_eee_cap2_features) __ro_after_init; -- 2.50.1 From a85035561025063125f81090e4f2bd65da368c83 Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Tue, 18 Feb 2025 18:59:40 +0100 Subject: [PATCH 11/16] net: sfp: add quirk for 2.5G OEM BX SFP The OEM SFP-2.5G-BX10-D/U SFP module pair is meant to operate with 2500Base-X. However, in their EEPROM they incorrectly specify: Transceiver codes : 0x00 0x12 0x00 0x00 0x12 0x00 0x01 0x05 0x00 BR, Nominal : 2500MBd Use sfp_quirk_2500basex for this module to allow 2500Base-X mode anyway. Tested on BananaPi R3. Signed-off-by: Birger Koblitz Reviewed-by: Daniel Golle Link: https://patch.msgid.link/20250218-b4-lkmsub-v1-1-1e51dcabed90@birger-koblitz.de Signed-off-by: Jakub Kicinski --- drivers/net/phy/sfp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index 7dbcbf0a4ee2..9369f5297769 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -515,6 +515,8 @@ static const struct sfp_quirk sfp_quirks[] = { SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc), SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g), + SFP_QUIRK_M("OEM", "SFP-2.5G-BX10-D", sfp_quirk_2500basex), + SFP_QUIRK_M("OEM", "SFP-2.5G-BX10-U", sfp_quirk_2500basex), SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc), SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc), SFP_QUIRK_F("Turris", "RTSFP-2.5G", sfp_fixup_rollball), -- 2.50.1 From 3fa337651df581e2beba2d1988344671bfa6f07a Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 19 Feb 2025 08:52:12 +1300 Subject: [PATCH 12/16] dt-bindings: net: Move realtek,rtl9301-switch to net Initially realtek,rtl9301-switch was placed under mfd/ because it had some non-switch related blocks (specifically i2c and reset) but with a bit more review it has become apparent that this was wrong and the binding should live under net/. Signed-off-by: Chris Packham Acked-by: Lee Jones Acked-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250218195216.1034220-2-chris.packham@alliedtelesis.co.nz Signed-off-by: Jakub Kicinski --- .../bindings/{mfd => net}/realtek,rtl9301-switch.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Documentation/devicetree/bindings/{mfd => net}/realtek,rtl9301-switch.yaml (97%) diff --git a/Documentation/devicetree/bindings/mfd/realtek,rtl9301-switch.yaml b/Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml similarity index 97% rename from Documentation/devicetree/bindings/mfd/realtek,rtl9301-switch.yaml rename to Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml index f053303ab1e6..d0a93d5f03aa 100644 --- a/Documentation/devicetree/bindings/mfd/realtek,rtl9301-switch.yaml +++ b/Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- -$id: http://devicetree.org/schemas/mfd/realtek,rtl9301-switch.yaml# +$id: http://devicetree.org/schemas/net/realtek,rtl9301-switch.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Realtek Switch with Internal CPU -- 2.50.1 From 92575a2182376e1244fe0c45e85158f5ebbd7b51 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 19 Feb 2025 08:52:13 +1300 Subject: [PATCH 13/16] dt-bindings: net: Add switch ports and interrupts to RTL9300 Add bindings for the ethernet-switch and interrupt properties for the RTL9300. Signed-off-by: Chris Packham Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250218195216.1034220-3-chris.packham@alliedtelesis.co.nz Signed-off-by: Jakub Kicinski --- .../bindings/net/realtek,rtl9301-switch.yaml | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml b/Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml index d0a93d5f03aa..5d29647bea2d 100644 --- a/Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml +++ b/Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml @@ -14,6 +14,8 @@ description: number of different peripherals are accessed through a common register block, represented here as a syscon node. +$ref: ethernet-switch.yaml#/$defs/ethernet-ports + properties: compatible: items: @@ -28,12 +30,23 @@ properties: reg: maxItems: 1 + interrupts: + maxItems: 2 + + interrupt-names: + items: + - const: switch + - const: nic + '#address-cells': const: 1 '#size-cells': const: 1 + ethernet-ports: + type: object + patternProperties: 'reboot@[0-9a-f]+$': $ref: /schemas/power/reset/syscon-reboot.yaml# @@ -44,6 +57,8 @@ patternProperties: required: - compatible - reg + - interrupts + - interrupt-names additionalProperties: false @@ -52,6 +67,9 @@ examples: ethernet-switch@1b000000 { compatible = "realtek,rtl9301-switch", "syscon", "simple-mfd"; reg = <0x1b000000 0x10000>; + interrupt-parent = <&intc>; + interrupts = <23>, <24>; + interrupt-names = "switch", "nic"; #address-cells = <1>; #size-cells = <1>; @@ -110,5 +128,17 @@ examples: }; }; }; + + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + }; + port@1 { + reg = <1>; + }; + }; }; -- 2.50.1 From 96757457da0ee36b99ced7a978476d521dddd49d Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Wed, 19 Feb 2025 08:52:14 +1300 Subject: [PATCH 14/16] dt-bindings: net: Add Realtek MDIO controller Add dtschema for the MDIO controller found in the RTL9300 Ethernet switch. The controller is slightly unusual in that direct MDIO communication is not possible. We model the MDIO controller with the MDIO buses as child nodes and the PHYs as children of the buses. The mapping of switch port number to MDIO bus/addr requires the ethernet-ports sibling to provide the mapping via the phy-handle property. Signed-off-by: Chris Packham Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20250218195216.1034220-4-chris.packham@alliedtelesis.co.nz Signed-off-by: Jakub Kicinski --- .../bindings/net/realtek,rtl9301-mdio.yaml | 86 +++++++++++++++++++ .../bindings/net/realtek,rtl9301-switch.yaml | 31 +++++++ 2 files changed, 117 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml diff --git a/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml b/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml new file mode 100644 index 000000000000..02e4e33e9969 --- /dev/null +++ b/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/realtek,rtl9301-mdio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Realtek RTL9300 MDIO Controller + +maintainers: + - Chris Packham + +properties: + compatible: + oneOf: + - items: + - enum: + - realtek,rtl9302b-mdio + - realtek,rtl9302c-mdio + - realtek,rtl9303-mdio + - const: realtek,rtl9301-mdio + - const: realtek,rtl9301-mdio + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + reg: + maxItems: 1 + +patternProperties: + '^mdio-bus@[0-3]$': + $ref: mdio.yaml# + + properties: + reg: + maxItems: 1 + + required: + - reg + + patternProperties: + '^ethernet-phy@[a-f0-9]+$': + type: object + $ref: ethernet-phy.yaml# + unevaluatedProperties: false + + unevaluatedProperties: false + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + mdio-controller@ca00 { + compatible = "realtek,rtl9301-mdio"; + reg = <0xca00 0x200>; + #address-cells = <1>; + #size-cells = <0>; + + mdio-bus@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0>; + }; + }; + + mdio-bus@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml b/Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml index 5d29647bea2d..80eabc170669 100644 --- a/Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml +++ b/Documentation/devicetree/bindings/net/realtek,rtl9301-switch.yaml @@ -54,6 +54,9 @@ patternProperties: 'i2c@[0-9a-f]+$': $ref: /schemas/i2c/realtek,rtl9301-i2c.yaml# + 'mdio-controller@[0-9a-f]+$': + $ref: realtek,rtl9301-mdio.yaml# + required: - compatible - reg @@ -129,15 +132,43 @@ examples: }; }; + mdio-controller@ca00 { + compatible = "realtek,rtl9301-mdio"; + reg = <0xca00 0x200>; + #address-cells = <1>; + #size-cells = <0>; + + mdio-bus@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + phy1: ethernet-phy@0 { + reg = <0>; + }; + }; + mdio-bus@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + phy2: ethernet-phy@0 { + reg = <0>; + }; + }; + }; + ethernet-ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; + phy-handle = <&phy1>; }; port@1 { reg = <1>; + phy-handle = <&phy2>; }; }; }; -- 2.50.1 From ec061546c6cffbb8929495bba3953f0cc5e177fa Mon Sep 17 00:00:00 2001 From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:27 +0800 Subject: [PATCH 15/16] rtnetlink: Lookup device in target netns when creating link When creating link, lookup for existing device in target net namespace instead of current one. For example, two links created by: # ip link add dummy1 type dummy # ip link add netns ns1 dummy1 type dummy should have no conflict since they are in different namespaces. Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima Link: https://patch.msgid.link/20250219125039.18024-2-shaw.leon@gmail.com Signed-off-by: Jakub Kicinski --- net/core/rtnetlink.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index abe1a461ea67..0f3e2c6021de 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3867,20 +3867,26 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, { struct nlattr ** const tb = tbs->tb; struct net *net = sock_net(skb->sk); + struct net *device_net; struct net_device *dev; struct ifinfomsg *ifm; bool link_specified; + /* When creating, lookup for existing device in target net namespace */ + device_net = (nlh->nlmsg_flags & NLM_F_CREATE) && + (nlh->nlmsg_flags & NLM_F_EXCL) ? + tgt_net : net; + ifm = nlmsg_data(nlh); if (ifm->ifi_index > 0) { link_specified = true; - dev = __dev_get_by_index(net, ifm->ifi_index); + dev = __dev_get_by_index(device_net, ifm->ifi_index); } else if (ifm->ifi_index < 0) { NL_SET_ERR_MSG(extack, "ifindex can't be negative"); return -EINVAL; } else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) { link_specified = true; - dev = rtnl_dev_get(net, tb); + dev = rtnl_dev_get(device_net, tb); } else { link_specified = false; dev = NULL; -- 2.50.1 From 69c7be1b903fca2835e80ec506bd1d75ce84fb4d Mon Sep 17 00:00:00 2001 From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:28 +0800 Subject: [PATCH 16/16] rtnetlink: Pack newlink() params into struct There are 4 net namespaces involved when creating links: - source netns - where the netlink socket resides, - target netns - where to put the device being created, - link netns - netns associated with the device (backend), - peer netns - netns of peer device. Currently, two nets are passed to newlink() callback - "src_net" parameter and "dev_net" (implicitly in net_device). They are set as follows, depending on netlink attributes in the request. +------------+-------------------+---------+---------+ | peer netns | IFLA_LINK_NETNSID | src_net | dev_net | +------------+-------------------+---------+---------+ | | absent | source | target | | absent +-------------------+---------+---------+ | | present | link | link | +------------+-------------------+---------+---------+ | | absent | peer | target | | present +-------------------+---------+---------+ | | present | peer | link | +------------+-------------------+---------+---------+ When IFLA_LINK_NETNSID is present, the device is created in link netns first and then moved to target netns. This has some side effects, including extra ifindex allocation, ifname validation and link events. These could be avoided if we create it in target netns from the beginning. On the other hand, the meaning of src_net parameter is ambiguous. It varies depending on how parameters are passed. It is the effective link (or peer netns) by design, but some drivers ignore it and use dev_net instead. To provide more netns context for drivers, this patch packs existing newlink() parameters, along with the source netns, link netns and peer netns, into a struct. The old "src_net" is renamed to "net" to avoid confusion with real source netns, and will be deprecated later. The use of src_net are converted to params->net trivially. Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima Link: https://patch.msgid.link/20250219125039.18024-3-shaw.leon@gmail.com Signed-off-by: Jakub Kicinski --- drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 7 ++++-- drivers/net/amt.c | 7 ++++-- drivers/net/bareudp.c | 7 ++++-- drivers/net/bonding/bond_netlink.c | 6 +++-- drivers/net/can/dev/netlink.c | 4 +-- drivers/net/can/vxcan.c | 7 ++++-- .../ethernet/qualcomm/rmnet/rmnet_config.c | 7 ++++-- drivers/net/geneve.c | 7 ++++-- drivers/net/gtp.c | 6 +++-- drivers/net/ipvlan/ipvlan.h | 3 +-- drivers/net/ipvlan/ipvlan_main.c | 6 +++-- drivers/net/ipvlan/ipvtap.c | 6 ++--- drivers/net/macsec.c | 7 ++++-- drivers/net/macvlan.c | 19 ++++++++------ drivers/net/macvtap.c | 6 ++--- drivers/net/netkit.c | 14 +++++++---- drivers/net/pfcp.c | 5 ++-- drivers/net/ppp/ppp_generic.c | 7 ++++-- drivers/net/team/team_core.c | 6 +++-- drivers/net/veth.c | 7 ++++-- drivers/net/vrf.c | 5 ++-- drivers/net/vxlan/vxlan_core.c | 7 ++++-- drivers/net/wireguard/device.c | 5 ++-- drivers/net/wireless/virtual/virt_wifi.c | 6 +++-- drivers/net/wwan/wwan_core.c | 16 +++++++++--- include/linux/if_macvlan.h | 6 +++-- include/net/rtnetlink.h | 25 ++++++++++++++++--- net/8021q/vlan_netlink.c | 7 ++++-- net/batman-adv/soft-interface.c | 9 +++---- net/bridge/br_netlink.c | 6 +++-- net/caif/chnl_net.c | 5 ++-- net/core/rtnetlink.c | 15 ++++++++--- net/hsr/hsr_netlink.c | 6 +++-- net/ieee802154/6lowpan/core.c | 5 ++-- net/ipv4/ip_gre.c | 16 ++++++++---- net/ipv4/ip_vti.c | 6 +++-- net/ipv4/ipip.c | 6 +++-- net/ipv6/ip6_gre.c | 14 ++++++++--- net/ipv6/ip6_tunnel.c | 6 +++-- net/ipv6/ip6_vti.c | 5 ++-- net/ipv6/sit.c | 6 +++-- net/xfrm/xfrm_interface_core.c | 7 +++--- 42 files changed, 223 insertions(+), 110 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c index 9ad8d9856275..16cb8ced9f35 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c @@ -97,10 +97,13 @@ out_err: return ret; } -static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipoib_new_child_link(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *pdev; struct ipoib_dev_priv *ppriv; u16 child_pkey; diff --git a/drivers/net/amt.c b/drivers/net/amt.c index 98c6205ed19f..96b7ec9a2c13 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -3161,11 +3161,14 @@ static int amt_validate(struct nlattr *tb[], struct nlattr *data[], return 0; } -static int amt_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int amt_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct amt_dev *amt = netdev_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; int err = -EINVAL; amt->net = net; diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c index 70814303aab8..fc21dcfb4848 100644 --- a/drivers/net/bareudp.c +++ b/drivers/net/bareudp.c @@ -698,10 +698,13 @@ static void bareudp_dellink(struct net_device *dev, struct list_head *head) unregister_netdevice_queue(dev, head); } -static int bareudp_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int bareudp_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; struct bareudp_conf conf; int err; diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 2a6a424806aa..ac5e402c34bc 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -564,10 +564,12 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[], return 0; } -static int bond_newlink(struct net *src_net, struct net_device *bond_dev, - struct nlattr *tb[], struct nlattr *data[], +static int bond_newlink(struct net_device *bond_dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; int err; err = bond_changelink(bond_dev, tb, data, extack); diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index 01aacdcda260..f1db9b7ffd4d 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -624,8 +624,8 @@ nla_put_failure: return -EMSGSIZE; } -static int can_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int can_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { return -EOPNOTSUPP; diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index ca8811941085..6f8ebb1cfd7b 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -172,10 +172,13 @@ static void vxcan_setup(struct net_device *dev) /* forward declaration for rtnl_create_link() */ static struct rtnl_link_ops vxcan_link_ops; -static int vxcan_newlink(struct net *peer_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vxcan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *peer_net = params->net; + struct nlattr **tb = params->tb; struct vxcan_priv *priv; struct net_device *peer; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c index f3bea196a8f9..8151e91395e2 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c @@ -117,11 +117,14 @@ static void rmnet_unregister_bridge(struct rmnet_port *port) rmnet_unregister_real_device(bridge_dev); } -static int rmnet_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int rmnet_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { u32 data_format = RMNET_FLAGS_INGRESS_DEAGGREGATION; + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *real_dev; int mode = RMNET_EPMODE_VND; struct rmnet_endpoint *ep; diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index dbb3960126ee..d6e8b2521052 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1614,10 +1614,13 @@ static void geneve_link_config(struct net_device *dev, geneve_change_mtu(dev, ldev_mtu - info->options_len); } -static int geneve_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int geneve_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; struct geneve_config cfg = { .df = GENEVE_DF_UNSET, .use_udp6_rx_checksums = false, diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index b7b46c5e6399..762514af8b30 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1462,10 +1462,12 @@ static int gtp_create_sockets(struct gtp_dev *gtp, const struct nlattr *nla, #define GTP_TH_MAXLEN (sizeof(struct udphdr) + sizeof(struct gtp0_header)) #define GTP_IPV6_MAXLEN (sizeof(struct ipv6hdr) + GTP_TH_MAXLEN) -static int gtp_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int gtp_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; unsigned int role = GTP_ROLE_GGSN; struct gtp_dev *gtp; struct gtp_net *gn; diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 025e0c19ec25..50de3ee204db 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h @@ -166,8 +166,7 @@ struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h, void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type); void ipvlan_count_rx(const struct ipvl_dev *ipvlan, unsigned int len, bool success, bool mcast); -int ipvlan_link_new(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +int ipvlan_link_new(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack); void ipvlan_link_delete(struct net_device *dev, struct list_head *head); void ipvlan_link_setup(struct net_device *dev); diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index da3a97a65507..19ce19ca7e32 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -532,11 +532,13 @@ err: return ret; } -int ipvlan_link_new(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +int ipvlan_link_new(struct net_device *dev, struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ipvl_dev *ipvlan = netdev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct ipvl_port *port; struct net_device *phy_dev; int err; diff --git a/drivers/net/ipvlan/ipvtap.c b/drivers/net/ipvlan/ipvtap.c index 1afc4c47be73..edd13916831a 100644 --- a/drivers/net/ipvlan/ipvtap.c +++ b/drivers/net/ipvlan/ipvtap.c @@ -73,8 +73,8 @@ static void ipvtap_update_features(struct tap_dev *tap, netdev_update_features(vlan->dev); } -static int ipvtap_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipvtap_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ipvtap_dev *vlantap = netdev_priv(dev); @@ -97,7 +97,7 @@ static int ipvtap_newlink(struct net *src_net, struct net_device *dev, /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ - err = ipvlan_link_new(src_net, dev, tb, data, extack); + err = ipvlan_link_new(dev, params, extack); if (err) { netdev_rx_handler_unregister(dev); return err; diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 1bc1e5993f56..1869b0513f57 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -4141,11 +4141,14 @@ static int macsec_add_dev(struct net_device *dev, sci_t sci, u8 icv_len) static struct lock_class_key macsec_netdev_addr_lock_key; -static int macsec_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int macsec_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct macsec_dev *macsec = macsec_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; + struct net *net = params->net; rx_handler_func_t *rx_handler; u8 icv_len = MACSEC_DEFAULT_ICV_LEN; struct net_device *real_dev; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index fed4fe2a4748..f903b414eaeb 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -1440,16 +1440,19 @@ static int macvlan_changelink_sources(struct macvlan_dev *vlan, u32 mode, return 0; } -int macvlan_common_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +int macvlan_common_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct macvlan_dev *vlan = netdev_priv(dev); - struct macvlan_port *port; + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *lowerdev; - int err; - int macmode; + struct macvlan_port *port; bool create = false; + int macmode; + int err; if (!tb[IFLA_LINK]) return -EINVAL; @@ -1565,11 +1568,11 @@ destroy_macvlan_port: } EXPORT_SYMBOL_GPL(macvlan_common_newlink); -static int macvlan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int macvlan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { - return macvlan_common_newlink(src_net, dev, tb, data, extack); + return macvlan_common_newlink(dev, params, extack); } void macvlan_dellink(struct net_device *dev, struct list_head *head) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 29a5929d48e5..b391a0f740a3 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -77,8 +77,8 @@ static void macvtap_update_features(struct tap_dev *tap, netdev_update_features(vlan->dev); } -static int macvtap_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int macvtap_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct macvtap_dev *vlantap = netdev_priv(dev); @@ -105,7 +105,7 @@ static int macvtap_newlink(struct net *src_net, struct net_device *dev, /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ - err = macvlan_common_newlink(src_net, dev, tb, data, extack); + err = macvlan_common_newlink(dev, params, extack); if (err) { netdev_rx_handler_unregister(dev); return err; diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c index 1e1b00756be7..640a2dbbbd28 100644 --- a/drivers/net/netkit.c +++ b/drivers/net/netkit.c @@ -327,17 +327,20 @@ static int netkit_validate(struct nlattr *tb[], struct nlattr *data[], static struct rtnl_link_ops netkit_link_ops; -static int netkit_new_link(struct net *peer_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int netkit_new_link(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { - struct nlattr *peer_tb[IFLA_MAX + 1], **tbp = tb, *attr; - enum netkit_action policy_prim = NETKIT_PASS; - enum netkit_action policy_peer = NETKIT_PASS; enum netkit_scrub scrub_prim = NETKIT_SCRUB_DEFAULT; enum netkit_scrub scrub_peer = NETKIT_SCRUB_DEFAULT; + struct nlattr *peer_tb[IFLA_MAX + 1], **tbp, *attr; + enum netkit_action policy_prim = NETKIT_PASS; + enum netkit_action policy_peer = NETKIT_PASS; + struct nlattr **data = params->data; + struct net *peer_net = params->net; enum netkit_mode mode = NETKIT_L3; unsigned char ifname_assign_type; + struct nlattr **tb = params->tb; u16 headroom = 0, tailroom = 0; struct ifinfomsg *ifmp = NULL; struct net_device *peer; @@ -345,6 +348,7 @@ static int netkit_new_link(struct net *peer_net, struct net_device *dev, struct netkit *nk; int err; + tbp = tb; if (data) { if (data[IFLA_NETKIT_MODE]) mode = nla_get_u32(data[IFLA_NETKIT_MODE]); diff --git a/drivers/net/pfcp.c b/drivers/net/pfcp.c index 68d0d9e92a22..7b0575940e1d 100644 --- a/drivers/net/pfcp.c +++ b/drivers/net/pfcp.c @@ -184,11 +184,12 @@ static int pfcp_add_sock(struct pfcp_dev *pfcp) return PTR_ERR_OR_ZERO(pfcp->sock); } -static int pfcp_newlink(struct net *net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int pfcp_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct pfcp_dev *pfcp = netdev_priv(dev); + struct net *net = params->net; struct pfcp_net *pn; int err; diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 4583e15ad03a..b3340f8a6149 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -1303,10 +1303,13 @@ static int ppp_nl_validate(struct nlattr *tb[], struct nlattr *data[], return 0; } -static int ppp_nl_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ppp_nl_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct ppp_config conf = { .unit = -1, .ifname_is_set = true, diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index f4019815f473..78edb8186b6d 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -2218,10 +2218,12 @@ static void team_setup(struct net_device *dev) dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; } -static int team_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int team_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **tb = params->tb; + if (tb[IFLA_ADDRESS] == NULL) eth_hw_addr_random(dev); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 01251868a9c2..7dfda89f072f 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1765,10 +1765,13 @@ static int veth_init_queues(struct net_device *dev, struct nlattr *tb[]) return 0; } -static int veth_newlink(struct net *peer_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int veth_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *peer_net = params->net; + struct nlattr **tb = params->tb; int err; struct net_device *peer; struct veth_priv *priv; diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 5f21ce1013c4..849c3ced2690 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1675,11 +1675,12 @@ static void vrf_dellink(struct net_device *dev, struct list_head *head) unregister_netdevice_queue(dev, head); } -static int vrf_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vrf_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct net_vrf *vrf = netdev_priv(dev); + struct nlattr **data = params->data; struct netns_vrf *nn_vrf; bool *add_fib_rules; struct net *net; diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index e2354c02def0..1a1d03abb6b9 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -4400,10 +4400,13 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], return 0; } -static int vxlan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vxlan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct vxlan_config conf; int err; diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index 6cf173a008e7..404cf05bd72b 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -307,11 +307,12 @@ static void wg_setup(struct net_device *dev) wg->dev = dev; } -static int wg_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int wg_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct wg_device *wg = netdev_priv(dev); + struct net *src_net = params->net; int ret = -ENOMEM; rcu_assign_pointer(wg->creating_net, src_net); diff --git a/drivers/net/wireless/virtual/virt_wifi.c b/drivers/net/wireless/virtual/virt_wifi.c index 4ee374080466..26905b2b3ba3 100644 --- a/drivers/net/wireless/virtual/virt_wifi.c +++ b/drivers/net/wireless/virtual/virt_wifi.c @@ -519,11 +519,13 @@ static rx_handler_result_t virt_wifi_rx_handler(struct sk_buff **pskb) } /* Called with rtnl lock held. */ -static int virt_wifi_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int virt_wifi_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct virt_wifi_netdev_priv *priv = netdev_priv(dev); + struct net *src_net = params->net; + struct nlattr **tb = params->tb; int err; if (!tb[IFLA_LINK]) diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c index a51e2755991a..a05c49b4e7f8 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -967,15 +967,18 @@ out: return dev; } -static int wwan_rtnl_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int wwan_rtnl_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct wwan_device *wwandev = wwan_dev_get_by_parent(dev->dev.parent); - u32 link_id = nla_get_u32(data[IFLA_WWAN_LINK_ID]); struct wwan_netdev_priv *priv = netdev_priv(dev); + struct nlattr **data = params->data; + u32 link_id; int ret; + link_id = nla_get_u32(data[IFLA_WWAN_LINK_ID]); + if (IS_ERR(wwandev)) return PTR_ERR(wwandev); @@ -1061,6 +1064,11 @@ static void wwan_create_default_link(struct wwan_device *wwandev, { struct nlattr *tb[IFLA_MAX + 1], *linkinfo[IFLA_INFO_MAX + 1]; struct nlattr *data[IFLA_WWAN_MAX + 1]; + struct rtnl_newlink_params params = { + .net = &init_net, + .tb = tb, + .data = data, + }; struct net_device *dev; struct nlmsghdr *nlh; struct sk_buff *msg; @@ -1105,7 +1113,7 @@ static void wwan_create_default_link(struct wwan_device *wwandev, if (WARN_ON(IS_ERR(dev))) goto unlock; - if (WARN_ON(wwan_rtnl_newlink(&init_net, dev, tb, data, NULL))) { + if (WARN_ON(wwan_rtnl_newlink(dev, ¶ms, NULL))) { free_netdev(dev); goto unlock; } diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 523025106a64..0f7281e3e448 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -59,8 +59,10 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, extern void macvlan_common_setup(struct net_device *dev); -extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +struct rtnl_newlink_params; + +extern int macvlan_common_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack); extern void macvlan_dellink(struct net_device *dev, struct list_head *head); diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index bc0069a8b6ea..563a6a27436c 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -69,6 +69,25 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) return AF_UNSPEC; } +/** + * struct rtnl_newlink_params - parameters of rtnl_link_ops::newlink() + * + * @net: Netns of interest + * @src_net: Source netns of rtnetlink socket + * @link_net: Link netns by IFLA_LINK_NETNSID, NULL if not specified + * @peer_net: Peer netns + * @tb: IFLA_* attributes + * @data: IFLA_INFO_DATA attributes + */ +struct rtnl_newlink_params { + struct net *net; + struct net *src_net; + struct net *link_net; + struct net *peer_net; + struct nlattr **tb; + struct nlattr **data; +}; + /** * struct rtnl_link_ops - rtnetlink link operations * @@ -125,10 +144,8 @@ struct rtnl_link_ops { struct nlattr *data[], struct netlink_ext_ack *extack); - int (*newlink)(struct net *src_net, - struct net_device *dev, - struct nlattr *tb[], - struct nlattr *data[], + int (*newlink)(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack); int (*changelink)(struct net_device *dev, struct nlattr *tb[], diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index 134419667d59..91df0f96e32a 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c @@ -135,11 +135,14 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[], return 0; } -static int vlan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vlan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net_device *real_dev; unsigned int max_mtu; __be16 proto; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 822d788a5f86..d893c8013261 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -1077,19 +1077,18 @@ static int batadv_softif_validate(struct nlattr *tb[], struct nlattr *data[], /** * batadv_softif_newlink() - pre-initialize and register new batadv link - * @src_net: the applicable net namespace * @dev: network device to register - * @tb: IFLA_INFO_DATA netlink attributes - * @data: enum batadv_ifla_attrs attributes + * @params: rtnl newlink parameters * @extack: extended ACK report struct * * Return: 0 if successful or error otherwise. */ -static int batadv_softif_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int batadv_softif_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct batadv_priv *bat_priv = netdev_priv(dev); + struct nlattr **data = params->data; const char *algo_name; int err; diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 3e0f47203f2a..6e337937d0d7 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1553,11 +1553,13 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], return 0; } -static int br_dev_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int br_dev_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct net_bridge *br = netdev_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; int err; err = register_netdevice(dev); diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 94ad09e36df2..fa6a3c2634a8 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -438,10 +438,11 @@ static void caif_netlink_parms(struct nlattr *data[], } } -static int ipcaif_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipcaif_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; int ret; struct chnl_net *caifdev; ASSERT_RTNL(); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 0f3e2c6021de..9ebbde0d131c 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3767,7 +3767,13 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, struct netlink_ext_ack *extack) { unsigned char name_assign_type = NET_NAME_USER; - struct net *net = sock_net(skb->sk); + struct rtnl_newlink_params params = { + .src_net = sock_net(skb->sk), + .link_net = link_net, + .peer_net = peer_net, + .tb = tb, + .data = data, + }; u32 portid = NETLINK_CB(skb).portid; struct net_device *dev; char ifname[IFNAMSIZ]; @@ -3792,13 +3798,14 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm, dev->ifindex = ifm->ifi_index; + params.net = params.src_net; if (link_net) - net = link_net; + params.net = link_net; if (peer_net) - net = peer_net; + params.net = peer_net; if (ops->newlink) - err = ops->newlink(net, dev, tb, data, extack); + err = ops->newlink(dev, ¶ms, extack); else err = register_netdevice(dev); if (err < 0) { diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index b68f2f71d0e1..39add538ba99 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -29,10 +29,12 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = { /* Here, it seems a netdevice has already been allocated for us, and the * hsr_dev_setup routine has been executed. Nice! */ -static int hsr_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int hsr_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct net *src_net = params->net; enum hsr_version proto_version; unsigned char multicast_spec; u8 proto = HSR_PROTOCOL_HSR; diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c index 175efd860f7b..704bf9e3f097 100644 --- a/net/ieee802154/6lowpan/core.c +++ b/net/ieee802154/6lowpan/core.c @@ -129,10 +129,11 @@ static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[], return 0; } -static int lowpan_newlink(struct net *src_net, struct net_device *ldev, - struct nlattr *tb[], struct nlattr *data[], +static int lowpan_newlink(struct net_device *ldev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **tb = params->tb; struct net_device *wdev; int ret; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c9f11a046c26..1fe9b13d351c 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1396,10 +1396,12 @@ ipgre_newlink_encap_setup(struct net_device *dev, struct nlattr *data[]) return 0; } -static int ipgre_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipgre_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct ip_tunnel_parm_kern p; __u32 fwmark = 0; int err; @@ -1414,10 +1416,12 @@ static int ipgre_newlink(struct net *src_net, struct net_device *dev, return ip_tunnel_newlink(dev, tb, &p, fwmark); } -static int erspan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int erspan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct ip_tunnel_parm_kern p; __u32 fwmark = 0; int err; @@ -1697,6 +1701,7 @@ static struct rtnl_link_ops erspan_link_ops __read_mostly = { struct net_device *gretap_fb_dev_create(struct net *net, const char *name, u8 name_assign_type) { + struct rtnl_newlink_params params = { .net = net }; struct nlattr *tb[IFLA_MAX + 1]; struct net_device *dev; LIST_HEAD(list_kill); @@ -1704,6 +1709,7 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, int err; memset(&tb, 0, sizeof(tb)); + params.tb = tb; dev = rtnl_create_link(net, name, name_assign_type, &ipgre_tap_ops, tb, NULL); @@ -1714,7 +1720,7 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, t = netdev_priv(dev); t->collect_md = true; - err = ipgre_newlink(net, dev, tb, NULL, NULL); + err = ipgre_newlink(dev, ¶ms, NULL); if (err < 0) { free_netdev(dev); return ERR_PTR(err); diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index f0b4419cef34..b901bee03e6d 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -575,11 +575,13 @@ static void vti_netlink_parms(struct nlattr *data[], *fwmark = nla_get_u32(data[IFLA_VTI_FWMARK]); } -static int vti_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vti_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; struct ip_tunnel_parm_kern parms; + struct nlattr **tb = params->tb; __u32 fwmark = 0; vti_netlink_parms(data, &parms, &fwmark); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index dc0db5895e0e..a8b844bcfc64 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -436,11 +436,13 @@ static void ipip_netlink_parms(struct nlattr *data[], *fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); } -static int ipip_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipip_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ip_tunnel *t = netdev_priv(dev); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct ip_tunnel_encap ipencap; struct ip_tunnel_parm_kern p; __u32 fwmark = 0; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 235808cfec70..863852abe8ea 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -2005,11 +2005,14 @@ out: return err; } -static int ip6gre_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ip6gre_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ip6_tnl *nt = netdev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip6gre_net *ign; int err; @@ -2241,11 +2244,14 @@ static void ip6erspan_tap_setup(struct net_device *dev) netif_keep_dst(dev); } -static int ip6erspan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ip6erspan_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { struct ip6_tnl *nt = netdev_priv(dev); + struct nlattr **data = params->data; + struct net *src_net = params->net; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip6gre_net *ign; int err; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 48fd53b98972..54b843d20870 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -2002,10 +2002,12 @@ static void ip6_tnl_netlink_parms(struct nlattr *data[], parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]); } -static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ip6_tnl_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); struct ip_tunnel_encap ipencap; diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 590737c27537..993f85aeb882 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -997,10 +997,11 @@ static void vti6_netlink_parms(struct nlattr *data[], parms->fwmark = nla_get_u32(data[IFLA_VTI_FWMARK]); } -static int vti6_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int vti6_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; struct net *net = dev_net(dev); struct ip6_tnl *nt; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 39bd8951bfca..e2bd52cabdee 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1550,10 +1550,12 @@ static bool ipip6_netlink_6rd_parms(struct nlattr *data[], } #endif -static int ipip6_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], +static int ipip6_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct net *net = dev_net(dev); struct ip_tunnel *nt; struct ip_tunnel_encap ipencap; diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c index c397eb99d867..5659a6cadd51 100644 --- a/net/xfrm/xfrm_interface_core.c +++ b/net/xfrm/xfrm_interface_core.c @@ -814,10 +814,11 @@ static void xfrmi_netlink_parms(struct nlattr *data[], parms->collect_md = true; } -static int xfrmi_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], - struct netlink_ext_ack *extack) +static int xfrmi_newlink(struct net_device *dev, + struct rtnl_newlink_params *params, + struct netlink_ext_ack *extack) { + struct nlattr **data = params->data; struct net *net = dev_net(dev); struct xfrm_if_parms p = {}; struct xfrm_if *xi; -- 2.50.1