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.
>
> Signed-off-by: Frode Nordahl <[email protected]>
> ---

Recheck-request: github-robot

>  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 */
>      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 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]);
>          }
> +        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) {
> +                    VLOG_DBG_RL(&rl, "Got short message while parsing 
> RTA_VIA "
> +                                "attribute for family AF_INET.");
> +                    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.");
> +                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])
> +
> +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])
> -- 
> 2.45.2

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to