On 7 Feb 2023, at 7:48, Nobuhiro MIKI wrote:

> We can use the "ip route add ... src ..." command to set the preferred
> source address for each entry in the kernel FIB. OVS has a mechanism to
> cache the FIB, but the preferred source address is ignored and
> calculated with its own logic. This patch resolves the difference
> between kernel FIB and OVS route table cache by retrieving the
> RTA_PREFSRC attribute of Netlink messages.

Thanks for the patch, one small nit inline, the rest looks good.

Cheers,

Eelco

> Signed-off-by: Nobuhiro MIKI <nm...@yahoo-corp.jp>
> ---
>  lib/ovs-router.c      |  6 +++---
>  lib/ovs-router.h      |  3 ++-
>  lib/route-table.c     | 16 +++++++++++++++-
>  tests/system-route.at | 39 +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 59 insertions(+), 5 deletions(-)
>
> diff --git a/lib/ovs-router.c b/lib/ovs-router.c
> index fc95a91012f9..160f6fb085bd 100644
> --- a/lib/ovs-router.c
> +++ b/lib/ovs-router.c
> @@ -276,13 +276,13 @@ ovs_router_insert__(uint32_t mark, uint8_t priority, 
> bool local,
>
>  void
>  ovs_router_insert(uint32_t mark, const struct in6_addr *ip_dst, uint8_t plen,
> -                  bool local, const char output_bridge[],
> -                  const struct in6_addr *gw)
> +                  bool local, const char output_bridge[],
> +                  const struct in6_addr *gw, const struct in6_addr *prefsrc)
>  {
>      if (use_system_routing_table) {
>          uint8_t priority = local ? plen + 64 : plen;
>          ovs_router_insert__(mark, priority, local, ip_dst, plen,
> -                            output_bridge, gw, &in6addr_any);
> +                            output_bridge, gw, prefsrc);
>      }
>  }
>
> diff --git a/lib/ovs-router.h b/lib/ovs-router.h
> index d8ce3c00ded5..eb4ff85d9e63 100644
> --- a/lib/ovs-router.h
> +++ b/lib/ovs-router.h
> @@ -32,7 +32,8 @@ bool ovs_router_lookup(uint32_t mark, const struct in6_addr 
> *ip_dst,
>  void ovs_router_init(void);
>  void ovs_router_insert(uint32_t mark, const struct in6_addr *ip_dst,
>                         uint8_t plen, bool local,
> -                       const char output_bridge[], const struct in6_addr 
> *gw);
> +                       const char output_bridge[], const struct in6_addr *gw,
> +                       const struct in6_addr *prefsrc);
>  void ovs_router_flush(void);
>
>  void ovs_router_disable_system_routing_table(void);
> diff --git a/lib/route-table.c b/lib/route-table.c
> index ac82cf262f86..bb030c8ef66c 100644
> --- a/lib/route-table.c
> +++ b/lib/route-table.c
> @@ -51,6 +51,7 @@ 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;
> @@ -201,6 +202,7 @@ route_table_parse(struct ofpbuf *buf, struct 
> route_table_msg *change)
>          [RTA_OIF] = { .type = NL_A_U32, .optional = true },
>          [RTA_GATEWAY] = { .type = NL_A_U32, .optional = true },
>          [RTA_MARK] = { .type = NL_A_U32, .optional = true },
> +        [RTA_PREFSRC] = { .type = NL_A_U32, .optional = true  },

You have a double space after true and before }.

>      };
>
>      static const struct nl_policy policy6[] = {
> @@ -208,6 +210,7 @@ route_table_parse(struct ofpbuf *buf, struct 
> route_table_msg *change)
>          [RTA_OIF] = { .type = NL_A_U32, .optional = true },
>          [RTA_MARK] = { .type = NL_A_U32, .optional = true },
>          [RTA_GATEWAY] = { .type = NL_A_IPV6, .optional = true },
> +        [RTA_PREFSRC] = { .type = NL_A_IPV6, .optional = true },
>      };
>
>      struct nlattr *attrs[ARRAY_SIZE(policy)];
> @@ -274,6 +277,16 @@ route_table_parse(struct ofpbuf *buf, struct 
> route_table_msg *change)
>          } else if (ipv4) {
>              in6_addr_set_mapped_ipv4(&change->rd.rta_dst, 0);
>          }
> +        if (attrs[RTA_PREFSRC]) {
> +            if (ipv4) {
> +                ovs_be32 prefsrc;
> +                prefsrc = nl_attr_get_be32(attrs[RTA_PREFSRC]);
> +                in6_addr_set_mapped_ipv4(&change->rd.rta_prefsrc, prefsrc);
> +            } else {
> +                change->rd.rta_prefsrc =
> +                    nl_attr_get_in6_addr(attrs[RTA_PREFSRC]);
> +            }
> +        }
>          if (attrs[RTA_GATEWAY]) {
>              if (ipv4) {
>                  ovs_be32 gw;
> @@ -309,7 +322,8 @@ route_table_handle_msg(const struct route_table_msg 
> *change)
>          const struct route_data *rd = &change->rd;
>
>          ovs_router_insert(rd->mark, &rd->rta_dst, rd->rtm_dst_len,
> -                          rd->local, rd->ifname, &rd->rta_gw);
> +                          rd->local, rd->ifname, &rd->rta_gw,
> +                          &rd->rta_prefsrc);
>      }
>  }
>
> diff --git a/tests/system-route.at b/tests/system-route.at
> index 270956d13f6f..114aaebc77f3 100644
> --- a/tests/system-route.at
> +++ b/tests/system-route.at
> @@ -25,3 +25,42 @@ OVS_WAIT_UNTIL([test `ovs-appctl ovs/route/show | grep -c 
> 'p1-route'` -eq 0 ])
>
>  OVS_TRAFFIC_VSWITCHD_STOP
>  AT_CLEANUP
> +
> +AT_SETUP([ovs-route - add system route with src - ipv4])
> +AT_KEYWORDS([route])
> +OVS_TRAFFIC_VSWITCHD_START()
> +AT_CHECK([ip link set br0 up])
> +
> +AT_CHECK([ip addr add 192.168.9.2/24 dev br0], [0], [stdout])
> +AT_CHECK([ip addr add 192.168.9.3/24 dev br0], [0], [stdout])
> +
> +AT_CHECK([ip route add 192.168.10.12/32 dev br0 via 192.168.9.1 src 
> 192.168.9.2], [0], [stdout])
> +AT_CHECK([ip route add 192.168.10.13/32 dev br0 via 192.168.9.1 src 
> 192.168.9.3], [0], [stdout])
> +
> +OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E 
> '192.168.10.1[[23]]/32' | sort], [dnl
> +Cached: 192.168.10.12/32 dev br0 GW 192.168.9.1 SRC 192.168.9.2
> +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 src - ipv6])
> +AT_KEYWORDS([route])
> +OVS_TRAFFIC_VSWITCHD_START()
> +AT_CHECK([ip link set br0 up])
> +
> +AT_CHECK([ip -6 addr add fc00:db8:cafe::2/64 dev br0], [0], [stdout])
> +AT_CHECK([ip -6 addr add fc00:db8:cafe::3/64 dev br0], [0], [stdout])
> +
> +dnl If we try to add a route immediately after assigning ipv6 addresses,
> +dnl iproute2 would give us "Invalid source address" error,
> +dnl so wait a while to succeed.
> +OVS_WAIT_UNTIL([ip -6 route add fc00:db8:beef::12/128 via fc00:db8:cafe::1 
> dev br0 src fc00:db8:cafe::3])
> +OVS_WAIT_UNTIL([ip -6 route add fc00:db8:beef::13/128 via fc00:db8:cafe::1 
> dev br0 src fc00:db8:cafe::2])
> +
> +OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E 
> 'fc00:db8:beef::1[[23]]/128' | sort], [dnl
> +Cached: fc00:db8:beef::12/128 dev br0 GW fc00:db8:cafe::1 SRC 
> fc00:db8:cafe::3
> +Cached: fc00:db8:beef::13/128 dev br0 GW fc00:db8:cafe::1 SRC 
> fc00:db8:cafe::2])
> +
> +OVS_TRAFFIC_VSWITCHD_STOP
> +AT_CLEANUP
> -- 
> 2.31.1
>
> _______________________________________________
> dev mailing list
> d...@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to