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

Reply via email to