Thread (4 messages) 4 messages, 1 author, 3d ago

[PATCH iproute2 0/3] iplink: bond: fix partner LACP state decoding

flat view
WARM3d

From: Dave Seddon <hidden>
Date: 2026-10-11 03:29:10

I have been using an LLM to help port iproute2's netlink handling to
Go. While comparing the two decoders it flagged that ip reads
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE one byte wide. I may well be
missing something; details below in case it is real.

Patch 1 is the one-line fix and stands on its own. Patches 2 and 3 add
a test for it. Please take just patch 1 if you would rather not have
the test.

Issue
- kernel sends u16: nla_put_u16() in bond_fill_slave_info(),
  drivers/net/bonding/bond_netlink.c:79. The field is
  struct port_params.port_state, u16, include/net/bond_3ad.h:205.
- iproute2 reads u8: rta_getattr_u8() in bond_slave_print_opt(),
  ip/iplink_bond_slave.c:148.
- little endian: first byte is the low byte. Output is right because
  the kernel never sets bits above 0xff (the value comes from the
  one-byte LACPDU actor_state, bond_3ad.c:562).
- big endian: first byte is the always-zero high byte. Every bond port
  prints:
    ad_partner_oper_port_state 0 ad_partner_oper_port_state_str <>
  Reproduced on s390x under qemu-user by replaying a generated message.
- regressed in 39ac2d2b802b (v5.6.0). That commit added the _str
  output and copied the actor (u8) block for the partner. The code
  before it used rta_getattr_u16().
- the kernel width is old: u16 in the struct since 1055c9aba3b6
  (2008), exported as u16 since 46ea297ed67c (2015). sysfs and the
  YNL spec agree with it, so the fix belongs in iproute2.
- /proc/net/bonding and sysfs read the struct directly and are fine,
  which is probably why nobody noticed.
- the other bond and bond slave attributes match bond_netlink.c; this
  is the only width mismatch.

Test
- tools/generate_nlmsg writes four RTM_NEWLINK blobs for a bond slave
  with partner state 0x003f, 0x0000, 0x0100 and absent.
- tests/ip/link/show_bond_slave_lacp_state.t decodes them with
  "ip -d monitor file" and checks the printed value. No root needed.
- 0x0100 cannot occur in real LACP. A one-byte reader prints 0 for it
  on little endian and 1 on big endian; only a u16 reader prints 256.
  That makes the bug visible on x86_64 too.

How it was tested
- x86_64, native: new test red with patch 1 reverted (0x0100 prints 0),
  green with it.
- s390x, qemu-user: the blobs were written by an s390x build of
  generate_nlmsg, so they are big endian (partner payload 01 00 for
  0x0100). ip built with and without patch 1:
    without: 0x3f prints "0 <>", 0x0100 prints "1 <active>"
    with:    0x3f prints "63 <active,...>", 0x0100 prints "256"
- results: without patch 1, 1 of 6 checks fails on x86_64 and 2 of 6
  on s390x. With it, all pass on both.
- whole testsuite, rootless, with the series: no change. add_tunnel.t
  and the two netns/set_nsid tests fail (no module load, no
  /var/run/netns), the same as on unpatched e11870d5.
- test_on_not fix checked against matching, mixed, absent and empty
  output, a bad regex and a missing file.
- builds with no warnings. checkpatch --strict is clean apart from the
  exec bit on the new .t, which matches the existing .t files.
- the new .t is shellcheck clean and passes under dash, busybox sh and
  bash --posix, so it does not depend on what /bin/sh points to.

Fix
- patch 1: rta_getattr_u8 -> rta_getattr_u16.
- patch 2: lib/generic.sh test_on_not uses "grep -vqE", which passes
  whenever any line does not match. Fixed so the new test can use it.
  Its one caller, tests/bridge/vlan/show.t, still passes.
- patch 3: the test.

LLM use
- The LLM spotted the mismatch, wrote the patches and drafted this
  letter. Each patch carries Assisted-by: LLM.
- Every result above comes from running the code, natively and under
  qemu-s390x. I have read all of it and can answer for it.

Dave Seddon (3):
  iplink_bond_slave: read ad_partner_oper_port_state as u16
  testsuite: fix test_on_not on multi-line output
  testsuite: add bond slave LACP port state test

 .gitignore                                    |   1 +
 ip/iplink_bond_slave.c                        |   2 +-
 testsuite/Makefile                            |   1 +
 testsuite/lib/generic.sh                      |   5 +-
 .../ip/link/show_bond_slave_lacp_state.t      |  33 ++++++
 testsuite/tools/generate_nlmsg.c              | 103 ++++++++++++++++--
 6 files changed, 133 insertions(+), 12 deletions(-)
 create mode 100755 testsuite/tests/ip/link/show_bond_slave_lacp_state.t

-- 
2.55.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help