On 10/26/26 7:17 AM, Han Zhou via dev wrote: > A route can describe its next hop with a separate nexthop object (see > 'ip nexthop') that it refers to through a nexthop id carried in the > RTA_NH_ID attribute, instead of encoding the next hop inline. Routing > daemons commonly install routes this way, as it lets many routes share > one next hop and be redirected at once. > > Parse RTA_NH_ID and report it in 'struct route_data'. The kernel reports > the next hop inline as well, so such a route is parsed as any other and > the id is extra information, which users of the library that keep track > of the kernel nexthop table themselves can follow. > > Nothing in the tree resolves the id. ovs-router in particular relies on > the inline next hop, which the kernel leaves out when the > net.ipv4.nexthop_compat_mode sysctl is turned off, so OVS still needs > that sysctl at its default. A route that then carries none of RTA_OIF, > RTA_GATEWAY, RTA_VIA and RTA_MULTIPATH is no longer dropped as > unparseable though: it is reported with an empty nexthop list next to a > non-zero id, which tells a user of the library that it has to resolve the > id itself. > > Assisted-by: Claude Opus 5, Cursor > Signed-off-by: Han Zhou <[email protected]> > --- > v2: Addressed Ilya's comments. > v3: Addressed more comments from Ilya. Also rebased. > > lib/route-table.c | 19 ++++++++++--- > lib/route-table.h | 3 +++ > tests/system-route.at | 52 ++++++++++++++++++++++++++++++++++++ > tests/test-lib-route-table.c | 5 ++-- > 4 files changed, 74 insertions(+), 5 deletions(-) > > diff --git a/lib/route-table.c b/lib/route-table.c > index 2a13a5cc7d93..ac6f8e74e50f 100644 > --- a/lib/route-table.c > +++ b/lib/route-table.c > @@ -45,6 +45,7 @@ > * in case we're building with old headers. (We can't test for it with #ifdef > * because it's an enum.) */ > #define RTA_MARK 16 /* Linux 2.6.36 */ > +#define RTA_NH_ID 30 /* Linux 5.3 */ > #define FRA_SUPPRESS_PREFIXLEN 14 /* Linux 3.12 */ > #define FRA_TABLE 15 /* Linux 2.6.19 */ > #define FRA_PROTOCOL 21 /* Linux 4.17 */ > @@ -468,6 +469,7 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs, > [RTA_PRIORITY] = { .type = NL_A_U32, .optional = true }, > [RTA_VIA] = { .type = NL_A_RTA_VIA, .optional = true }, > [RTA_MULTIPATH] = { .type = NL_A_NESTED, .optional = true }, > + [RTA_NH_ID] = { .type = NL_A_U32, .optional = true }, > }; > > static const struct nl_policy policy6[] = { > @@ -480,6 +482,7 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs, > [RTA_PRIORITY] = { .type = NL_A_U32, .optional = true }, > [RTA_VIA] = { .type = NL_A_RTA_VIA, .optional = true }, > [RTA_MULTIPATH] = { .type = NL_A_NESTED, .optional = true }, > + [RTA_NH_ID] = { .type = NL_A_U32, .optional = true }, > }; > > struct nlattr *attrs[ARRAY_SIZE(policy)]; > @@ -585,6 +588,9 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs, > if (attrs[RTA_PRIORITY]) { > change->rd.rta_priority = nl_attr_get_u32(attrs[RTA_PRIORITY]); > } > + if (attrs[RTA_NH_ID]) { > + change->rd.rta_nhid = nl_attr_get_u32(attrs[RTA_NH_ID]); > + } > if (attrs[RTA_VIA]) { > const struct rtvia *rtvia = nl_attr_get(attrs[RTA_VIA]); > ovs_be32 addr; > @@ -673,9 +679,16 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs, > if (route_type_needs_nexthop(rtm->rtm_type) > && !attrs[RTA_OIF] && !attrs[RTA_GATEWAY] > && !attrs[RTA_VIA] && !attrs[RTA_MULTIPATH]) { > - VLOG_DBG_RL(&rl, "route message needs an RTA_OIF, RTA_GATEWAY, " > - "RTA_VIA or RTA_MULTIPATH attribute"); > - goto error_out; > + if (!attrs[RTA_NH_ID]) { > + VLOG_DBG_RL(&rl, "route message needs an RTA_OIF, " > + "RTA_GATEWAY, RTA_VIA, RTA_MULTIPATH or " > + "RTA_NH_ID attribute"); > + goto error_out; > + } > + > + /* The next hop is in the nexthop object named by RTA_NH_ID, so > + * the entry added at the start of parsing was never filled in. > */ > + route_data_destroy_nexthops__(&change->rd); > } > /* Add any additional RTA attribute processing before RTA_MULTIPATH. > */ > > diff --git a/lib/route-table.h b/lib/route-table.h > index b49fbb14ebe0..45a9a012480a 100644 > --- a/lib/route-table.h > +++ b/lib/route-table.h > @@ -141,6 +141,9 @@ struct route_data { > uint32_t rta_mark; /* 0 if missing. */ > uint32_t rta_table_id; /* 0 if missing. */ > uint32_t rta_priority; /* 0 if missing. */ > + uint32_t rta_nhid; /* Nexthop object id, 0 if missing. > Resolved > + by the user; 'nexthops' is empty unless > the > + kernel also reported it inline. */
nit: need a star on each line. I fixed that and applied that patch. Thanks! Best regards, Ilya Maximets. _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
