* [PATCH net-next v4 0/6] netlink: add lwtunnel encap sub-message support to rt-route
@ 2026-10-08 8:24 Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 1/6] net: lwtunnel: change encap fill order Hangbin Liu
` (5 more replies)
0 siblings, 6 replies; 13+ messages in thread
From: Hangbin Liu @ 2026-10-08 8:24 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S. Miller, Jakub Kicinski,
Paolo Abeni, Simon Horman, Donald Hunter, Eric Dumazet,
Eric Dumazet
Cc: Hangbin Liu, netdev, linux-kernel, bpf, Hangbin Liu
This series adds YNL sub-message support for lwtunnel encap data in
the rt-route netlink family, and describes the tunnel-specific
attribute sets that were previously opaque binary blobs.
The kernel currently emits encap_type after the encap payload nest,
but YNL sub-message parsing needs the selector (encap_type) first to
dispatch on the correct attribute set. Patch 1 reorders the kernel
output, and patch 2 teaches the YNL C code generator to convert enum
selectors to their string form for sub-message dispatch.
Patches 3-6 extend the rt-route YAML spec.
Tested with ynl selftest and checked with following cmds
# modprobe ila
# modprobe xfrm_interface
# ip addr add 10.1.0.1/24 dev lo
# ip link add geneve1 type geneve id 1 remote 10.1.0.2 ttl 64
# ip link set geneve1 up
# ip route add 10.1.0.0/24 dev lo encap mpls 100 via 10.1.0.254
# ip route add 1.1.1.0/24 encap ip id 1 geneve_opts 1:1:1212121234567891,2:2:1212121234567892,3:3:1212121234567893 dst 10.1.0.2 dev geneve1
# ip route add 2001:db8:3::/64 dev lo encap ila 1:2:3:4 csum-mode no-action ident-type luid hook-type output
# ip route add 2001:db8:4::/64 dev lo encap ip6 id 1 dst 2001:db8::5 src 2001:db8::1 hoplimit 64
# ip route add 2001:db8:5::/64 dev lo encap seg6 mode inline segs 2001:db8::1
# ip route add 2001:db8:6::/65 dev lo encap seg6local action End flavors psp,next-csid lblen 32 nflen 16
# ip route add 2001:db8:7::/65 dev lo encap bpf in ob /tmp/kself/net/lib/xdp_dummy.bpf.o sec xdp
# ip route add 2001:db8:8::/64 dev lo encap rpl segs 2001:db8::1
# ip route add 2001:db8:9::/64 encap ioam6 trace prealloc type 0x800000 ns 0 size 4 dev lo
# ip route add 2001:db8:10::/64 dev lo encap xfrm if_id 100
# ip route show
1.1.1.0/24 encap ip id 1 src 0.0.0.0 dst 10.1.0.2 ttl 0 tos 0
geneve_opts 1:1:1212121234567891,2:2:1212121234567892,3:3:1212121234567893 dev geneve1 scope link
10.1.0.0/24 encap mpls 100 via 10.1.0.254 dev lo
# ip -6 route show
2001:db8:3::/64 encap ila 1:2:3:4 csum-mode no-action ident-type luid hook-type output dev lo metric 1024 pref medium
2001:db8:4::/64 encap ip6 id 1 src 2001:db8::1 dst 2001:db8::5 hoplimit 64 tc 0 dev lo metric 1024 pref medium
2001:db8:5::/64 encap seg6 mode inline segs 2 [ 2001:db8::1 :: ] dev lo metric 1024 pref medium
2001:db8:6::/65 encap seg6local action End flavors psp,next-csid lblen 32 nflen 16 dev lo metric 1024 pref medium
2001:db8:7::/65 encap bpf in xdp_dummy.bpf.o:[xdp] dev lo metric 1024 pref medium
2001:db8:8::/64 encap rpl segs 1 [ 2001:db8::1 ] dev lo metric 1024 pref medium
2001:db8:9::/64 encap ioam6 freq 1/1 mode inline trace prealloc type 0x800000 ns 0 size 4 dev lo metric 1024 pref medium
2001:db8:10::/64 encap xfrm if_id 100 dev lo metric 1024 pref medium
# ./tools/net/ynl/pyynl/cli.py --family rt-route --dump getroute > /tmp/route_dump.json
All the result looks good.
Signed-off-by: Hangbin Liu <liuhangbin@kylinos.cn>
---
Changes in v4:
- patch 02: include check `not self.selector.is_external()` for enum selectors,
return error when enum lookup failed. (sashiko, Jakub)
- patch 04: set geneve options to binary due to the different format between
request and dump (sashiko)
- patch 05: set max-len for lwt-bpf-prog-name (sashiko)
- patch 06: fix seg6-local-flv-ops type and name prefix (sashiko)
- Link to v3: https://lore.kernel.org/r/20260930-ynl_rt_encap-v3-0-4106c21b9ee7@kylinos.cn
Changes in v3:
- patch 02: return local_vars and define new helpers is_enum_val and
get_enum_name (Jakub Kicinski)
- patch 03: alphabet order for header files in Makefile (Jakub Kicinski)
set byte-order for ila-attrs. ILA_ATTR_IDENTIFIER is not used, so no
need to set byte-order. (sashiko)
- patch 04: add multi-attr: true for geneve opts (sashiko)
- patch 05: remove lwt-bpf-prog from seg6 local, add a seg6 specific one
in patch 06 (sashiko)
- patch 06: add seg6-local-bpf and seg6-local-flv-ops. Set enum-as-flags
for seg6-local-flv-ops, set max-len for seg6-local-bpf-prog-name (sashiko)
- Link to v2: https://lore.kernel.org/r/20260920-ynl_rt_encap-v2-0-c664a3e726f6@kylinos.cn
Changes in v2:
- Patch 1: Check ops->fill_encap before setting encap_type_attr
- Patch 2: Get string in generated sub-message parser and check it before reference
- Patch 3-4: set byte-orders and max-len
- Patch 5: include lwtunnel.h
- Link to v1: https://lore.kernel.org/r/20260917-ynl_rt_encap-v1-0-fbbe6e680571@kylinos.cn
---
Hangbin Liu (6):
net: lwtunnel: change encap fill order
tools: ynl: convert enum selector to string for sub-message parsing
netlink: specs: rt-route: add lwtunnel encap sub-message support
netlink: specs: rt-route: describe lwtunnel IP options
netlink: specs: rt-route: describe lwt BPF program options
netlink: specs: rt-route: describe seg6-local attrs
Documentation/netlink/specs/rt-route.yaml | 430 +++++++++++++++++++++++++++++-
net/core/lwtunnel.c | 35 +--
tools/net/ynl/Makefile.deps | 9 +-
tools/net/ynl/pyynl/ynl_gen_c.py | 34 ++-
4 files changed, 484 insertions(+), 24 deletions(-)
---
base-commit: 8df0638138d3e0344fd1fb36cf2d1ca1cf5028f0
change-id: 20260908-ynl_rt_encap-3140103b368a
Best regards,
--
Hangbin Liu <liuhangbin@kylinos.cn>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net-next v4 1/6] net: lwtunnel: change encap fill order
2026-10-08 8:24 [PATCH net-next v4 0/6] netlink: add lwtunnel encap sub-message support to rt-route Hangbin Liu
@ 2026-10-08 8:24 ` Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 2/6] tools: ynl: convert enum selector to string for sub-message parsing Hangbin Liu
` (4 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Hangbin Liu @ 2026-10-08 8:24 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S. Miller, Jakub Kicinski,
Paolo Abeni, Simon Horman, Donald Hunter, Eric Dumazet,
Eric Dumazet
Cc: Hangbin Liu, netdev, linux-kernel, bpf, Hangbin Liu
From: Hangbin Liu <liuhangbin@kylinos.cn>
I plan to add lwtunnel encap attributes to the YNL rt-route.yaml spec.
When decoding submessages, YNL expects to read the "selector" (encap-type)
first. Currently lwtunnel writes the encap payload first, which makes YNL
fail to parse the lwtunnel encap message.
Fixing this within YNL itself would be complicated. Instead, reorder the
netlink attributes in the kernel to output encap_type first.
This is a preparatory change for the upcoming rt-route spec updates.
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Hangbin Liu <liuhangbin@kylinos.cn>
---
net/core/lwtunnel.c | 35 ++++++++++++++++++-----------------
1 file changed, 18 insertions(+), 17 deletions(-)
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index b01a395d9a96..8223c44f10c8 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -231,7 +231,7 @@ int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate,
{
const struct lwtunnel_encap_ops *ops;
struct nlattr *nest;
- int ret;
+ int ret = 0;
if (!lwtstate)
return 0;
@@ -240,30 +240,31 @@ int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate,
lwtstate->type > LWTUNNEL_ENCAP_MAX)
return 0;
- nest = nla_nest_start_noflag(skb, encap_attr);
- if (!nest)
- return -EMSGSIZE;
-
- ret = -EOPNOTSUPP;
rcu_read_lock();
+
ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
- if (likely(ops && ops->fill_encap))
- ret = ops->fill_encap(skb, lwtstate);
- rcu_read_unlock();
+ if (unlikely(!ops || !ops->fill_encap))
+ goto unlock_out;
- if (ret)
- goto nla_put_failure;
- nla_nest_end(skb, nest);
ret = nla_put_u16(skb, encap_type_attr, lwtstate->type);
if (ret)
- goto nla_put_failure;
+ goto unlock_out;
- return 0;
+ nest = nla_nest_start_noflag(skb, encap_attr);
+ if (!nest) {
+ ret = -EMSGSIZE;
+ goto unlock_out;
+ }
-nla_put_failure:
- nla_nest_cancel(skb, nest);
+ ret = ops->fill_encap(skb, lwtstate);
+ if (ret)
+ nla_nest_cancel(skb, nest);
+ else
+ nla_nest_end(skb, nest);
- return (ret == -EOPNOTSUPP ? 0 : ret);
+unlock_out:
+ rcu_read_unlock();
+ return ret;
}
EXPORT_SYMBOL_GPL(lwtunnel_fill_encap);
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net-next v4 2/6] tools: ynl: convert enum selector to string for sub-message parsing
2026-10-08 8:24 [PATCH net-next v4 0/6] netlink: add lwtunnel encap sub-message support to rt-route Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 1/6] net: lwtunnel: change encap fill order Hangbin Liu
@ 2026-10-08 8:24 ` Hangbin Liu
2026-10-09 9:06 ` netdev-bot+sashiko
2026-10-08 8:24 ` [PATCH net-next v4 3/6] netlink: specs: rt-route: add lwtunnel encap sub-message support Hangbin Liu
` (3 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Hangbin Liu @ 2026-10-08 8:24 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S. Miller, Jakub Kicinski,
Paolo Abeni, Simon Horman, Donald Hunter, Eric Dumazet,
Eric Dumazet
Cc: Hangbin Liu, netdev, linux-kernel, bpf, Hangbin Liu
From: Hangbin Liu <liuhangbin@kylinos.cn>
YNL sub-message parsing expects a string selector for strcmp(). So for
non-external enum selectors, convert the integer value to its string form
via the family's {enum}_str() helper. This enables correct decoding of
sub-messages keyed by enum values.
After the change, if there is no encap_type (e.g. previous ordering on
older kernels), or a new encap_type is missing from the spec file in
future kernel, the code will report "Sub-message key not set", the same
with string lookup fails. With the subsequent rt-route encap spec update,
the newly generated code will look like:
if (!dst->_present.encap_type)
return ynl_submsg_failed(yarg, "encap", "encap-type");
encap_type_str = rt_route_encap_type_str(dst->encap_type);
if (!encap_type_str)
return ynl_submsg_failed(yarg, "encap", "enum-lookup-failed");
if (rt_route_encap_data_parse(&parg, encap_type_str, attr))
return YNL_PARSE_CB_ERROR;
Signed-off-by: Hangbin Liu <liuhangbin@kylinos.cn>
---
For sashiko:
1. For the extack error-walking path in ynl.c that doesn't handle
enum-keyed selectors. This series doesn't modify ynl.c, it changes
the code generator to emit the _str() conversion in generated parsing
code. The run time error-walking path is a separate concern.
Since rt-route encap is the first enum-keyed sub-message in the YNL
specs, this is a new limitation rather than a regression in existing
functionality. It can be addressed as a follow-up patch to ynl.c.
2. For the selector byte-order issue. This doesn't affect the current
series. The encap-type selector is type: u16 with no byte-order
specified (native order), so the raw value passed to _str() is already
host-order. nftables is in GENS_UNSUP today, so no in-tree generated
family hits this yet. We address this as a follow-up.
---
tools/net/ynl/pyynl/ynl_gen_c.py | 34 +++++++++++++++++++++++++++++-----
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py
index 15c79849c609..4aca51396a9e 100755
--- a/tools/net/ynl/pyynl/ynl_gen_c.py
+++ b/tools/net/ynl/pyynl/ynl_gen_c.py
@@ -951,13 +951,31 @@ class TypeSubMessage(TypeNest):
sel_var = f"_sel_{sel}"
else:
sel_var = f"{var}->{sel}"
- get_lines = [f'if (!{sel_var})',
- f'return ynl_submsg_failed(yarg, "{self.name}", "{selector}");',
- f"if ({self.nested_render_name}_parse(&parg, {sel_var}, attr))",
- "return YNL_PARSE_CB_ERROR;"]
+
+ local_vars = None
+
+ if self.selector.is_enum_val() and not self.selector.is_external():
+ enum = self.family.consts[self.selector.get_enum_name()]
+ pres_var = f"{var}->_present.{sel}"
+ parse_sel = f"{sel}_str"
+ local_vars = [f'const char *{parse_sel};']
+
+ get_lines = [
+ f'if (!{pres_var})',
+ f'return ynl_submsg_failed(yarg, "{self.name}", "{selector}");',
+ f'{parse_sel} = {enum.render_name}_str({sel_var});',
+ f'if (!{parse_sel})',
+ f'return ynl_submsg_failed(yarg, "{self.name}", "enum-lookup-failed");']
+ else:
+ parse_sel = sel_var
+ get_lines = [f'if (!{parse_sel})',
+ f'return ynl_submsg_failed(yarg, "{self.name}", "{selector}");']
+
+ get_lines += [f"if ({self.nested_render_name}_parse(&parg, {parse_sel}, attr))",
+ "return YNL_PARSE_CB_ERROR;"]
init_lines = [f"parg.rsp_policy = &{self.nested_render_name}_nest;",
f"parg.data = &{var}->{self.c_name};"]
- return get_lines, init_lines, None
+ return get_lines, init_lines, local_vars
class Selector:
@@ -979,6 +997,12 @@ class Selector:
def is_external(self):
return self._external
+ def is_enum_val(self):
+ return self.get_enum_name() is not None
+
+ def get_enum_name(self):
+ return self.attr and self.attr.attr.get("enum")
+
class Struct:
def __init__(self, family, space_name, type_list=None, fixed_header=None,
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net-next v4 3/6] netlink: specs: rt-route: add lwtunnel encap sub-message support
2026-10-08 8:24 [PATCH net-next v4 0/6] netlink: add lwtunnel encap sub-message support to rt-route Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 1/6] net: lwtunnel: change encap fill order Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 2/6] tools: ynl: convert enum selector to string for sub-message parsing Hangbin Liu
@ 2026-10-08 8:24 ` Hangbin Liu
2026-10-09 9:06 ` netdev-bot+sashiko
2026-10-08 8:24 ` [PATCH net-next v4 4/6] netlink: specs: rt-route: describe lwtunnel IP options Hangbin Liu
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Hangbin Liu @ 2026-10-08 8:24 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S. Miller, Jakub Kicinski,
Paolo Abeni, Simon Horman, Donald Hunter, Eric Dumazet,
Eric Dumazet
Cc: Hangbin Liu, netdev, linux-kernel, bpf, Hangbin Liu
From: Hangbin Liu <liuhangbin@kylinos.cn>
Define encap-type enum (LWTUNNEL_ENCAP_*) and add encap-data sub-message
keyed by encap-type. Add tunnel attribute sets (mpls, ip, ila, ip6, seg6,
bpf, seg6-local, rpl, ioam6, xfrm). This spec update depends on the kernel
side encap-type/data reorder patch.
Keep some nested option attributes as binary in this patch to simplify
review; they will be converted in follow-up patches.
Also add the Makefile to include uapi headers. Note the lwtunnel.h
is guarded by _UAPI_LWTUNNEL_H_.
Signed-off-by: Hangbin Liu <liuhangbin@kylinos.cn>
---
For sashiko:
This patch is part of the series. When applying it, the prior two patches
(reorder kernel encap filling and enum selector support in YNL) will also
be applied. There is no need to worry about route dumps failing on kernels
lacking the reorder patch.
---
Documentation/netlink/specs/rt-route.yaml | 287 +++++++++++++++++++++++++++++-
tools/net/ynl/Makefile.deps | 9 +-
2 files changed, 294 insertions(+), 2 deletions(-)
diff --git a/Documentation/netlink/specs/rt-route.yaml b/Documentation/netlink/specs/rt-route.yaml
index 253037ea5176..dc842a786794 100644
--- a/Documentation/netlink/specs/rt-route.yaml
+++ b/Documentation/netlink/specs/rt-route.yaml
@@ -99,6 +99,58 @@ definitions:
name: ra-withdrawn
doc: A Router Advertisement withdrew the route with a zero
lifetime.
+ -
+ name: encap-type
+ type: enum
+ name-prefix: lwtunnel-encap-
+ enum-name:
+ entries:
+ - none
+ - mpls
+ - ip
+ - ila
+ - ip6
+ - seg6
+ - bpf
+ - seg6-local
+ - rpl
+ - ioam6
+ - xfrm
+
+sub-messages:
+ -
+ name: encap-data
+ formats:
+ -
+ value: mpls
+ attribute-set: mpls-iptunnel
+ -
+ value: ip
+ attribute-set: lwtunnel-ip
+ -
+ value: ila
+ attribute-set: ila-attrs
+ -
+ value: ip6
+ attribute-set: lwtunnel-ip6
+ -
+ value: seg6
+ attribute-set: seg6-iptunnel
+ -
+ value: bpf
+ attribute-set: lwt-bpf
+ -
+ value: seg6-local
+ attribute-set: seg6-local
+ -
+ value: rpl
+ attribute-set: rpl-iptunnel
+ -
+ value: ioam6
+ attribute-set: ioam6-iptunnel
+ -
+ value: xfrm
+ attribute-set: lwt-xfrm
attribute-sets:
-
@@ -174,9 +226,12 @@ attribute-sets:
-
name: encap-type
type: u16
+ enum: encap-type
-
name: encap
- type: binary # tunnel specific nest
+ type: sub-message
+ sub-message: encap-data
+ selector: encap-type
-
name: expires
type: u32
@@ -277,6 +332,236 @@ attribute-sets:
-
name: fastopen-no-cookie
type: u32
+ -
+ name: mpls-iptunnel
+ name-prefix: mpls-iptunnel-
+ header: linux/mpls_iptunnel.h
+ attributes:
+ -
+ name: dst
+ type: binary
+ -
+ name: ttl
+ type: u8
+ -
+ name: lwtunnel-ip
+ name-prefix: lwtunnel-ip-
+ header: linux/lwtunnel.h
+ attributes:
+ -
+ name: id
+ type: u64
+ byte-order: big-endian
+ -
+ name: dst
+ type: u32
+ byte-order: big-endian
+ display-hint: ipv4
+ -
+ name: src
+ type: u32
+ byte-order: big-endian
+ display-hint: ipv4
+ -
+ name: ttl
+ type: u8
+ -
+ name: tos
+ type: u8
+ -
+ name: flags
+ type: u16
+ byte-order: big-endian
+ -
+ name: pad
+ type: pad
+ -
+ name: opts
+ type: binary # lwtunnel ip nest options
+ -
+ name: ila-attrs
+ name-prefix: ila-attr-
+ header: linux/ila.h
+ attributes:
+ -
+ name: locator
+ type: u64
+ byte-order: big-endian
+ -
+ name: identifier
+ type: u64
+ -
+ name: locator-match
+ type: u64
+ byte-order: big-endian
+ -
+ name: ifindex
+ type: s32
+ -
+ name: dir
+ type: u32
+ -
+ name: pad
+ type: pad
+ -
+ name: csum-mode
+ type: u8
+ -
+ name: ident-type
+ type: u8
+ -
+ name: hook-type
+ type: u8
+ -
+ name: lwtunnel-ip6
+ name-prefix: lwtunnel-ip6-
+ header: linux/lwtunnel.h
+ attributes:
+ -
+ name: id
+ type: u64
+ byte-order: big-endian
+ -
+ name: dst
+ type: binary
+ display-hint: ipv6
+ -
+ name: src
+ type: binary
+ display-hint: ipv6
+ -
+ name: hoplimit
+ type: u8
+ -
+ name: tc
+ type: u8
+ -
+ name: flags
+ type: u16
+ byte-order: big-endian
+ -
+ name: pad
+ type: pad
+ -
+ name: opts
+ type: binary # lwtunnel ip nest options
+ -
+ name: seg6-iptunnel
+ name-prefix: seg6-iptunnel-
+ header: linux/seg6_iptunnel.h
+ attributes:
+ -
+ name: srh
+ type: binary
+ -
+ name: src
+ type: binary
+ display-hint: ipv6
+ -
+ name: table
+ type: u32
+ -
+ name: lwt-bpf
+ name-prefix: lwt-bpf-
+ header: linux/lwtunnel.h
+ attributes:
+ -
+ name: in
+ type: binary # bpf prog
+ -
+ name: out
+ type: binary
+ -
+ name: xmit
+ type: binary
+ -
+ name: xmit-headroom
+ type: u32
+ -
+ name: seg6-local
+ name-prefix: seg6-local-
+ header: linux/seg6_local.h
+ attributes:
+ -
+ name: action
+ type: u32
+ -
+ name: srh
+ type: binary
+ -
+ name: table
+ type: u32
+ -
+ name: nh4
+ type: u32
+ byte-order: big-endian
+ display-hint: ipv4
+ -
+ name: nh6
+ type: binary
+ display-hint: ipv6
+ -
+ name: iif
+ type: u32
+ -
+ name: oif
+ type: u32
+ -
+ name: bpf
+ type: binary
+ -
+ name: vrftable
+ type: u32
+ -
+ name: counters
+ type: binary
+ -
+ name: flavors
+ type: binary
+ -
+ name: rpl-iptunnel
+ name-prefix: rpl-iptunnel-
+ header: linux/rpl_iptunnel.h
+ attributes:
+ -
+ name: srh
+ type: binary
+ -
+ name: ioam6-iptunnel
+ name-prefix: ioam6-iptunnel-
+ header: linux/ioam6_iptunnel.h
+ attributes:
+ -
+ name: mode
+ type: u8
+ -
+ name: dst
+ type: binary
+ display-hint: ipv6
+ -
+ name: trace
+ type: binary
+ -
+ name: freq-k
+ type: u32
+ -
+ name: freq-n
+ type: u32
+ -
+ name: src
+ type: binary
+ display-hint: ipv6
+ -
+ name: lwt-xfrm
+ name-prefix: lwt-xfrm-
+ header: linux/lwtunnel.h
+ attributes:
+ -
+ name: if-id
+ type: u32
+ -
+ name: link
+ type: u32
operations:
enum-model: directional
diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps
index 1e746e25e2bc..3eee34e0efcf 100644
--- a/tools/net/ynl/Makefile.deps
+++ b/tools/net/ynl/Makefile.deps
@@ -45,7 +45,14 @@ CFLAGS_rt-link:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \
$(call get_hdr_inc,_LINUX_IF_LINK_H,if_link.h)
CFLAGS_rt-neigh:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \
$(call get_hdr_inc,__LINUX_NEIGHBOUR_H,neighbour.h)
-CFLAGS_rt-route:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h)
+CFLAGS_rt-route:=$(call get_hdr_inc,_LINUX_ILA_H,ila.h) \
+ $(call get_hdr_inc,_LINUX_IOAM6_IPTUNNEL_H,ioam6_iptunnel.h) \
+ $(call get_hdr_inc,_LINUX_MPLS_IPTUNNEL_H,mpls_iptunnel.h) \
+ $(call get_hdr_inc,_LINUX_RPL_IPTUNNEL_H,rpl_iptunnel.h) \
+ $(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \
+ $(call get_hdr_inc,_LINUX_SEG6_IPTUNNEL_H,seg6_iptunnel.h) \
+ $(call get_hdr_inc,_LINUX_SEG6_LOCAL_H,seg6_local.h) \
+ $(call get_hdr_inc,_LWTUNNEL_H_,lwtunnel.h)
CFLAGS_rt-rule:=$(call get_hdr_inc,__LINUX_FIB_RULES_H,fib_rules.h)
CFLAGS_tc:= $(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \
$(call get_hdr_inc,__LINUX_PKT_SCHED_H,pkt_sched.h) \
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net-next v4 4/6] netlink: specs: rt-route: describe lwtunnel IP options
2026-10-08 8:24 [PATCH net-next v4 0/6] netlink: add lwtunnel encap sub-message support to rt-route Hangbin Liu
` (2 preceding siblings ...)
2026-10-08 8:24 ` [PATCH net-next v4 3/6] netlink: specs: rt-route: add lwtunnel encap sub-message support Hangbin Liu
@ 2026-10-08 8:24 ` Hangbin Liu
2026-10-09 9:07 ` netdev-bot+sashiko
2026-10-08 8:24 ` [PATCH net-next v4 5/6] netlink: specs: rt-route: describe lwt BPF program options Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 6/6] netlink: specs: rt-route: describe seg6-local attrs Hangbin Liu
5 siblings, 1 reply; 13+ messages in thread
From: Hangbin Liu @ 2026-10-08 8:24 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S. Miller, Jakub Kicinski,
Paolo Abeni, Simon Horman, Donald Hunter, Eric Dumazet,
Eric Dumazet
Cc: Hangbin Liu, netdev, linux-kernel, bpf, Hangbin Liu
From: Hangbin Liu <liuhangbin@kylinos.cn>
Replace binary opts in lwtunnel-ip and lwtunnel-ip6 with a nested
lwtunnel-ip-opts set. Add attribute sets for geneve, vxlan, and erspan
IP options to match linux/lwtunnel.h.
Note the kernel encodes LWTUNNEL_IP_OPTS_GENEVE differently for requests
vs dumps. On the request path, the kernel iterates and reads one
CLASS/TYPE/DATA triplet per geneve option. On the dump path, the kernel
opens only one nested geneve option and writes a CLASS/TYPE/DATA triplet
for every option within it. Before there is a proper way to handle it,
I will just omit geneve options and use binary for it.
Signed-off-by: Hangbin Liu <liuhangbin@kylinos.cn>
---
For sashiko:
We don't need to add linux/lwtunnel.h for lwtunnel-ip-opts,
lwtunnel-ip-opt-vxlan and lwtunnel-ip-opt-erspan since the parent
one lwtunnel-ip already include it.
---
Documentation/netlink/specs/rt-route.yaml | 45 +++++++++++++++++++++++++++++--
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/Documentation/netlink/specs/rt-route.yaml b/Documentation/netlink/specs/rt-route.yaml
index dc842a786794..ea6711292c9b 100644
--- a/Documentation/netlink/specs/rt-route.yaml
+++ b/Documentation/netlink/specs/rt-route.yaml
@@ -377,7 +377,8 @@ attribute-sets:
type: pad
-
name: opts
- type: binary # lwtunnel ip nest options
+ type: nest
+ nested-attributes: lwtunnel-ip-opts
-
name: ila-attrs
name-prefix: ila-attr-
@@ -444,7 +445,8 @@ attribute-sets:
type: pad
-
name: opts
- type: binary # lwtunnel ip nest options
+ type: nest
+ nested-attributes: lwtunnel-ip-opts
-
name: seg6-iptunnel
name-prefix: seg6-iptunnel-
@@ -562,6 +564,45 @@ attribute-sets:
-
name: link
type: u32
+ -
+ name: lwtunnel-ip-opts
+ name-prefix: lwtunnel-ip-opts-
+ attributes:
+ -
+ name: geneve
+ type: binary
+ -
+ name: vxlan
+ type: nest
+ nested-attributes: lwtunnel-ip-opt-vxlan
+ -
+ name: erspan
+ type: nest
+ nested-attributes: lwtunnel-ip-opt-erspan
+ -
+ name: lwtunnel-ip-opt-vxlan
+ name-prefix: lwtunnel-ip-opt-vxlan-
+ attributes:
+ -
+ name: gbp
+ type: u32
+ -
+ name: lwtunnel-ip-opt-erspan
+ name-prefix: lwtunnel-ip-opt-erspan-
+ attributes:
+ -
+ name: ver
+ type: u8
+ -
+ name: index
+ type: u32
+ byte-order: big-endian
+ -
+ name: dir
+ type: u8
+ -
+ name: hwid
+ type: u8
operations:
enum-model: directional
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net-next v4 5/6] netlink: specs: rt-route: describe lwt BPF program options
2026-10-08 8:24 [PATCH net-next v4 0/6] netlink: add lwtunnel encap sub-message support to rt-route Hangbin Liu
` (3 preceding siblings ...)
2026-10-08 8:24 ` [PATCH net-next v4 4/6] netlink: specs: rt-route: describe lwtunnel IP options Hangbin Liu
@ 2026-10-08 8:24 ` Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 6/6] netlink: specs: rt-route: describe seg6-local attrs Hangbin Liu
5 siblings, 0 replies; 13+ messages in thread
From: Hangbin Liu @ 2026-10-08 8:24 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S. Miller, Jakub Kicinski,
Paolo Abeni, Simon Horman, Donald Hunter, Eric Dumazet,
Eric Dumazet
Cc: Hangbin Liu, netdev, linux-kernel, bpf, Hangbin Liu
From: Hangbin Liu <liuhangbin@kylinos.cn>
Replace binary BPF attributes with a nested lwt-bpf-prog to support
lwt bpf prog options.
Signed-off-by: Hangbin Liu <liuhangbin@kylinos.cn>
---
Documentation/netlink/specs/rt-route.yaml | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/Documentation/netlink/specs/rt-route.yaml b/Documentation/netlink/specs/rt-route.yaml
index ea6711292c9b..82e59af56ecd 100644
--- a/Documentation/netlink/specs/rt-route.yaml
+++ b/Documentation/netlink/specs/rt-route.yaml
@@ -469,13 +469,16 @@ attribute-sets:
attributes:
-
name: in
- type: binary # bpf prog
+ type: nest
+ nested-attributes: lwt-bpf-prog
-
name: out
- type: binary
+ type: nest
+ nested-attributes: lwt-bpf-prog
-
name: xmit
- type: binary
+ type: nest
+ nested-attributes: lwt-bpf-prog
-
name: xmit-headroom
type: u32
@@ -603,6 +606,18 @@ attribute-sets:
-
name: hwid
type: u8
+ -
+ name: lwt-bpf-prog
+ name-prefix: lwt-bpf-prog-
+ attributes:
+ -
+ name: fd
+ type: u32
+ -
+ name: name
+ type: string
+ checks:
+ max-len: 256
operations:
enum-model: directional
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net-next v4 6/6] netlink: specs: rt-route: describe seg6-local attrs
2026-10-08 8:24 [PATCH net-next v4 0/6] netlink: add lwtunnel encap sub-message support to rt-route Hangbin Liu
` (4 preceding siblings ...)
2026-10-08 8:24 ` [PATCH net-next v4 5/6] netlink: specs: rt-route: describe lwt BPF program options Hangbin Liu
@ 2026-10-08 8:24 ` Hangbin Liu
2026-10-09 9:07 ` netdev-bot+sashiko
5 siblings, 1 reply; 13+ messages in thread
From: Hangbin Liu @ 2026-10-08 8:24 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S. Miller, Jakub Kicinski,
Paolo Abeni, Simon Horman, Donald Hunter, Eric Dumazet,
Eric Dumazet
Cc: Hangbin Liu, netdev, linux-kernel, bpf, Hangbin Liu
From: Hangbin Liu <liuhangbin@kylinos.cn>
Add SEG6 local actions enums, seg6-local-flv-ops flags.
Replace binary bpf/counters/flavors in seg6-local with
nested seg6-local-bpf, seg6-local-cnt and seg6-local-flv.
Signed-off-by: Hangbin Liu <liuhangbin@kylinos.cn>
---
Documentation/netlink/specs/rt-route.yaml | 93 ++++++++++++++++++++++++++++++-
1 file changed, 90 insertions(+), 3 deletions(-)
diff --git a/Documentation/netlink/specs/rt-route.yaml b/Documentation/netlink/specs/rt-route.yaml
index 82e59af56ecd..48d1659f20f3 100644
--- a/Documentation/netlink/specs/rt-route.yaml
+++ b/Documentation/netlink/specs/rt-route.yaml
@@ -116,6 +116,45 @@ definitions:
- rpl
- ioam6
- xfrm
+ -
+ name: seg6-local-actions
+ type: enum
+ name-prefix: seg6-local-action-
+ enum-name:
+ entries:
+ - unspec
+ - end
+ - end-x
+ - end-t
+ - end-dx2
+ - end-dx6
+ - end-dx4
+ - end-dt6
+ - end-dt4
+ - end-b6
+ - end-b6-encap
+ - end-bm
+ - end-s
+ - end-as
+ - end-am
+ - end-bpf
+ - end-dt46
+ -
+ name: seg6-local-flv-ops
+ type: enum
+ name-prefix: seg6-local-flv-op-
+ enum-name:
+ entries:
+ -
+ name: unspec
+ -
+ name: psp
+ -
+ name: usp
+ -
+ name: usd
+ -
+ name: next-csid
sub-messages:
-
@@ -490,6 +529,7 @@ attribute-sets:
-
name: action
type: u32
+ enum: seg6-local-actions
-
name: srh
type: binary
@@ -513,16 +553,19 @@ attribute-sets:
type: u32
-
name: bpf
- type: binary
+ type: nest
+ nested-attributes: seg6-local-bpf
-
name: vrftable
type: u32
-
name: counters
- type: binary
+ type: nest
+ nested-attributes: seg6-local-cnt
-
name: flavors
- type: binary
+ type: nest
+ nested-attributes: seg6-local-flv
-
name: rpl-iptunnel
name-prefix: rpl-iptunnel-
@@ -618,6 +661,50 @@ attribute-sets:
type: string
checks:
max-len: 256
+ -
+ name: seg6-local-bpf
+ name-prefix: seg6-local-bpf-
+ attr-max-name: seg6-local-bpf-prog-max
+ attributes:
+ -
+ name: prog
+ type: u32
+ -
+ name: prog-name
+ type: string
+ checks:
+ max-len: 256
+ -
+ name: seg6-local-cnt
+ name-prefix: seg6-local-cnt-
+ attributes:
+ -
+ name: pad
+ type: pad
+ -
+ name: packets
+ type: u64
+ -
+ name: bytes
+ type: u64
+ -
+ name: errors
+ type: u64
+ -
+ name: seg6-local-flv
+ name-prefix: seg6-local-flv-
+ attributes:
+ -
+ name: operation
+ type: u32
+ enum: seg6-local-flv-ops
+ enum-as-flags: true
+ -
+ name: lcblock-bits
+ type: u8
+ -
+ name: lcnode-fn-bits
+ type: u8
operations:
enum-model: directional
--
2.55.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v4 2/6] tools: ynl: convert enum selector to string for sub-message parsing
2026-10-08 8:24 ` [PATCH net-next v4 2/6] tools: ynl: convert enum selector to string for sub-message parsing Hangbin Liu
@ 2026-10-09 9:06 ` netdev-bot+sashiko
2026-10-09 9:40 ` Hangbin Liu
0 siblings, 1 reply; 13+ messages in thread
From: netdev-bot+sashiko @ 2026-10-09 9:06 UTC (permalink / raw)
To: hangbin.liu
Cc: dsahern, idosch, davem, kuba, pabeni, horms, donald.hunter,
edumazet, netdev, linux-kernel, bpf, liuhangbin
Thank you for your contribution! Sashiko AI review found 4 potential
issue(s) to consider.
Critical: 0 · High: 0 · Medium: 2 · Low: 2
If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).
- [Medium] An unknown enum selector value now aborts the whole message or
dump.
- [Medium] The new enum-to-string conversion ignores byte order.
- [Low] When the enum lookup fails, the error message is misleading.
- [Low] The generator now produces working response parsing for enum-
keyed sub-messages.
--
tools: ynl: convert enum selector to string for sub-message parsing
This patch changes the YNL C code generator for sub-messages keyed by a
non-external enum selector. The integer selector value is converted to a
string with the family's {enum}_str() helper before the sub-message parse
function is called. A missing selector or a failed enum lookup is
reported through ynl_submsg_failed().
> diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py
> index 15c79849c6096..4aca51396a9e2 100755
> --- a/tools/net/ynl/pyynl/ynl_gen_c.py
> +++ b/tools/net/ynl/pyynl/ynl_gen_c.py
> @@ -951,13 +951,31 @@ class TypeSubMessage(TypeNest):
[ ... ]
> + if self.selector.is_enum_val() and not self.selector.is_external():
> + enum = self.family.consts[self.selector.get_enum_name()]
> + pres_var = f"{var}->_present.{sel}"
> + parse_sel = f"{sel}_str"
> + local_vars = [f'const char *{parse_sel};']
> +
> + get_lines = [
> + f'if (!{pres_var})',
> + f'return ynl_submsg_failed(yarg, "{self.name}", "{selector}");',
> + f'{parse_sel} = {enum.render_name}_str({sel_var});',
[Severity: Medium]
Does this handle selectors declared with byte-order: big-endian?
TypeScalar._attr_get() loads the value in {sel_var} with a plain
ynl_attr_get_u32() or ynl_attr_get_u16(), which is a native load. In
TypeScalar.__init__(), byte-order only becomes a C comment through
byte_order_comment. The struct member therefore holds the value in wire
order.
On a little-endian host, a big-endian selector value of 1 arrives as
0x01000000. That fails the range check in the generated {enum}_str():
if (value < 0 || value >= (int)YNL_ARRAY_SIZE(map))
return NULL;
So every sub-message would fail with "enum-lookup-failed".
This combination already exists in-tree. obj-attrs in
Documentation/netlink/specs/nftables.yaml has:
name: type
type: u32
enum: object-type
byte-order: big-endian
...
name: data
type: sub-message
sub-message: obj-data
selector: type
nftables is listed in GENS_UNSUP in tools/net/ynl/generated/Makefile, so
the default build does not generate it.
Before this patch, though, the generator passed the u32 as the
const char *sel argument, which failed at compile time. Now it silently
emits code that cannot decode these sub-messages.
Should the conversion normalize the byte order first, or should the
generator reject such specs?
Because of obj-attrs, the note below the commit message saying rt-route
encap is "the first enum-keyed sub-message in the YNL specs" also does
not seem accurate.
> + f'if (!{parse_sel})',
> + f'return ynl_submsg_failed(yarg, "{self.name}", "enum-lookup-failed");']
[Severity: Medium]
Is it intended that an unknown enum value aborts the whole message or
dump?
ynl_submsg_failed() always returns YNL_PARSE_CB_ERROR.
ynl_dump_trampoline() passes that up, and __ynl_sock_read_msgs() stops
processing.
The string selector path behaves differently. parse_rsp_submsg() emits a
strcmp() chain that ends in return 0. An unknown string key, such as a
new rt-link kind, is skipped and parsing continues.
The enum path is also inconsistent within itself. A value that is in the
enum but has no formats entry falls through the strcmp() chain and
returns 0. A value outside the enum is a hard error.
Take the rt-route spec from this series. If a future kernel adds a new
LWTUNNEL_ENCAP_* type, wouldn't the generated client fail the entire
route dump as soon as one route uses that encap? Leaving the encap
undecoded would match the rest of YNL.
The commit message says:
or a new encap_type is missing from the spec file in future kernel,
the code will report "Sub-message key not set", the same with string
lookup fails.
This doesn't match the string path, which skips unknown keys silently.
Could this skip the sub-message instead, leaving it unset and returning
success, when the enum lookup misses?
[Severity: Low]
Is "enum-lookup-failed" the right value for the selector name argument?
ynl_submsg_failed() always uses this format with YNL_ERROR_SUBMSG_KEY:
"Parsing error: Sub-message key not set (msg %s, key %s)"
The user would see "Sub-message key not set (msg encap, key
enum-lookup-failed)". In this case the key was present but held an
unknown value.
The message also loses the real selector name (encap-type) and does not
report the numeric value that failed. To the caller, this looks the same
as a missing selector.
> + else:
> + parse_sel = sel_var
[ ... ]
> @@ -979,6 +997,12 @@ class Selector:
> def is_external(self):
> return self._external
>
> + def is_enum_val(self):
> + return self.get_enum_name() is not None
> +
> + def get_enum_name(self):
> + return self.attr and self.attr.attr.get("enum")
> +
[Severity: Low]
Response parsing now supports enum selectors. Should the policy side be
addressed, or at least documented? TypeSubMessage._attr_typol() still
says:
# Reverse-parsing of the policy (ynl_err_walk() in ynl.c) does not
# support external selectors. No family uses sub-messages with external
# selector for requests so this is fine for now.
Only TypeString._attr_typol() emits .is_selector = 1.
TypeScalar._attr_typol() emits only .type = YNL_PT_U<N>, so the u16
encap-type selector never gets the flag.
As a result, ynl_err_walk_is_sel() never records the selector. For any
extack offset inside RTA_ENCAP, ynl_err_walk_report_one() then reaches
this code and the attribute path is cut off at .encap:
if (!selector) {
if (*n < str_sz)
*n += snprintf(str, str_sz, "(!selector)");
return 1;
}
For NLMSGERR_ATTR_MISS_NEST inside the encap nest, ynl_ext_ack_check()
leaves nest_pol at the outer route-attrs policy. The missing attribute
would then be named from the wrong policy.
newroute and delroute requests carry encap. The kernel does return
extack offsets inside RTA_ENCAP, for example NL_SET_ERR_MSG_ATTR on
tb[IOAM6_IPTUNNEL_*] in net/ipv6/ioam6_iptunnel.c.
ynl_err_walk_sel_policy() also assumes a string selector
(ynl_attr_get_str() plus strcmp()). It would need enum-to-string support
before is_selector could be set for scalar selectors.
The note below the commit message says this will be a follow-up. Could
the comment in _attr_typol() be updated to mention the enum/integer
selector limitation too?
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261008-ynl_rt_encap-v4-0-4ed2ccf7f949%40kylinos.cn
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v4 3/6] netlink: specs: rt-route: add lwtunnel encap sub-message support
2026-10-08 8:24 ` [PATCH net-next v4 3/6] netlink: specs: rt-route: add lwtunnel encap sub-message support Hangbin Liu
@ 2026-10-09 9:06 ` netdev-bot+sashiko
0 siblings, 0 replies; 13+ messages in thread
From: netdev-bot+sashiko @ 2026-10-09 9:06 UTC (permalink / raw)
To: hangbin.liu
Cc: dsahern, idosch, davem, kuba, pabeni, horms, donald.hunter,
edumazet, netdev, linux-kernel, bpf, liuhangbin
Thank you for your contribution! Sashiko AI review found more severe
issue(s) in other patches of this series. This mail is only an FYI, in case
you want to address the nit picks below when you respin.
Low priority / nit picks for your consideration:
- [Low] rt-route is the first C-generated family whose sub-message
selector is an integer enum (`encap-type`, u16) rather than a string;…
- [Low] Generated C parsing of route messages fails hard when
RTA_ENCAP_TYPE carries a value outside the spec's `encap-type` enum…
--
netlink: specs: rt-route: add lwtunnel encap sub-message support
This commit adds an encap-type enum for the LWTUNNEL_ENCAP_* values. It
turns the rt-route encap attribute into a sub-message keyed on encap-type
and adds attribute sets for each lwtunnel type. It also updates
Makefile.deps to pull in the matching uapi headers.
> diff --git a/Documentation/netlink/specs/rt-route.yaml b/Documentation/netlink/specs/rt-route.yaml
> index 253037ea5176a..dc842a786794a 100644
> --- a/Documentation/netlink/specs/rt-route.yaml
> +++ b/Documentation/netlink/specs/rt-route.yaml
> @@ -99,6 +99,58 @@ definitions:
> name: ra-withdrawn
> doc: A Router Advertisement withdrew the route with a zero
> lifetime.
> + -
> + name: encap-type
> + type: enum
> + name-prefix: lwtunnel-encap-
> + enum-name:
> + entries:
> + - none
> + - mpls
> + - ip
> + - ila
> + - ip6
> + - seg6
> + - bpf
> + - seg6-local
> + - rpl
> + - ioam6
> + - xfrm
[Severity: Low]
What happens in generated C clients when the kernel reports an encap type
that is not in this list?
For an enum selector, TypeSubMessage._attr_get() in ynl_gen_c.py (added
earlier in this series) generates:
encap_type_str = rt_route_encap_type_str(dst->encap_type);
if (!encap_type_str)
return ynl_submsg_failed(yarg, "encap", "enum-lookup-failed");
The generated _str() helper returns NULL for any value past the end of its
string map. lwtunnel_fill_encap() emits RTA_ENCAP_TYPE and then RTA_ENCAP
for any type up to LWTUNNEL_ENCAP_MAX.
Suppose a future kernel adds a new LWTUNNEL_ENCAP_* value. Would a single
route using that type make a C client built from this spec fail the whole
getroute dump, or fail to parse the notification?
String selectors behave differently. parse_rsp_submsg() ends its strcmp()
chain with return 0, so an unknown format is skipped. The generated parsers
also ignore unknown attribute types.
The earlier commit message in the series says this case behaves "the same
with string lookup fails". Is that accurate? Unknown string selector values
are skipped, not reported as errors.
[ ... ]
> @@ -174,9 +226,12 @@ attribute-sets:
> -
> name: encap-type
> type: u16
> + enum: encap-type
> -
> name: encap
> - type: binary # tunnel specific nest
> + type: sub-message
> + sub-message: encap-data
> + selector: encap-type
[Severity: Low]
Can the C library's extack walker resolve error offsets inside RTA_ENCAP
when the selector is a u16?
rt-route looks like the first C-generated family whose sub-message selector
is an integer enum instead of a string. nftables also uses an enum
selector, but it is in GENS_UNSUP.
Selector.__init__ in ynl_gen_c.py sets attr.is_selector = True on
encap-type. However, only TypeString._attr_typol() turns that into the
policy flag:
def _attr_typol(self):
typol = '.type = YNL_PT_NUL_STR, '
if self.is_selector:
typol += '.is_selector = 1, '
return typol
TypeScalar._attr_typol() only emits .type = YNL_PT_U16, so ynl_err_walk()
never records a selector for RTA_ENCAP.
Both newroute and delroute requests list encap-type and encap. If the
kernel returns NLMSGERR_ATTR_OFFS pointing at or inside RTA_ENCAP,
ynl_err_walk_report_one() stops here:
if (policy->table[type].is_submsg) {
if (!selector) {
if (*n < str_sz)
*n += snprintf(str, str_sz, "(!selector)");
return 1;
}
The user would see something like ".encap(!selector)" instead of
".encap(mpls).dst".
Setting .is_selector for scalars would not be enough by itself, because
ynl_err_walk_sel_policy() reads the selector as a string:
sel = ynl_attr_get_str(selector);
for (i = 0; i <= policy->max_attr; i++) {
if (!strcmp(sel, policy->table[i].name))
That cannot match a 2-byte u16 payload.
The series patch "tools: ynl: convert enum selector to string for
sub-message parsing" updated the parse path but not this error-walk path.
Should the error walker also convert enum selectors to strings?
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261008-ynl_rt_encap-v4-0-4ed2ccf7f949%40kylinos.cn
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v4 4/6] netlink: specs: rt-route: describe lwtunnel IP options
2026-10-08 8:24 ` [PATCH net-next v4 4/6] netlink: specs: rt-route: describe lwtunnel IP options Hangbin Liu
@ 2026-10-09 9:07 ` netdev-bot+sashiko
2026-10-09 9:44 ` Hangbin Liu
0 siblings, 1 reply; 13+ messages in thread
From: netdev-bot+sashiko @ 2026-10-09 9:07 UTC (permalink / raw)
To: hangbin.liu
Cc: dsahern, idosch, davem, kuba, pabeni, horms, donald.hunter,
edumazet, netdev, linux-kernel, bpf, liuhangbin
Thank you for your contribution! Sashiko AI review found 3 potential
issue(s) to consider.
Critical: 0 · High: 0 · Medium: 1 · Low: 2
If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).
- [Medium] Under this spec, YNL cannot send a request that sets Geneve
tunnel options; the kernel rejects it.
- [Low] The new `lwtunnel-ip-opts` set declares `geneve` as one `binary`
attribute without `multi-attr: true`.
- [Low] The commit message contradicts itself.
--
netlink: specs: rt-route: describe lwtunnel IP options
This commit changes the binary opts attribute in lwtunnel-ip and
lwtunnel-ip6 into a nest of a new lwtunnel-ip-opts set. It adds vxlan and
erspan option sets. Geneve options stay binary because the kernel uses a
different layout for requests and for dumps.
> Replace binary opts in lwtunnel-ip and lwtunnel-ip6 with a nested
> lwtunnel-ip-opts set. Add attribute sets for geneve, vxlan, and erspan
> IP options to match linux/lwtunnel.h.
[Severity: Low]
The first paragraph says attribute sets are added for geneve, vxlan and
erspan. The diff adds lwtunnel-ip-opts, lwtunnel-ip-opt-vxlan and
lwtunnel-ip-opt-erspan, but no lwtunnel-ip-opt-geneve set, and the
second paragraph says geneve is omitted.
Could the first paragraph say something like "Add attribute sets for
vxlan and erspan IP options; keep geneve as binary (see below)"?
> diff --git a/Documentation/netlink/specs/rt-route.yaml b/Documentation/netlink/specs/rt-route.yaml
> index dc842a786794a..ea6711292c9b6 100644
> --- a/Documentation/netlink/specs/rt-route.yaml
> +++ b/Documentation/netlink/specs/rt-route.yaml
> @@ -377,7 +377,8 @@ attribute-sets:
> type: pad
> -
> name: opts
> - type: binary # lwtunnel ip nest options
> + type: nest
> + nested-attributes: lwtunnel-ip-opts
> -
> name: ila-attrs
> name-prefix: ila-attr-
[ ... ]
> @@ -562,6 +564,45 @@ attribute-sets:
> -
> name: link
> type: u32
> + -
> + name: lwtunnel-ip-opts
> + name-prefix: lwtunnel-ip-opts-
> + attributes:
> + -
> + name: geneve
> + type: binary
[Severity: Medium]
With geneve declared as binary, can YNL still send a route request that
carries Geneve options?
In tools/net/ynl/pyynl/lib/ynl.py, YnlFamily._add_attr() sets
NLA_F_NESTED only in the nest branch. The binary branch copies the payload
and leaves the flag out of the header:
if attr["type"] == 'nest':
nl_type |= Netlink.NLA_F_NESTED
...
elif attr["type"] == 'binary':
...
attr_payload = value
In the kernel, ip_opts_policy types GENEVE as nested:
net/ipv4/ip_tunnel_core.c:
[LWTUNNEL_IP_OPTS_GENEVE] = { .type = NLA_NESTED },
ip_tun_parse_opts() validates the payload in strict mode:
err = nla_validate(nla_data(attr), nla_len(attr), LWTUNNEL_IP_OPTS_MAX,
ip_opts_policy, extack);
NL_VALIDATE_STRICT includes NL_VALIDATE_NESTED, so validate_nla() in
lib/nlattr.c rejects the attribute:
if (validate & NL_VALIDATE_NESTED) {
if ((pt->type == NLA_NESTED || pt->type == NLA_NESTED_ARRAY) &&
!(nla->nla_type & NLA_F_NESTED)) {
ip_tun_parse_opts_geneve() then calls nla_parse_nested(), which does the
same check. So a newroute with encap type ip or ip6 and encap.opts.geneve
set to bytes fails with -EINVAL, even if the bytes hold a well-formed
CLASS/TYPE/DATA triplet.
Before this patch the whole opts attribute was binary. A caller could
pass the raw LWTUNNEL_IP_OPTS payload with NLA_F_NESTED already set on the
inner GENEVE header. The outer attribute is parsed with
nla_parse_nested_deprecated(), so the missing flag there was not checked.
Is this a regression for YNL users who configure Geneve options? Dumps
still decode, because ip_tun_fill_encap_opts_geneve() uses
nla_nest_start_noflag(). Later patches in the series do not change this,
and the final rt-route.yaml still has geneve as binary.
[Severity: Low]
Can this spec describe a request with more than one Geneve option?
On the request path, ip_tun_parse_opts() walks every attribute in the
opts nest. It passes each LWTUNNEL_IP_OPTS_GENEVE to
ip_tun_parse_opts_geneve(), which reads exactly one CLASS/TYPE/DATA
option:
nla_for_each_attr(nla, nla_data(attr), nla_len(attr), rem) {
switch (nla_type(nla)) {
case LWTUNNEL_IP_OPTS_GENEVE:
...
opts_len += opt_len;
if (opts_len > IP_TUNNEL_OPTS_MAX)
So a request sends several Geneve options by repeating the GENEVE
attribute. The uAPI also defines a structured inner set for it, which
geneve_opt_policy enforces:
[LWTUNNEL_IP_OPT_GENEVE_CLASS] = { .type = NLA_U16 },
[LWTUNNEL_IP_OPT_GENEVE_TYPE] = { .type = NLA_U8 },
[LWTUNNEL_IP_OPT_GENEVE_DATA] = { .type = NLA_BINARY, .len = 127 },
The geneve entry here has no multi-attr. YnlFamily._add_attr() only turns
a list value into repeated attributes when attr.is_multi is set, so two
Geneve options on one route cannot be expressed.
Adding multi-attr alone would not make requests work, because of the
NLA_F_NESTED problem above. Nothing later in the series changes this.
> + -
> + name: vxlan
> + type: nest
> + nested-attributes: lwtunnel-ip-opt-vxlan
[ ... ]
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261008-ynl_rt_encap-v4-0-4ed2ccf7f949%40kylinos.cn
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v4 6/6] netlink: specs: rt-route: describe seg6-local attrs
2026-10-08 8:24 ` [PATCH net-next v4 6/6] netlink: specs: rt-route: describe seg6-local attrs Hangbin Liu
@ 2026-10-09 9:07 ` netdev-bot+sashiko
0 siblings, 0 replies; 13+ messages in thread
From: netdev-bot+sashiko @ 2026-10-09 9:07 UTC (permalink / raw)
To: hangbin.liu
Cc: dsahern, idosch, davem, kuba, pabeni, horms, donald.hunter,
edumazet, netdev, linux-kernel, bpf, liuhangbin
Thank you for your contribution! Sashiko AI review found more severe
issue(s) in other patches of this series. This mail is only an FYI, in case
you want to address the nit picks below when you respin.
Low priority / nit picks for your consideration:
- [Low] The patch adds the `seg6-local-flv-ops` enum to
Documentation/netlink/specs/rt-route.yaml with `unspec` as its first…
--
netlink: specs: rt-route: describe seg6-local attrs
This commit adds two enums to the rt-route spec: the SEG6 local actions and
the seg6-local flavor operations. It also changes the bpf, counters and
flavors attributes in seg6-local from binary to nested attribute sets
(seg6-local-bpf, seg6-local-cnt and seg6-local-flv).
> diff --git a/Documentation/netlink/specs/rt-route.yaml b/Documentation/netlink/specs/rt-route.yaml
> index 82e59af56ecdb..48d1659f20f34 100644
> --- a/Documentation/netlink/specs/rt-route.yaml
> +++ b/Documentation/netlink/specs/rt-route.yaml
> @@ -116,6 +116,45 @@ definitions:
[ ... ]
> + -
> + name: seg6-local-flv-ops
> + type: enum
> + name-prefix: seg6-local-flv-op-
> + enum-name:
> + entries:
> + -
> + name: unspec
> + -
> + name: psp
> + -
> + name: usp
> + -
> + name: usd
> + -
> + name: next-csid
[ ... ]
> @@ -618,6 +661,50 @@ attribute-sets:
[ ... ]
> + -
> + name: seg6-local-flv
> + name-prefix: seg6-local-flv-
> + attributes:
> + -
> + name: operation
> + type: u32
> + enum: seg6-local-flv-ops
> + enum-as-flags: true
[Severity: Low]
With enum-as-flags set, should unspec still be the first entry of
seg6-local-flv-ops?
YNL turns each entry's value into a bit position in this mode:
tools/net/ynl/pyynl/lib/nlspec.py:EnumEntry.user_value() {
if self.enum_set['type'] == 'flags' or as_flags:
return 1 << self.value
}
The flag values come out as unspec=0x1, psp=0x2, usp=0x4, usd=0x8 and
next-csid=0x10.
The psp through next-csid bits line up with the kernel's
SEG6_F_LOCAL_FLV_OP(flvname), which is BIT(SEG6_LOCAL_FLV_OP_##flvname). Bit
0 (UNSPEC), however, is not a real flavor operation. The supported masks in
net/ipv6/seg6_local.c contain only NEXT_CSID and PSP:
#define SEG6_LOCAL_END_FLV_SUPP_OPS (SEG6_F_LOCAL_FLV_NEXT_CSID | \
SEG6_LOCAL_FLV8986_SUPP_OPS)
#define SEG6_LOCAL_END_X_FLV_SUPP_OPS SEG6_F_LOCAL_FLV_NEXT_CSID
parse_nla_flavors() rejects every bit outside these masks:
if (rc < 0 || (fops & ~supp_fops)) {
NL_SET_ERR_MSG(extack, "Unsupported Flavor operation(s)");
return -EOPNOTSUPP;
}
As a result, the spec offers an "unspec" flag that the kernel never reports
in a dump. When it is sent in a request, the kernel always rejects it with
-EOPNOTSUPP.
devlink.yaml's reload-action enum is also used with enum-as-flags, and it
handles this by leaving out unspec and setting value: 1 on its first entry.
Could this spec do the same? Dropping unspec and giving psp value: 1 would
keep every real bit in place.
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261008-ynl_rt_encap-v4-0-4ed2ccf7f949%40kylinos.cn
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v4 2/6] tools: ynl: convert enum selector to string for sub-message parsing
2026-10-09 9:06 ` netdev-bot+sashiko
@ 2026-10-09 9:40 ` Hangbin Liu
0 siblings, 0 replies; 13+ messages in thread
From: Hangbin Liu @ 2026-10-09 9:40 UTC (permalink / raw)
To: netdev-bot+sashiko
Cc: dsahern, idosch, davem, kuba, pabeni, horms, donald.hunter,
edumazet, netdev, linux-kernel, bpf, liuhangbin
On Fri, Oct 09, 2026 at 09:06:58AM +0000, netdev-bot+sashiko@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 4 potential
> issue(s) to consider.
>
> Critical: 0 · High: 0 · Medium: 2 · Low: 2
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [Medium] An unknown enum selector value now aborts the whole message or
> dump.
> - [Medium] The new enum-to-string conversion ignores byte order.
> - [Low] When the enum lookup fails, the error message is misleading.
> - [Low] The generator now produces working response parsing for enum-
> keyed sub-messages.
>
> --
>
> tools: ynl: convert enum selector to string for sub-message parsing
>
> This patch changes the YNL C code generator for sub-messages keyed by a
> non-external enum selector. The integer selector value is converted to a
> string with the family's {enum}_str() helper before the sub-message parse
> function is called. A missing selector or a failed enum lookup is
> reported through ynl_submsg_failed().
>
> > diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py
> > index 15c79849c6096..4aca51396a9e2 100755
> > --- a/tools/net/ynl/pyynl/ynl_gen_c.py
> > +++ b/tools/net/ynl/pyynl/ynl_gen_c.py
> > @@ -951,13 +951,31 @@ class TypeSubMessage(TypeNest):
>
> [ ... ]
>
> > + if self.selector.is_enum_val() and not self.selector.is_external():
> > + enum = self.family.consts[self.selector.get_enum_name()]
> > + pres_var = f"{var}->_present.{sel}"
> > + parse_sel = f"{sel}_str"
> > + local_vars = [f'const char *{parse_sel};']
> > +
> > + get_lines = [
> > + f'if (!{pres_var})',
> > + f'return ynl_submsg_failed(yarg, "{self.name}", "{selector}");',
> > + f'{parse_sel} = {enum.render_name}_str({sel_var});',
>
> [Severity: Medium]
> Does this handle selectors declared with byte-order: big-endian?
This doesn't affect the current series. The encap-type selector is
type: u16 with no byte-order specified (native order), so the raw value
passed to _str() is already host-order. nftables is in GENS_UNSUP today,
so no in-tree generated family hits this yet. We address this as a follow-up.
>
> TypeScalar._attr_get() loads the value in {sel_var} with a plain
> ynl_attr_get_u32() or ynl_attr_get_u16(), which is a native load. In
> TypeScalar.__init__(), byte-order only becomes a C comment through
> byte_order_comment. The struct member therefore holds the value in wire
> order.
>
> On a little-endian host, a big-endian selector value of 1 arrives as
> 0x01000000. That fails the range check in the generated {enum}_str():
>
> if (value < 0 || value >= (int)YNL_ARRAY_SIZE(map))
> return NULL;
>
> So every sub-message would fail with "enum-lookup-failed".
>
> This combination already exists in-tree. obj-attrs in
> Documentation/netlink/specs/nftables.yaml has:
>
> name: type
> type: u32
> enum: object-type
> byte-order: big-endian
> ...
> name: data
> type: sub-message
> sub-message: obj-data
> selector: type
>
> nftables is listed in GENS_UNSUP in tools/net/ynl/generated/Makefile, so
> the default build does not generate it.
>
> Before this patch, though, the generator passed the u32 as the
> const char *sel argument, which failed at compile time. Now it silently
> emits code that cannot decode these sub-messages.
>
> Should the conversion normalize the byte order first, or should the
> generator reject such specs?
>
> Because of obj-attrs, the note below the commit message saying rt-route
> encap is "the first enum-keyed sub-message in the YNL specs" also does
> not seem accurate.
>
> > + f'if (!{parse_sel})',
> > + f'return ynl_submsg_failed(yarg, "{self.name}", "enum-lookup-failed");']
>
> [Severity: Medium]
> Is it intended that an unknown enum value aborts the whole message or
> dump?
Yes, this is intended. The same with string lookup fails.
>
> ynl_submsg_failed() always returns YNL_PARSE_CB_ERROR.
> ynl_dump_trampoline() passes that up, and __ynl_sock_read_msgs() stops
> processing.
>
> The string selector path behaves differently. parse_rsp_submsg() emits a
> strcmp() chain that ends in return 0. An unknown string key, such as a
> new rt-link kind, is skipped and parsing continues.
>
> The enum path is also inconsistent within itself. A value that is in the
> enum but has no formats entry falls through the strcmp() chain and
> returns 0. A value outside the enum is a hard error.
>
> Take the rt-route spec from this series. If a future kernel adds a new
> LWTUNNEL_ENCAP_* type, wouldn't the generated client fail the entire
> route dump as soon as one route uses that encap? Leaving the encap
> undecoded would match the rest of YNL.
>
> The commit message says:
>
> or a new encap_type is missing from the spec file in future kernel,
> the code will report "Sub-message key not set", the same with string
> lookup fails.
>
> This doesn't match the string path, which skips unknown keys silently.
The string patch used to failed like
if (!{sel_var})
return ynl_submsg_failed(yarg, "{self.name}", "{selector}");
>
> Could this skip the sub-message instead, leaving it unset and returning
> success, when the enum lookup misses?
Jakub has suggested to use the current way other than *continue* to skip.
Thanks
Hangbin
>
> [Severity: Low]
> Is "enum-lookup-failed" the right value for the selector name argument?
> ynl_submsg_failed() always uses this format with YNL_ERROR_SUBMSG_KEY:
>
> "Parsing error: Sub-message key not set (msg %s, key %s)"
>
> The user would see "Sub-message key not set (msg encap, key
> enum-lookup-failed)". In this case the key was present but held an
> unknown value.
>
> The message also loses the real selector name (encap-type) and does not
> report the numeric value that failed. To the caller, this looks the same
> as a missing selector.
>
> > + else:
> > + parse_sel = sel_var
>
> [ ... ]
>
> > @@ -979,6 +997,12 @@ class Selector:
> > def is_external(self):
> > return self._external
> >
> > + def is_enum_val(self):
> > + return self.get_enum_name() is not None
> > +
> > + def get_enum_name(self):
> > + return self.attr and self.attr.attr.get("enum")
> > +
>
> [Severity: Low]
> Response parsing now supports enum selectors. Should the policy side be
> addressed, or at least documented? TypeSubMessage._attr_typol() still
> says:
>
> # Reverse-parsing of the policy (ynl_err_walk() in ynl.c) does not
> # support external selectors. No family uses sub-messages with external
> # selector for requests so this is fine for now.
>
> Only TypeString._attr_typol() emits .is_selector = 1.
> TypeScalar._attr_typol() emits only .type = YNL_PT_U<N>, so the u16
> encap-type selector never gets the flag.
>
> As a result, ynl_err_walk_is_sel() never records the selector. For any
> extack offset inside RTA_ENCAP, ynl_err_walk_report_one() then reaches
> this code and the attribute path is cut off at .encap:
>
> if (!selector) {
> if (*n < str_sz)
> *n += snprintf(str, str_sz, "(!selector)");
> return 1;
> }
>
> For NLMSGERR_ATTR_MISS_NEST inside the encap nest, ynl_ext_ack_check()
> leaves nest_pol at the outer route-attrs policy. The missing attribute
> would then be named from the wrong policy.
>
> newroute and delroute requests carry encap. The kernel does return
> extack offsets inside RTA_ENCAP, for example NL_SET_ERR_MSG_ATTR on
> tb[IOAM6_IPTUNNEL_*] in net/ipv6/ioam6_iptunnel.c.
>
> ynl_err_walk_sel_policy() also assumes a string selector
> (ynl_attr_get_str() plus strcmp()). It would need enum-to-string support
> before is_selector could be set for scalar selectors.
>
> The note below the commit message says this will be a follow-up. Could
> the comment in _attr_typol() be updated to mention the enum/integer
> selector limitation too?
>
> --
> Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261008-ynl_rt_encap-v4-0-4ed2ccf7f949%40kylinos.cn
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net-next v4 4/6] netlink: specs: rt-route: describe lwtunnel IP options
2026-10-09 9:07 ` netdev-bot+sashiko
@ 2026-10-09 9:44 ` Hangbin Liu
0 siblings, 0 replies; 13+ messages in thread
From: Hangbin Liu @ 2026-10-09 9:44 UTC (permalink / raw)
To: netdev-bot+sashiko
Cc: dsahern, idosch, davem, kuba, pabeni, horms, donald.hunter,
edumazet, netdev, linux-kernel, bpf, liuhangbin
On Fri, Oct 09, 2026 at 09:07:01AM +0000, netdev-bot+sashiko@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential
> issue(s) to consider.
>
> Critical: 0 · High: 0 · Medium: 1 · Low: 2
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [Medium] Under this spec, YNL cannot send a request that sets Geneve
> tunnel options; the kernel rejects it.
> - [Low] The new `lwtunnel-ip-opts` set declares `geneve` as one `binary`
> attribute without `multi-attr: true`.
> - [Low] The commit message contradicts itself.
>
> --
>
> netlink: specs: rt-route: describe lwtunnel IP options
>
> This commit changes the binary opts attribute in lwtunnel-ip and
> lwtunnel-ip6 into a nest of a new lwtunnel-ip-opts set. It adds vxlan and
> erspan option sets. Geneve options stay binary because the kernel uses a
> different layout for requests and for dumps.
>
> > Replace binary opts in lwtunnel-ip and lwtunnel-ip6 with a nested
> > lwtunnel-ip-opts set. Add attribute sets for geneve, vxlan, and erspan
> > IP options to match linux/lwtunnel.h.
>
> [Severity: Low]
> The first paragraph says attribute sets are added for geneve, vxlan and
> erspan. The diff adds lwtunnel-ip-opts, lwtunnel-ip-opt-vxlan and
> lwtunnel-ip-opt-erspan, but no lwtunnel-ip-opt-geneve set, and the
> second paragraph says geneve is omitted.
I mean add geneve attr. I didn't add lwtunnel-ip-opt-geneve.
>
> Could the first paragraph say something like "Add attribute sets for
> vxlan and erspan IP options; keep geneve as binary (see below)"?
>
> > diff --git a/Documentation/netlink/specs/rt-route.yaml b/Documentation/netlink/specs/rt-route.yaml
> > index dc842a786794a..ea6711292c9b6 100644
> > --- a/Documentation/netlink/specs/rt-route.yaml
> > +++ b/Documentation/netlink/specs/rt-route.yaml
> > @@ -377,7 +377,8 @@ attribute-sets:
> > type: pad
> > -
> > name: opts
> > - type: binary # lwtunnel ip nest options
> > + type: nest
> > + nested-attributes: lwtunnel-ip-opts
> > -
> > name: ila-attrs
> > name-prefix: ila-attr-
>
> [ ... ]
>
> > @@ -562,6 +564,45 @@ attribute-sets:
> > -
> > name: link
> > type: u32
> > + -
> > + name: lwtunnel-ip-opts
> > + name-prefix: lwtunnel-ip-opts-
> > + attributes:
> > + -
> > + name: geneve
> > + type: binary
>
> [Severity: Medium]
> With geneve declared as binary, can YNL still send a route request that
> carries Geneve options?
No, before this patch, the whole encap data is binary. We now support
all the encap types other than geneve, which encodes LWTUNNEL_IP_OPTS_GENEVE
differently for requests and dumps.
Thanks
Hangbin
>
> In tools/net/ynl/pyynl/lib/ynl.py, YnlFamily._add_attr() sets
> NLA_F_NESTED only in the nest branch. The binary branch copies the payload
> and leaves the flag out of the header:
>
> if attr["type"] == 'nest':
> nl_type |= Netlink.NLA_F_NESTED
> ...
> elif attr["type"] == 'binary':
> ...
> attr_payload = value
>
> In the kernel, ip_opts_policy types GENEVE as nested:
>
> net/ipv4/ip_tunnel_core.c:
> [LWTUNNEL_IP_OPTS_GENEVE] = { .type = NLA_NESTED },
>
> ip_tun_parse_opts() validates the payload in strict mode:
>
> err = nla_validate(nla_data(attr), nla_len(attr), LWTUNNEL_IP_OPTS_MAX,
> ip_opts_policy, extack);
>
> NL_VALIDATE_STRICT includes NL_VALIDATE_NESTED, so validate_nla() in
> lib/nlattr.c rejects the attribute:
>
> if (validate & NL_VALIDATE_NESTED) {
> if ((pt->type == NLA_NESTED || pt->type == NLA_NESTED_ARRAY) &&
> !(nla->nla_type & NLA_F_NESTED)) {
>
> ip_tun_parse_opts_geneve() then calls nla_parse_nested(), which does the
> same check. So a newroute with encap type ip or ip6 and encap.opts.geneve
> set to bytes fails with -EINVAL, even if the bytes hold a well-formed
> CLASS/TYPE/DATA triplet.
>
> Before this patch the whole opts attribute was binary. A caller could
> pass the raw LWTUNNEL_IP_OPTS payload with NLA_F_NESTED already set on the
> inner GENEVE header. The outer attribute is parsed with
> nla_parse_nested_deprecated(), so the missing flag there was not checked.
>
> Is this a regression for YNL users who configure Geneve options? Dumps
> still decode, because ip_tun_fill_encap_opts_geneve() uses
> nla_nest_start_noflag(). Later patches in the series do not change this,
> and the final rt-route.yaml still has geneve as binary.
>
> [Severity: Low]
> Can this spec describe a request with more than one Geneve option?
>
> On the request path, ip_tun_parse_opts() walks every attribute in the
> opts nest. It passes each LWTUNNEL_IP_OPTS_GENEVE to
> ip_tun_parse_opts_geneve(), which reads exactly one CLASS/TYPE/DATA
> option:
>
> nla_for_each_attr(nla, nla_data(attr), nla_len(attr), rem) {
> switch (nla_type(nla)) {
> case LWTUNNEL_IP_OPTS_GENEVE:
> ...
> opts_len += opt_len;
> if (opts_len > IP_TUNNEL_OPTS_MAX)
>
> So a request sends several Geneve options by repeating the GENEVE
> attribute. The uAPI also defines a structured inner set for it, which
> geneve_opt_policy enforces:
>
> [LWTUNNEL_IP_OPT_GENEVE_CLASS] = { .type = NLA_U16 },
> [LWTUNNEL_IP_OPT_GENEVE_TYPE] = { .type = NLA_U8 },
> [LWTUNNEL_IP_OPT_GENEVE_DATA] = { .type = NLA_BINARY, .len = 127 },
>
> The geneve entry here has no multi-attr. YnlFamily._add_attr() only turns
> a list value into repeated attributes when attr.is_multi is set, so two
> Geneve options on one route cannot be expressed.
>
> Adding multi-attr alone would not make requests work, because of the
> NLA_F_NESTED problem above. Nothing later in the series changes this.
>
> > + -
> > + name: vxlan
> > + type: nest
> > + nested-attributes: lwtunnel-ip-opt-vxlan
>
> [ ... ]
>
> --
> Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261008-ynl_rt_encap-v4-0-4ed2ccf7f949%40kylinos.cn
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-10-09 9:45 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-08 8:24 [PATCH net-next v4 0/6] netlink: add lwtunnel encap sub-message support to rt-route Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 1/6] net: lwtunnel: change encap fill order Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 2/6] tools: ynl: convert enum selector to string for sub-message parsing Hangbin Liu
2026-10-09 9:06 ` netdev-bot+sashiko
2026-10-09 9:40 ` Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 3/6] netlink: specs: rt-route: add lwtunnel encap sub-message support Hangbin Liu
2026-10-09 9:06 ` netdev-bot+sashiko
2026-10-08 8:24 ` [PATCH net-next v4 4/6] netlink: specs: rt-route: describe lwtunnel IP options Hangbin Liu
2026-10-09 9:07 ` netdev-bot+sashiko
2026-10-09 9:44 ` Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 5/6] netlink: specs: rt-route: describe lwt BPF program options Hangbin Liu
2026-10-08 8:24 ` [PATCH net-next v4 6/6] netlink: specs: rt-route: describe seg6-local attrs Hangbin Liu
2026-10-09 9:07 ` netdev-bot+sashiko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®