mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
Merge branch 'gtp-ynl-spec-for-the-gtp-netlink-family-two-fixes-and-a-selftest'
Anil Kaushik says: ==================== gtp: ynl spec for the GTP netlink family, two fixes, and a selftest This adds a ynl spec for the gtp genetlink family, two small driver fixes, and a selftest. Patch 1: the GET and dump replies carried the family id in the command field, so ynl dropped them. Use GTP_CMD_GETPDP instead. Patch 2: new in v7. On the netdev CI debug kernel, the selftest hit an RCU warning: adding a PDP context looks up the device without the RCU read lock. Hold it around the lookup. Patch 3: the spec (NEWPDP/DELPDP/GETPDP/ECHOREQ), no uapi change. Patch 4: a selftest that adds, dumps and deletes PDP contexts. The multicast notifications are not in the spec: they reuse the request command values, which the ynl C generator can't express with the current uapi header. v6: https://lore.kernel.org/netdev/20261013031000.528393-1-anilkaushikwireless@gmail.com/ v5: https://lore.kernel.org/netdev/20261012024800.400616-1-anilkaushikwireless@gmail.com/ v4: https://lore.kernel.org/netdev/20261010105740.223992-1-anilkaushikwireless@gmail.com/ v3: https://lore.kernel.org/netdev/20261009060615.4177402-1-anilkaushikwireless@gmail.com/ v2: https://lore.kernel.org/netdev/20261008181031.4129029-1-anilkaushikwireless@gmail.com/ ==================== Link: https://patch.msgid.link/20261016093225.1036375-1-anilkaushikwireless@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
66123066d8
196
Documentation/netlink/specs/gtp.yaml
Normal file
196
Documentation/netlink/specs/gtp.yaml
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
|
||||
---
|
||||
name: gtp
|
||||
|
||||
protocol: genetlink-legacy
|
||||
|
||||
doc: |
|
||||
GPRS Tunnelling Protocol, user plane (GTP-U).
|
||||
|
||||
The gtp netdevice encapsulates and decapsulates user plane packets in
|
||||
GTP-U tunnels (GTPv0 and GTPv1-U, see 3GPP TS 29.060 and TS 29.281).
|
||||
This family manages the PDP contexts that describe the tunnels and
|
||||
triggers GTP-U echo requests. It is driven by user space control planes
|
||||
such as those built on libgtpnl.
|
||||
|
||||
The kernel registers the family with version 0, which the
|
||||
genetlink-legacy schema cannot express.
|
||||
|
||||
The notifications multicast on the "gtp" group are not described: PDP
|
||||
context additions and deletions, and GTP-U echo responses, reuse the
|
||||
NEWPDP, DELPDP and ECHOREQ command values of the requests.
|
||||
|
||||
kernel-policy: global
|
||||
|
||||
definitions:
|
||||
-
|
||||
type: enum
|
||||
name: version
|
||||
name-prefix: gtp-
|
||||
enum-name: gtp-version
|
||||
header: linux/gtp.h
|
||||
entries: [v0, v1]
|
||||
|
||||
attribute-sets:
|
||||
-
|
||||
name: gtp
|
||||
name-prefix: gtpa-
|
||||
attributes:
|
||||
-
|
||||
name: link
|
||||
type: u32
|
||||
doc: ifindex of the gtp netdevice the context is attached to.
|
||||
-
|
||||
name: version
|
||||
type: u32
|
||||
enum: version
|
||||
doc: GTP version of the context, GTPv0 or GTPv1-U.
|
||||
-
|
||||
name: tid
|
||||
type: u64
|
||||
doc: Tunnel identifier, GTPv0 only.
|
||||
-
|
||||
name: peer-address
|
||||
type: u32
|
||||
byte-order: big-endian
|
||||
display-hint: ipv4
|
||||
doc: |
|
||||
IPv4 address of the remote GSN peer (GGSN or SGSN). Also known
|
||||
as GTPA_SGSN_ADDRESS, kept for legacy user space.
|
||||
-
|
||||
name: ms-address
|
||||
type: u32
|
||||
byte-order: big-endian
|
||||
display-hint: ipv4
|
||||
doc: IPv4 address of the mobile subscriber served by the context.
|
||||
-
|
||||
name: flow
|
||||
type: u16
|
||||
doc: Flow label, GTPv0 only.
|
||||
-
|
||||
name: net-ns-fd
|
||||
type: u32
|
||||
doc: File descriptor of the network namespace of the gtp netdevice.
|
||||
-
|
||||
name: i-tei
|
||||
type: u32
|
||||
doc: Ingress Tunnel Endpoint Identifier, GTPv1-U only.
|
||||
-
|
||||
name: o-tei
|
||||
type: u32
|
||||
doc: Egress Tunnel Endpoint Identifier, GTPv1-U only.
|
||||
-
|
||||
name: pad
|
||||
type: pad
|
||||
-
|
||||
name: peer-addr6
|
||||
type: binary
|
||||
checks:
|
||||
min-len: 16
|
||||
byte-order: big-endian
|
||||
display-hint: ipv6
|
||||
doc: IPv6 address of the remote GSN peer (GGSN or SGSN).
|
||||
-
|
||||
name: ms-addr6
|
||||
type: binary
|
||||
checks:
|
||||
min-len: 16
|
||||
byte-order: big-endian
|
||||
display-hint: ipv6
|
||||
doc: |
|
||||
IPv6 prefix of the mobile subscriber served by the context: a /64
|
||||
prefix, with the lower 64 bits set to zero.
|
||||
-
|
||||
name: family
|
||||
type: u8
|
||||
doc: |
|
||||
Address family (AF_INET or AF_INET6) of ms-address or ms-addr6,
|
||||
AF_INET when absent. The peer address uses the family of the
|
||||
tunnel socket.
|
||||
|
||||
operations:
|
||||
list:
|
||||
-
|
||||
name: newpdp
|
||||
doc: Create or update a PDP context.
|
||||
attribute-set: gtp
|
||||
value: 0
|
||||
dont-validate: [strict, dump]
|
||||
flags: [admin-perm]
|
||||
do:
|
||||
request: &pdp-attrs
|
||||
attributes:
|
||||
- link
|
||||
- version
|
||||
- tid
|
||||
- peer-address
|
||||
- peer-addr6
|
||||
- ms-address
|
||||
- ms-addr6
|
||||
- flow
|
||||
- i-tei
|
||||
- o-tei
|
||||
- family
|
||||
- net-ns-fd
|
||||
-
|
||||
name: delpdp
|
||||
doc: Delete a PDP context.
|
||||
attribute-set: gtp
|
||||
dont-validate: [strict, dump]
|
||||
flags: [admin-perm]
|
||||
do:
|
||||
request: &pdp-find
|
||||
attributes:
|
||||
- link
|
||||
- version
|
||||
- tid
|
||||
- ms-address
|
||||
- ms-addr6
|
||||
- i-tei
|
||||
- family
|
||||
- net-ns-fd
|
||||
-
|
||||
name: getpdp
|
||||
doc: Get or dump one or more PDP contexts.
|
||||
attribute-set: gtp
|
||||
dont-validate: [strict, dump]
|
||||
flags: [admin-perm]
|
||||
do:
|
||||
request: *pdp-find
|
||||
reply: &pdp-reply
|
||||
attributes:
|
||||
- link
|
||||
- version
|
||||
- tid
|
||||
- peer-address
|
||||
- peer-addr6
|
||||
- ms-address
|
||||
- ms-addr6
|
||||
- flow
|
||||
- i-tei
|
||||
- o-tei
|
||||
- family
|
||||
dump:
|
||||
reply: *pdp-reply
|
||||
-
|
||||
name: echoreq
|
||||
doc: |
|
||||
Send a GTP-U echo request to a peer. ms-address is not a mobile
|
||||
subscriber address here, but the local IPv4 address used as source
|
||||
of the request.
|
||||
attribute-set: gtp
|
||||
dont-validate: [strict, dump]
|
||||
flags: [admin-perm]
|
||||
do:
|
||||
request:
|
||||
attributes:
|
||||
- link
|
||||
- version
|
||||
- peer-address
|
||||
- ms-address
|
||||
- net-ns-fd
|
||||
|
||||
mcast-groups:
|
||||
list:
|
||||
-
|
||||
name: gtp
|
||||
|
|
@ -11422,7 +11422,9 @@ M: Harald Welte <laforge@gnumonks.org>
|
|||
L: osmocom-net-gprs@lists.osmocom.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/gtp.git
|
||||
F: Documentation/netlink/specs/gtp.yaml
|
||||
F: drivers/net/gtp.c
|
||||
F: tools/testing/selftests/net/gtp.py
|
||||
|
||||
GUID PARTITION TABLE (GPT)
|
||||
M: Davidlohr Bueso <dave@stgolabs.net>
|
||||
|
|
|
|||
|
|
@ -2050,7 +2050,10 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
rtnl_lock();
|
||||
|
||||
/* the rtnl lock keeps the device alive once found */
|
||||
rcu_read_lock();
|
||||
gtp = gtp_find_dev(sock_net(skb->sk), info->attrs);
|
||||
rcu_read_unlock();
|
||||
if (!gtp) {
|
||||
err = -ENODEV;
|
||||
goto out_unlock;
|
||||
|
|
@ -2279,7 +2282,7 @@ static int gtp_genl_get_pdp(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
|
||||
err = gtp_genl_fill_info(skb2, NETLINK_CB(skb).portid, info->snd_seq,
|
||||
0, info->nlhdr->nlmsg_type, pctx);
|
||||
0, GTP_CMD_GETPDP, pctx);
|
||||
if (err < 0)
|
||||
goto err_unlock_free;
|
||||
|
||||
|
|
@ -2326,7 +2329,7 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb,
|
|||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq,
|
||||
NLM_F_MULTI,
|
||||
cb->nlh->nlmsg_type, pctx)) {
|
||||
GTP_CMD_GETPDP, pctx)) {
|
||||
cb->args[0] = i;
|
||||
cb->args[1] = j;
|
||||
cb->args[2] = (unsigned long)gtp;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ CFLAGS_ethtool:=$(call get_hdr_inc,_LINUX_TYPELIMITS_H,typelimits.h) \
|
|||
$(call get_hdr_inc,_LINUX_ETHTOOL_H,ethtool.h) \
|
||||
$(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_H_,ethtool_netlink.h) \
|
||||
$(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_GENERATED_H,ethtool_netlink_generated.h)
|
||||
CFLAGS_gtp:=$(call get_hdr_inc,_LINUX_GTP_H_,gtp.h)
|
||||
CFLAGS_handshake:=$(call get_hdr_inc,_LINUX_HANDSHAKE_H,handshake.h)
|
||||
CFLAGS_lockd_netlink:=$(call get_hdr_inc,_LINUX_LOCKD_NETLINK_H,lockd_netlink.h)
|
||||
CFLAGS_mptcp_pm:=$(call get_hdr_inc,_LINUX_MPTCP_PM_H,mptcp_pm.h)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ TEST_PROGS := \
|
|||
fq_band_pktlimit.sh \
|
||||
gre_gso.sh \
|
||||
gre_ipv6_lladdr.sh \
|
||||
gtp.py \
|
||||
icmp.sh \
|
||||
icmp_redirect.sh \
|
||||
io_uring_zerocopy_tx.sh \
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ CONFIG_DEBUG_INFO_BTF=y
|
|||
CONFIG_DEBUG_INFO_BTF_MODULES=n
|
||||
CONFIG_DUMMY=y
|
||||
CONFIG_GENEVE=m
|
||||
CONFIG_GTP=m
|
||||
CONFIG_IFB=y
|
||||
CONFIG_INET_DIAG=y
|
||||
CONFIG_INET_ESP=y
|
||||
|
|
|
|||
123
tools/testing/selftests/net/gtp.py
Executable file
123
tools/testing/selftests/net/gtp.py
Executable file
|
|
@ -0,0 +1,123 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
"""Tests for the gtp netlink family."""
|
||||
|
||||
import errno
|
||||
|
||||
from lib.py import ksft_run, ksft_exit
|
||||
from lib.py import ksft_eq, ksft_in, ksft_not_in, ksft_raises
|
||||
from lib.py import KsftSkipEx
|
||||
from lib.py import NetNS, NetNSEnter
|
||||
from lib.py import GtpFamily, NlError
|
||||
from lib.py import CmdExitFailure
|
||||
from lib.py import ip, defer
|
||||
|
||||
_NO_GTP_ERRORS = ("Unknown device type", "Operation not supported",
|
||||
"Garbage instead of arguments")
|
||||
|
||||
|
||||
def _setup(ns):
|
||||
"""Return a gtp family handle, and the ifindex of a new gtp device.
|
||||
|
||||
Create the device first: that loads gtp.ko through its rtnl link
|
||||
alias. ynl resolves the family ids once per process, with a
|
||||
CTRL_CMD_GETFAMILY dump which does not autoload modules, so the
|
||||
family must be registered before the first family handle is created.
|
||||
"""
|
||||
try:
|
||||
ip("link add gtp0 type gtp role ggsn", ns=str(ns))
|
||||
except CmdExitFailure as e:
|
||||
# gtp.ko not available, or iproute2 without gtp support: any other
|
||||
# failure to create the device is a real error.
|
||||
if not any(msg in e.cmd.stderr for msg in _NO_GTP_ERRORS):
|
||||
raise
|
||||
raise KsftSkipEx("no gtp support (CONFIG_GTP, iproute2)") from e
|
||||
defer(ip, "link del gtp0", ns=str(ns))
|
||||
ip("link set gtp0 up", ns=str(ns))
|
||||
link = ip("-d link show gtp0", ns=str(ns), json=True)[0]["ifindex"]
|
||||
|
||||
with NetNSEnter(str(ns)):
|
||||
gtp = GtpFamily()
|
||||
defer(gtp.close)
|
||||
|
||||
return gtp, link
|
||||
|
||||
|
||||
def _contexts(gtp, link):
|
||||
return [c for c in gtp.getpdp({}, dump=True) if c.get("link") == link]
|
||||
|
||||
|
||||
def _iteis(contexts):
|
||||
return [c.get("i-tei") for c in contexts]
|
||||
|
||||
|
||||
def add_del_pdp(ns) -> None:
|
||||
"""Add a PDP context, query it, then delete it by TEI.
|
||||
|
||||
The dump must return the context with the link, TEIDs and addresses
|
||||
it was created with, and it must be gone after the delete. The delete
|
||||
only identifies the context by its TEI, to use the GTPv1 TEI lookup.
|
||||
"""
|
||||
gtp, link = _setup(ns)
|
||||
|
||||
gtp.newpdp({"link": link, "version": 1,
|
||||
"i-tei": 0x100, "o-tei": 0x200,
|
||||
"ms-address": "10.0.0.1", "peer-address": "192.0.2.1"})
|
||||
|
||||
pdp = [c for c in _contexts(gtp, link) if c.get("i-tei") == 0x100]
|
||||
ksft_eq(len(pdp), 1)
|
||||
ksft_eq(pdp[0]["o-tei"], 0x200)
|
||||
ksft_eq(pdp[0]["ms-address"], "10.0.0.1")
|
||||
ksft_eq(pdp[0]["peer-address"], "192.0.2.1")
|
||||
|
||||
gtp.delpdp({"link": link, "version": 1, "i-tei": 0x100})
|
||||
ksft_not_in(0x100, _iteis(_contexts(gtp, link)))
|
||||
|
||||
|
||||
def add_two_pdp(ns) -> None:
|
||||
"""Add two PDP contexts, check both are dumped, delete one by address.
|
||||
|
||||
The delete identifies the context by its MS address, and must leave
|
||||
the other context in place.
|
||||
"""
|
||||
gtp, link = _setup(ns)
|
||||
|
||||
for i_tei, o_tei, ms in ((0x111, 0x211, "10.0.1.1"),
|
||||
(0x112, 0x212, "10.0.1.2")):
|
||||
gtp.newpdp({"link": link, "version": 1,
|
||||
"i-tei": i_tei, "o-tei": o_tei,
|
||||
"ms-address": ms, "peer-address": "192.0.2.5"})
|
||||
|
||||
iteis = _iteis(_contexts(gtp, link))
|
||||
ksft_in(0x111, iteis)
|
||||
ksft_in(0x112, iteis)
|
||||
|
||||
gtp.delpdp({"link": link, "version": 1, "ms-address": "10.0.1.1"})
|
||||
iteis = _iteis(_contexts(gtp, link))
|
||||
ksft_not_in(0x111, iteis)
|
||||
ksft_in(0x112, iteis)
|
||||
|
||||
|
||||
def del_unknown_pdp(ns) -> None:
|
||||
"""Deleting a context that was never added must fail with ENOENT.
|
||||
|
||||
Both lookups are checked: by TEI, and by MS address.
|
||||
"""
|
||||
gtp, link = _setup(ns)
|
||||
|
||||
for attrs in ({"i-tei": 0x999}, {"ms-address": "10.9.9.9"}):
|
||||
with ksft_raises(NlError) as cm:
|
||||
gtp.delpdp({"link": link, "version": 1, **attrs})
|
||||
ksft_eq(cm.exception.error, errno.ENOENT)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Run the PDP context tests in a temporary netns."""
|
||||
with NetNS() as ns:
|
||||
ksft_run([add_del_pdp, add_two_pdp, del_unknown_pdp], args=(ns,))
|
||||
ksft_exit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -18,7 +18,7 @@ from .utils import CmdExitFailure, fd_read_timeout, cmd, bkg, defer, \
|
|||
from .bpf import bpf_map_set, bpf_map_dump, bpf_prog_map_ids
|
||||
from .ynl import NlError, NlctrlFamily, YnlFamily, \
|
||||
EthtoolFamily, NetdevFamily, RtnlFamily, RtnlAddrFamily, RtnlRouteFamily
|
||||
from .ynl import NetshaperFamily, DevlinkFamily, PSPFamily, Netlink
|
||||
from .ynl import NetshaperFamily, DevlinkFamily, GtpFamily, PSPFamily, Netlink
|
||||
|
||||
__all__ = ["KSRC",
|
||||
"KsftFailEx", "KsftSkipEx", "KsftXfailEx", "ksft_pr", "ksft_eq",
|
||||
|
|
@ -32,6 +32,7 @@ __all__ = ["KSRC",
|
|||
"wait_port_listen", "ctl_file_write", "wait_file", "tool", "tc",
|
||||
"bpf_map_set", "bpf_map_dump", "bpf_prog_map_ids",
|
||||
"NetdevSim", "NetdevSimDev",
|
||||
"NetshaperFamily", "DevlinkFamily", "PSPFamily", "NlError",
|
||||
"NetshaperFamily", "DevlinkFamily", "GtpFamily", "PSPFamily",
|
||||
"NlError",
|
||||
"YnlFamily", "EthtoolFamily", "NetdevFamily", "RtnlFamily",
|
||||
"NlctrlFamily", "RtnlAddrFamily", "RtnlRouteFamily", "Netlink"]
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ __all__ = [
|
|||
"NlError", "NlPolicy", "Netlink", "YnlFamily", "SPEC_PATH",
|
||||
"EthtoolFamily", "RtnlFamily", "RtnlAddrFamily", "RtnlRouteFamily",
|
||||
"NetdevFamily", "NetshaperFamily", "NlctrlFamily", "DevlinkFamily",
|
||||
"PSPFamily",
|
||||
"GtpFamily", "PSPFamily",
|
||||
]
|
||||
|
||||
#
|
||||
|
|
@ -85,3 +85,10 @@ class PSPFamily(YnlFamily):
|
|||
def __init__(self, recv_size=0):
|
||||
super().__init__((SPEC_PATH / Path('psp.yaml')).as_posix(),
|
||||
schema='', recv_size=recv_size)
|
||||
|
||||
|
||||
class GtpFamily(YnlFamily):
|
||||
"""YNL family for gtp, see Documentation/netlink/specs/gtp.yaml."""
|
||||
def __init__(self, recv_size=0):
|
||||
super().__init__((SPEC_PATH / Path('gtp.yaml')).as_posix(),
|
||||
schema='', recv_size=recv_size)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user