Open KanjiMonster opened 4 months ago
Grepping through the code, I guess this message comes from rtnl_bridge_notify(), which only sends a minimal message:
static inline size_t bridge_nlmsg_size(void)
{
return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+ nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+ nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
+ nla_total_size(sizeof(u32)) /* IFLA_MASTER */
+ nla_total_size(sizeof(u32)) /* IFLA_MTU */
+ nla_total_size(sizeof(u32)) /* IFLA_LINK */
+ nla_total_size(sizeof(u32)) /* IFLA_OPERSTATE */
+ nla_total_size(sizeof(u8)) /* IFLA_PROTINFO */
+ nla_total_size(sizeof(struct nlattr)) /* IFLA_AF_SPEC */
+ nla_total_size(sizeof(u16)) /* IFLA_BRIDGE_FLAGS */
+ nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_MODE */
}
I guess the proper solution would be to have a oo_update() that can merge this message into the existing object?
Grepping through the code, I guess this message comes from rtnl_bridge_notify(), which only sends a minimal message:
static inline size_t bridge_nlmsg_size(void) { return NLMSG_ALIGN(sizeof(struct ifinfomsg)) + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ + nla_total_size(sizeof(u32)) /* IFLA_MASTER */ + nla_total_size(sizeof(u32)) /* IFLA_MTU */ + nla_total_size(sizeof(u32)) /* IFLA_LINK */ + nla_total_size(sizeof(u32)) /* IFLA_OPERSTATE */ + nla_total_size(sizeof(u8)) /* IFLA_PROTINFO */ + nla_total_size(sizeof(struct nlattr)) /* IFLA_AF_SPEC */ + nla_total_size(sizeof(u16)) /* IFLA_BRIDGE_FLAGS */ + nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_MODE */ }
Scratch that, looking at [ATTR 26] (= IFLA_AF_SPEC)
, it contains a [ATTR 08] (= IFLA_BRIDGE_VLAN_INFO)
.
This implies this comes from br_info_notify()
:
void br_ifinfo_notify(int event, const struct net_bridge *br,
const struct net_bridge_port *port)
{
u32 filter = RTEXT_FILTER_BRVLAN_COMPRESSED;
return br_info_notify(event, br, port, filter);
}
which sends an update with just the VLAN info filled. And no IFLA_LINKINFO
, but ifi_family
set to AF_BRIDGE
.
I guess the proper solution would be to have a oo_update() that can merge this message into the existing object?
That sounds right.
I observed the link cache sometimes returning an incomplete object of family
AF_BRIDGE
, but with no link type set (and thus any rtnl_linkbridge* call triggering an assert).This happens shortly after creation and attaching a port to a bridge.
Running with
NLCB=debug
, the following messages can be seen:complete bridge object ("good" kernel message) => link cache returns a full object
but shortly after that the kernel sends a short message with incomplete bridge state:
Note how
[ATTR 26]
is basically empty, andl_family
is set to 07 /AF_BRIDGE
.While the first message has
l_family
set 00 /AF_UNSPEC
, libnl changes this to 07 /AF_BRIDGE
based on theIFLA_INFO_KIND
"bridge" in[ATTR 18]
.This then causes the previous full bridge object in the link cache to be replaced with an empty one based on the short message.
Not sure what the correct course of action here is. Ignore the short message? Update the bridge object instead of replacing it? If we wouldn't replace the
l_family
based on the value inIFLA_INFO_KIND
, both objects would co-exist and there would be no issue, but likely not doing that would now break the API and users.FWIW, this is libnl 3.8 with kernel 6.6, though the behavior also exists in 6.1.