fre. 6. des. 2024, 21:27 skrev Frode Nordahl <[email protected]>:
> The route-table code is useful outside the scope of Open vSwitch.
> In a subsequent patch we will expose the route-table data
> structures to allow projects compiling against the private Open
> vSwitch library to consume this data.
>
> Add support for storing and parsing multipath routes.
>
> Note that the internal handling of routes in the ovs-route module
> does currently not support multipath routes, so when presented
> with one the latter occurrence will be stored. This is not a
> regression as these routes were previously not considered at all.
>
> Storing the information in the route-table module data structure
> will allow external to OVS projects make use of this data.
>
> Co-Authored-by: Felix Huettner <[email protected]>
> Signed-off-by: Felix Huettner <[email protected]>
> Signed-off-by: Frode Nordahl <[email protected]>
> ---
> lib/route-table.c | 65 ++++++++++++++++++++++++++++++--------
> tests/system-route.at | 72 +++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 125 insertions(+), 12 deletions(-)
>
> diff --git a/lib/route-table.c b/lib/route-table.c
> index f452d96fc..4f0fed485 100644
> --- a/lib/route-table.c
> +++ b/lib/route-table.c
> @@ -256,6 +256,18 @@ route_table_reset(void)
>
> /* Return RTNLGRP_IPV4_ROUTE or RTNLGRP_IPV6_ROUTE on success, 0 on parse
> * error. */
> +#define ROUTE_TABLE_PARSE_IF_INDEXTONAME(IFINDEX, IFNAME)
> \
> + if (!if_indextoname(IFINDEX, IFNAME)) {
> \
> + int error = errno;
> \
> +
> \
> + VLOG_DBG_RL(&rl, "Could not find interface name[%u]:
> %s", \
> + IFINDEX, ovs_strerror(error));
> \
> + if (error == ENXIO) {
> \
> + change->relevant = false;
> \
> + } else {
> \
> + goto error_out;
> \
> + }
> \
> + }
> static int
> route_table_parse__(struct ofpbuf *buf, size_t ofs,
> const struct nlmsghdr *nlmsg,
> @@ -274,6 +286,7 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
> [RTA_TABLE] = { .type = NL_A_U32, .optional = true },
> [RTA_PRIORITY] = { .type = NL_A_U32, .optional = true },
> [RTA_VIA] = { .type = NL_A_UNSPEC, .optional = true },
> + [RTA_MULTIPATH] = { .type = NL_A_NESTED, .optional = true },
> };
>
> static const struct nl_policy policy6[] = {
> @@ -285,6 +298,7 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
> [RTA_TABLE] = { .type = NL_A_U32, .optional = true },
> [RTA_PRIORITY] = { .type = NL_A_U32, .optional = true },
> [RTA_VIA] = { .type = NL_A_UNSPEC, .optional = true },
> + [RTA_MULTIPATH] = { .type = NL_A_NESTED, .optional = true },
> };
>
> struct nlattr *attrs[ARRAY_SIZE(policy)];
> @@ -330,18 +344,7 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
>
> if (attrs[RTA_OIF]) {
> rta_oif = nl_attr_get_u32(attrs[RTA_OIF]);
> -
> - if (!if_indextoname(rta_oif, rdnh->ifname)) {
> - int error = errno;
> -
> - VLOG_DBG_RL(&rl, "Could not find interface name[%u]: %s",
> - rta_oif, ovs_strerror(error));
> - if (error == ENXIO) {
> - change->relevant = false;
> - } else {
> - goto error_out;
> - }
> - }
> + ROUTE_TABLE_PARSE_IF_INDEXTONAME(rta_oif, rdnh->ifname);
> }
>
> if (attrs[RTA_DST]) {
> @@ -398,6 +401,44 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
> goto error_out;
> }
> }
> + if (attrs[RTA_MULTIPATH]) {
> + const struct nlattr *nla;
> + size_t left;
> +
> + NL_NESTED_FOR_EACH (nla, left, attrs[RTA_MULTIPATH]) {
> + struct route_table_msg mp_change;
> + struct rtnexthop *rtnh;
> + struct ofpbuf mp_buf;
> + int rc;
> +
> + route_data_init(&mp_change.rd);
> + ofpbuf_use_data(&mp_buf, nla, nla->nla_len);
> + rtnh = ofpbuf_try_pull(&mp_buf, sizeof *rtnh);
> + if (!rtnh) {
> + VLOG_DBG_RL(&rl, "Got short message while parsing "
> + "multipath attribute.");
> + goto error_out;
> + }
> +
> + rc = route_table_parse__(&mp_buf, 0,
> + nlmsg, rtm, &mp_change);
> +
> + if (rc == RTNLGRP_IPV4_ROUTE
> + || rc == RTNLGRP_IPV6_ROUTE) {
> + struct route_data_nexthop *mp_rdnh;
> + LIST_FOR_EACH (mp_rdnh, nexthop_node,
> + &mp_change.rd.nexthops) {
> +
> ROUTE_TABLE_PARSE_IF_INDEXTONAME(rtnh->rtnh_ifindex,
> + mp_rdnh->ifname);
>
I'm considering passing struct rtnexthop into route_table_parse__ so that
it can look up and store interface name directly instead of this post
processing. That would also remove the need for the macro.
--
Frode Nordahl
+ }
> + ovs_list_push_back_all(&change->rd.nexthops,
> + &mp_change.rd.nexthops);
> + } else {
> + route_data_destroy(&mp_change.rd);
> + goto error_out;
> + }
> + }
> + }
> ovs_list_insert(&change->rd.nexthops, &rdnh->nexthop_node);
> } else {
> VLOG_DBG_RL(&rl, "received unparseable rtnetlink route message");
> diff --git a/tests/system-route.at b/tests/system-route.at
> index 46db676f2..c50b8d8b7 100644
> --- a/tests/system-route.at
> +++ b/tests/system-route.at
> @@ -44,6 +44,30 @@ Cached: 192.168.10.13/32 dev br0 GW 192.168.9.1 SRC
> 192.168.9.3])
> OVS_TRAFFIC_VSWITCHD_STOP
> AT_CLEANUP
>
> +AT_SETUP([ovs-route - add system route with multiple nexthop - ipv4])
> +AT_KEYWORDS([route])
> +OVS_TRAFFIC_VSWITCHD_START()
> +
> +dnl Create tap ports.
> +AT_CHECK([ip tuntap add name p1-route mode tap])
> +AT_CHECK([ip link set p1-route up])
> +on_exit 'ip link del p1-route'
> +AT_CHECK([ip tuntap add name p2-route mode tap])
> +AT_CHECK([ip link set p2-route up])
> +on_exit 'ip link del p2-route'
> +
> +AT_CHECK([ip addr add 192.168.42.10/24 dev p1-route], [0], [stdout])
> +AT_CHECK([ip addr add 192.168.51.10/24 dev p2-route], [0], [stdout])
> +AT_CHECK([ip route add 172.16.42.0/24 nexthop via 192.168.42.1 dev
> p1-route nexthop via 192.168.51.1 dev p2-route], [0], [stdout])
> +
> +dnl NOTE(fnordahl): At the time of this writing, it is expected that only
> the
> +dnl second route will be stored in ovs-router.
> +OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E '172.16.42.0/24'
> | sort], [dnl
> +Cached: 172.16.42.0/24 dev p2-route GW 192.168.51.1 SRC 192.168.51.10])
> +
> +OVS_TRAFFIC_VSWITCHD_STOP
> +AT_CLEANUP
> +
> AT_SETUP([ovs-route - add system route with src - ipv6])
> AT_KEYWORDS([route])
> OVS_TRAFFIC_VSWITCHD_START()
> @@ -65,6 +89,30 @@ 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 with multiple nexthop - ipv6])
> +AT_KEYWORDS([route])
> +OVS_TRAFFIC_VSWITCHD_START()
> +
> +dnl Create tap ports.
> +AT_CHECK([ip tuntap add name p1-route mode tap])
> +AT_CHECK([ip link set p1-route up])
> +on_exit 'ip link del p1-route'
> +AT_CHECK([ip tuntap add name p2-route mode tap])
> +AT_CHECK([ip link set p2-route up])
> +on_exit 'ip link del p2-route'
> +
> +AT_CHECK([ip -6 addr add fc00:db8:dead::10/64 dev p1-route], [0],
> [stdout])
> +AT_CHECK([ip -6 addr add fc00:db8:beef::10/64 dev p2-route], [0],
> [stdout])
> +AT_CHECK([ip -6 route add fc00:db8:cafe::/64 nexthop via fc00:db8:dead::1
> dev p1-route nexthop via fc00:db8:beef::1 dev p2-route], [0], [stdout])
> +
> +dnl NOTE(fnordahl): At the time of this writing, it is expected that only
> the
> +dnl second route will be stored in ovs-router.
> +OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E
> 'fc00:db8:cafe::/64' | sort], [dnl
> +Cached: fc00:db8:cafe::/64 dev p2-route GW fc00:db8:beef::1 SRC
> fc00:db8:beef::10])
> +
> +OVS_TRAFFIC_VSWITCHD_STOP
> +AT_CLEANUP
> +
> AT_SETUP([ovs-route - add system route - ipv4 via ipv6 nexthop])
> AT_KEYWORDS([route])
> OVS_TRAFFIC_VSWITCHD_START()
> @@ -83,6 +131,30 @@ Cached: 192.168.10.12/32 dev br0 GW
> fe80::253:ff:fe00:51 SRC fe80::253:ff:fe00:4
> OVS_TRAFFIC_VSWITCHD_STOP
> AT_CLEANUP
>
> +AT_SETUP([ovs-route - add system route - ipv4 via multiple ipv6 nexthop])
> +AT_KEYWORDS([route])
> +OVS_TRAFFIC_VSWITCHD_START()
> +
> +dnl Create tap ports.
> +AT_CHECK([ip tuntap add name p1-route mode tap])
> +AT_CHECK([ip link set p1-route up])
> +on_exit 'ip link del p1-route'
> +AT_CHECK([ip tuntap add name p2-route mode tap])
> +AT_CHECK([ip link set p2-route up])
> +on_exit 'ip link del p2-route'
> +
> +AT_CHECK([ip -6 addr add fc00:db8:dead::10/64 dev p1-route], [0],
> [stdout])
> +AT_CHECK([ip -6 addr add fc00:db8:beef::10/64 dev p2-route], [0],
> [stdout])
> +AT_CHECK([ip route add 172.16.42.0/24 nexthop via inet6 fc00:db8:dead::1
> dev p1-route nexthop via inet6 fc00:db8:beef::1 dev p2-route], [0],
> [stdout])
> +
> +dnl NOTE(fnordahl): At the time of this writing, it is expected that only
> the
> +dnl second route will be stored in ovs-router.
> +OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E '172.16.42.0/24'
> | sort], [dnl
> +Cached: 172.16.42.0/24 dev p2-route GW fc00:db8:beef::1 SRC
> fc00:db8:beef::10])
> +
> +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])
> --
> 2.45.2
>
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev