fre. 6. des. 2024, 21:27 skrev Frode Nordahl <[email protected]>:

> In preparation for adding support for parsing attributes such as
> RTA_VIA and RTA_MULTIPATH, we need dynamic storage for route
> nexthops.
>
> This patch makes this change in isolation so that it is easier to
> review subsequent patches.
>
> Signed-off-by: Frode Nordahl <[email protected]>
> ---
>  lib/route-table.c | 66 ++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 56 insertions(+), 10 deletions(-)
>
> diff --git a/lib/route-table.c b/lib/route-table.c
> index 33e0df2b8..30b1c7339 100644
> --- a/lib/route-table.c
> +++ b/lib/route-table.c
> @@ -32,6 +32,7 @@
>  #include "netlink.h"
>  #include "netlink-notifier.h"
>  #include "netlink-socket.h"
> +#include "openvswitch/list.h"
>  #include "openvswitch/ofpbuf.h"
>  #include "ovs-router.h"
>  #include "packets.h"
> @@ -47,7 +48,16 @@ VLOG_DEFINE_THIS_MODULE(route_table);
>
>  COVERAGE_DEFINE(route_table_dump);
>
> +struct route_data_nexthop {
> +    struct ovs_list nexthop_node;
> +
> +    struct in6_addr addr;
> +    char ifname[IFNAMSIZ]; /* Interface name. */
> +};
> +
>  struct route_data {
> +    struct ovs_list nexthops;
> +
>      /* Copied from struct rtmsg. */
>      unsigned char rtm_dst_len;
>      unsigned char rtm_protocol;
> @@ -56,13 +66,12 @@ struct route_data {
>      /* Extracted from Netlink attributes. */
>      struct in6_addr rta_dst; /* 0 if missing. */
>      struct in6_addr rta_prefsrc; /* 0 if missing. */
> -    struct in6_addr rta_gw;
> -    char ifname[IFNAMSIZ]; /* Interface name. */
>      uint32_t mark;
>      uint32_t rta_table_id; /* 0 if missing. */
>      uint32_t rta_priority; /* 0 if missing. */
>  };
>
> +
>  /* A digested version of a route message sent down by the kernel to
> indicate
>   * that a route has changed. */
>  struct route_table_msg {
> @@ -95,6 +104,25 @@ static void route_map_clear(void);
>  static void name_table_init(void);
>  static void name_table_change(const struct rtnetlink_change *, void *);
>
> +static void
> +route_data_init(struct route_data *rd)
> +{
> +    memset(rd, 0, sizeof *rd);
> +    *rd = (struct route_data) {
> +        .nexthops = OVS_LIST_INITIALIZER(&rd->nexthops),
> +    };
> +}
> +
> +static void
> +route_data_destroy(struct route_data *rd)
> +{
> +    struct route_data_nexthop *rdnh;
> +
> +    LIST_FOR_EACH_POP (rdnh, nexthop_node, &rd->nexthops) {
> +        free(rdnh);
> +    }
> +}
> +
>  uint64_t
>  route_table_get_change_seq(void)
>  {
> @@ -112,6 +140,8 @@ route_table_init(void)
>      ovs_assert(!route_notifier);
>      ovs_assert(!route6_notifier);
>
> +    route_data_init(&rtmsg.rd);
> +
>      ovs_router_init();
>      nln = nln_create(NETLINK_ROUTE, route_table_parse, &rtmsg);
>
> @@ -191,6 +221,7 @@ route_table_dump_one_table(unsigned char id)
>              }
>              route_table_handle_msg(&msg);
>          }
> +        route_data_destroy(&msg.rd);
>      }
>      ofpbuf_uninit(&buf);
>      nl_dump_done(&dump);
> @@ -230,6 +261,7 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
>                      const struct rtmsg *rtm, void *change_)
>  {
>      struct route_table_msg *change = change_;
> +    struct route_data_nexthop *rdnh = NULL;
>      bool parsed, ipv4 = false;
>
>      static const struct nl_policy policy[] = {
> @@ -268,8 +300,10 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
>
>      if (parsed) {
>          int rta_oif;      /* Output interface index. */
> +        rdnh = xzalloc(sizeof *rdnh);
>

When route_table_parse is called from route-table module we free this
memory after processing.

However it is also called from the netlink notifier, which will not free
this memory.

I'll add another front-end function to this, so we can decide whether data
should be stored or if we are only doing classification.

--
Frode Nordahl


>          memset(change, 0, sizeof *change);
> +        route_data_init(&change->rd);
>          change->relevant = true;
>
>          if (rtm->rtm_scope == RT_SCOPE_NOWHERE) {
> @@ -290,10 +324,11 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
>          change->rd.rtm_dst_len = rtm->rtm_dst_len + (ipv4 ? 96 : 0);
>          change->rd.rtm_protocol = rtm->rtm_protocol;
>          change->rd.local = rtm->rtm_type == RTN_LOCAL;
> +
>          if (attrs[RTA_OIF]) {
>              rta_oif = nl_attr_get_u32(attrs[RTA_OIF]);
>
> -            if (!if_indextoname(rta_oif, change->rd.ifname)) {
> +            if (!if_indextoname(rta_oif, rdnh->ifname)) {
>                  int error = errno;
>
>                  VLOG_DBG_RL(&rl, "Could not find interface name[%u]: %s",
> @@ -301,7 +336,7 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
>                  if (error == ENXIO) {
>                      change->relevant = false;
>                  } else {
> -                    return 0;
> +                    goto error_out;
>                  }
>              }
>          }
> @@ -331,9 +366,9 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
>              if (ipv4) {
>                  ovs_be32 gw;
>                  gw = nl_attr_get_be32(attrs[RTA_GATEWAY]);
> -                in6_addr_set_mapped_ipv4(&change->rd.rta_gw, gw);
> +                in6_addr_set_mapped_ipv4(&rdnh->addr, gw);
>              } else {
> -                change->rd.rta_gw =
> nl_attr_get_in6_addr(attrs[RTA_GATEWAY]);
> +                rdnh->addr = nl_attr_get_in6_addr(attrs[RTA_GATEWAY]);
>              }
>          }
>          if (attrs[RTA_MARK]) {
> @@ -342,13 +377,21 @@ route_table_parse__(struct ofpbuf *buf, size_t ofs,
>          if (attrs[RTA_PRIORITY]) {
>              change->rd.rta_priority =
> nl_attr_get_u32(attrs[RTA_PRIORITY]);
>          }
> +
> +        ovs_list_insert(&change->rd.nexthops, &rdnh->nexthop_node);
>      } else {
>          VLOG_DBG_RL(&rl, "received unparseable rtnetlink route message");
> -        return 0;
> +        goto error_out;
>      }
>
>      /* Success. */
>      return ipv4 ? RTNLGRP_IPV4_ROUTE : RTNLGRP_IPV6_ROUTE;
> +
> +error_out:
> +    if (rdnh) {
> +        free (rdnh);
> +    }
> +    return 0;
>  }
>
>  static int
> @@ -389,10 +432,13 @@ route_table_handle_msg(const struct route_table_msg
> *change)
>  {
>      if (change->relevant && change->nlmsg_type == RTM_NEWROUTE) {
>          const struct route_data *rd = &change->rd;
> +        const struct route_data_nexthop *rdnh;
>
> -        ovs_router_insert(rd->mark, &rd->rta_dst, rd->rtm_dst_len,
> -                          rd->local, rd->ifname, &rd->rta_gw,
> -                          &rd->rta_prefsrc);
> +        LIST_FOR_EACH (rdnh, nexthop_node, &rd->nexthops) {
> +            ovs_router_insert(rd->mark, &rd->rta_dst, rd->rtm_dst_len,
> +                              rd->local, rdnh->ifname, &rdnh->addr,
> +                              &rd->rta_prefsrc);
> +        }
>      }
>  }
>
> --
> 2.45.2
>
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to