On Fri, Jan 3, 2025 at 6:02 PM Eelco Chaudron <[email protected]> wrote:
>
> On 18 Dec 2024, at 20:12, Frode Nordahl wrote:
>
> > It is possible to add routes for IPv4 destinations using an IPv6
> > address for next hop.
> >
> > In such configurations the next hop information is provided in the
> > RTA_VIA attribute instead of the RTA_GATEWAY attribute.
>
> Some comments below.
>
> //Eelco
>
> > Signed-off-by: Frode Nordahl <[email protected]>
> > ---
> > lib/netlink.c | 2 ++
> > lib/netlink.h | 1 +
> > lib/route-table.c | 41 +++++++++++++++++++++++++++++++++++++++++
> > tests/system-route.at | 18 ++++++++++++++++++
> > 4 files changed, 62 insertions(+)
> >
> > diff --git a/lib/netlink.c b/lib/netlink.c
> > index 1e8d5a8ec..566c6c694 100644
> > --- a/lib/netlink.c
> > +++ b/lib/netlink.c
> > @@ -819,6 +819,7 @@ min_attr_len(enum nl_attr_type type)
> > case NL_A_IPV6: return 16;
> > case NL_A_NESTED: return 0;
> > case NL_A_LL_ADDR: return 6; /* ETH_ALEN */
> > + case NL_A_RTA_VIA: return 6; /* rtvia header + AF_INET address */
>
> Rather than adding a comment, what about:
>
> case NL_A_RTA_VIA: return sizeof(struct rtvia) + sizeof(struct in_addr);
That does make sense to me, my default behavior is to adhere to
existing style and I take your comment as acceptance of deviating from
it.
> > case N_NL_ATTR_TYPES: default: OVS_NOT_REACHED();
> > }
> > }
> > @@ -840,6 +841,7 @@ max_attr_len(enum nl_attr_type type)
> > case NL_A_IPV6: return 16;
> > case NL_A_NESTED: return SIZE_MAX;
> > case NL_A_LL_ADDR: return 20; /* INFINIBAND_ALEN */
> > + case NL_A_RTA_VIA: return 18; /* rtvia header + AF_INET6 address */
>
> case NL_A_RTA_VIA: return sizeof(struct rtvia) + sizeof(struct in6_addr);
Done.
> > case N_NL_ATTR_TYPES: default: OVS_NOT_REACHED();
> > }
> > }
> > diff --git a/lib/netlink.h b/lib/netlink.h
> > index 008604aa6..d98ef3a98 100644
> > --- a/lib/netlink.h
> > +++ b/lib/netlink.h
> > @@ -152,6 +152,7 @@ enum nl_attr_type
> > NL_A_IPV6,
> > NL_A_NESTED,
> > NL_A_LL_ADDR,
> > + NL_A_RTA_VIA,
> > N_NL_ATTR_TYPES
> > };
> >
> > diff --git a/lib/route-table.c b/lib/route-table.c
> > index b6f0223c0..4e5f89f7e 100644
> > --- a/lib/route-table.c
> > +++ b/lib/route-table.c
> > @@ -51,6 +51,7 @@ COVERAGE_DEFINE(route_table_dump);
> > struct route_data_nexthop {
> > struct ovs_list nexthop_node;
> >
> > + sa_family_t family;
> > struct in6_addr addr;
> > char ifname[IFNAMSIZ]; /* Interface name. */
> > };
> > @@ -277,6 +278,7 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
> > [RTA_PREFSRC] = { .type = NL_A_U32, .optional = true },
> > [RTA_TABLE] = { .type = NL_A_U32, .optional = true },
> > [RTA_PRIORITY] = { .type = NL_A_U32, .optional = true },
> > + [RTA_VIA] = { .type = NL_A_RTA_VIA, .optional = true },
> > };
> >
> > static const struct nl_policy policy6[] = {
> > @@ -287,6 +289,7 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
> > [RTA_PREFSRC] = { .type = NL_A_IPV6, .optional = true },
> > [RTA_TABLE] = { .type = NL_A_U32, .optional = true },
> > [RTA_PRIORITY] = { .type = NL_A_U32, .optional = true },
> > + [RTA_VIA] = { .type = NL_A_RTA_VIA, .optional = true },
> > };
> >
> > struct nlattr *attrs[ARRAY_SIZE(policy)];
> > @@ -311,6 +314,7 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
> > /* ovs_list_init / ovs_list_insert does not allocate any memory */
> > ovs_list_init(&change->rd.nexthops);
> > rdnh = &change->rd._primary_next_hop;
> > + rdnh->family = rtm->rtm_family;
> > ovs_list_insert(&change->rd.nexthops, &rdnh->nexthop_node);
> >
> > change->relevant = true;
> > @@ -385,6 +389,43 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
> > if (attrs[RTA_PRIORITY]) {
> > change->rd.rta_priority = nl_attr_get_u32(attrs[RTA_PRIORITY]);
> > }
>
> Above in 'if (attrs[RTA_GATEWAY])' you also need to set rdnh->family.
rdnh->family is initialized to rtm->rtm_family at the top, and
overridden in case of RTA_VIA.
> In addition, we should add a check to make sure one of the two attributes is
> set, or else rdnh is not initialized.
In any case it will be initialized due to call to memset/xzalloc, and
I guess the extra check does not hurt.
> if (!attrs[RTA_GATEWAY] && !attrs[RTA_VIA]) {
> VLOG_DBG_RL(&rl, "route message needs an RTA_GATEWAY or RTA_VIA
> attribute");
> goto error_out;
> }
We'd have to include a check for RTA_OIF here, as having a route with
only an OIF is valid. Done.
> > + if (attrs[RTA_VIA]) {
> > + const struct rtvia *rtvia = nl_attr_get(attrs[RTA_VIA]);
> > + ovs_be32 addr;
> > +
> > + if (attrs[RTA_GATEWAY]) {
> > + VLOG_DBG_RL(&rl, "route message can not contain both "
> > + "RTA_GATEWAY and RTA_VIA.");
> > + goto error_out;
> > + }
> > +
> > + rdnh->family = rtvia->rtvia_family;
> > + switch (rdnh->family) {
> > + case AF_INET:
> > + if (nl_attr_get_size(attrs[RTA_VIA])
> > + - sizeof rtvia->rtvia_family < sizeof addr) {
>
> This does not look right (same for ipv6). Should this be; - sizeof *rtvia <
> sizeof addr
The reason for the choice is that the rtvia_addr element is just a
placeholder whose real size is different, however the struct might
change in the future, in which case this would become a bug, thanks!
Done.
> > + VLOG_DBG_RL(&rl, "Got short message while parsing
> > RTA_VIA "
> > + "attribute for family AF_INET.");
>
> Log messages in this module do not seem to start with a capital. And in
> general log messages do not end with a dot. So please update all new messages
> you added.
Ack.
> > + goto error_out;
> > + }
> > + memcpy(&addr, rtvia->rtvia_addr, sizeof addr);
> > + in6_addr_set_mapped_ipv4(&rdnh->addr, addr);
> > + break;
> > + case AF_INET6:
> > + if (nl_attr_get_size(attrs[RTA_VIA])
> > + - sizeof rtvia->rtvia_family < sizeof rdnh->addr) {
> > + VLOG_DBG_RL(&rl, "Got short message while parsing
> > RTA_VIA "
> > + "attribute for family AF_INET6.");
> > + goto error_out;
> > + }
> > + memcpy(&rdnh->addr, rtvia->rtvia_addr, sizeof rdnh->addr);
> > + break;
> > + default:
> > + VLOG_DBG_RL(&rl, "No address family in via attribute.");
>
> What about:
>
> VLOG_DBG_RL(&rl, "unsupported address family, %d, in via attribute",
> rdnh->family);
Thanks, done.
> > + goto error_out;
> > + }
> > + }
> > } else {
> > VLOG_DBG_RL(&rl, "received unparseable rtnetlink route message");
> > goto error_out;
> > diff --git a/tests/system-route.at b/tests/system-route.at
> > index c99a2aff5..c9fed2fc6 100644
> > --- a/tests/system-route.at
> > +++ b/tests/system-route.at
> > @@ -65,6 +65,24 @@ Cached: fc00:db8:beef::13/128 dev br0 GW
> > fc00:db8:cafe::1 SRC fc00:db8:cafe::2])
> > OVS_TRAFFIC_VSWITCHD_STOP
> > AT_CLEANUP
> >
> > +AT_SETUP([ovs-route - add system route - ipv4 via ipv6 nexthop])
> > +AT_KEYWORDS([route])
> > +OVS_TRAFFIC_VSWITCHD_START()
> > +AT_CHECK([ovs-vsctl set bridge br0 other-config:hwaddr=00:53:00:00:00:42])
> > +AT_CHECK([ip link set br0 up])
> > +
> > +AT_CHECK([ip addr add 192.168.9.2/24 dev br0], [0], [stdout])
> > +
> > +AT_CHECK([ip route add 192.168.10.12/32 via inet6 fe80::253:ff:fe00:51 dev
> > br0], [0], [stdout])
>
> Maybe try to keep the test lines under 80 chars for new additions. Maybe
> something like:
>
> -AT_CHECK([ip route add 192.168.10.12/32 via inet6 fe80::253:ff:fe00:51 dev
> br0], [0], [stdout])
> +AT_CHECK([ip route add 192.168.10.12/32 via inet6 fe80::253:ff:fe00:51 dev
> br0],
> + [0], [stdout])
Sure, I don't see this mode of formatting anywhere else, but I do like
shorter than 79 length lines too, let's try it!
I chose to split the command in the middle, because we would otherwise
end up > 79 chars anyway.
> AT_CHECK([ovs-appctl revalidator/wait])
>
> -OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E '192.168.10.12/32'
> | sort], [dnl
> +OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | \
> + grep -E '192.168.10.12/32' | sort], [dnl
Done.
--
Frode Nordahl
> > +AT_CHECK([ovs-appctl revalidator/wait])
> > +
> > +OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E
> > '192.168.10.12/32' | sort], [dnl
> > +Cached: 192.168.10.12/32 dev br0 GW fe80::253:ff:fe00:51 SRC
> > fe80::253:ff:fe00:42])
> > +
> > +OVS_TRAFFIC_VSWITCHD_STOP
> > +AT_CLEANUP
> > +
> > dnl Checks that OVS doesn't use routes from non-standard tables.
> > AT_SETUP([ovs-route - route tables])
> > AT_KEYWORDS([route])
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev