Re: svn commit: r365521 - head/sys/net/route

2020-09-09 Thread Hartmann, O.
On Wed, 9 Sep 2020 22:07:55 + (UTC)
"Alexander V. Chernikov"  wrote:

> Author: melifaro
> Date: Wed Sep  9 22:07:54 2020
> New Revision: 365521
> URL: https://svnweb.freebsd.org/changeset/base/365521
>
> Log:
>   Update nexthop handling for route addition/deletion in preparation
> for mpath.
>   Currently kernel requests deletion for the certain routes with
> specified gateway, but this gateway is not actually checked. With
> multipath routes, internal gateway checking becomes mandatory. Add
> the logic performing this check.
>   Generalise RTF_PINNED routes to the generic route priorities,
> simplifying the logic.
>   Add lookup_prefix() function to perform exact match search based on
> data in @info.
>   Differential Revision:  https://reviews.freebsd.org/D26356
>
> Modified:
>   head/sys/net/route/route_ctl.c
>   head/sys/net/route/route_var.h
>
> Modified: head/sys/net/route/route_ctl.c
> ==
> --- head/sys/net/route/route_ctl.cWed Sep  9 22:02:30
> 2020  (r365520) +++ head/sys/net/route/route_ctl.cWed
> Sep  9 22:07:54 2020  (r365521) @@ -86,6 +86,10 @@ static int
> change_route(struct rib_head *rnh, struct r static int
> change_route_nhop(struct rib_head *rnh, struct rtentry *rt, struct
> rt_addrinfo *info, struct route_nhop_data *rnd, struct rib_cmd_info
> *rc); +
> +static int rt_unlinkrte(struct rib_head *rnh, struct rt_addrinfo
> *info,
> +struct rib_cmd_info *rc);
> +
>  static void rib_notify(struct rib_head *rnh, enum
> rib_subscription_type type, struct rib_cmd_info *rc);
>
> @@ -172,6 +176,141 @@ get_rnh(uint32_t fibnum, const struct
> rt_addrinfo *inf }
>
>  /*
> + * Check if specified @gw matches gw data in the nexthop @nh.
> + *
> + * Returns true if matches, false otherwise.
> + */
> +static bool
> +match_nhop_gw(const struct nhop_object *nh, const struct sockaddr
> *gw) +{
> +
> + if (nh->gw_sa.sa_family != gw->sa_family)
> + return (false);
> +
> + switch (gw->sa_family) {
> + case AF_INET:
> + return (nh->gw4_sa.sin_addr.s_addr ==
> + ((const struct sockaddr_in
> *)gw)->sin_addr.s_addr);
> + case AF_INET6:
> + {
> + const struct sockaddr_in6 *gw6;
> + gw6 = (const struct sockaddr_in6 *)gw;
> +
> + /*
> +  * Currently (2020-09) IPv6 gws in kernel
> have their
> +  * scope embedded. Once this becomes false,
> this code
> +  * has to be revisited.
> +  */
> + if (IN6_ARE_ADDR_EQUAL(>gw6_sa.sin6_addr,
> + >sin6_addr))
> + return (true);
> + return (false);
> + }
> + case AF_LINK:
> + {
> + const struct sockaddr_dl *sdl;
> + sdl = (const struct sockaddr_dl *)gw;
> + return (nh->gwl_sa.sdl_index ==
> sdl->sdl_index);
> + }
> + default:
> + return (memcmp(>gw_sa, gw, nh->gw_sa.sa_len) ==
> 0);
> + }
> +
> + /* NOTREACHED */
> + return (false);
> +}
> +
> +/*
> + * Checks if data in @info matches nexhop @nh.
> + *
> + * Returns 0 on success,
> + * ESRCH if not matched,
> + * ENOENT if filter function returned false
> + */
> +int
> +check_info_match_nhop(const struct rt_addrinfo *info, const struct
> rtentry *rt,
> +const struct nhop_object *nh)
> +{
> + const struct sockaddr *gw = info->rti_info[RTAX_GATEWAY];
> +
> + if (info->rti_filter != NULL) {
> + if (info->rti_filter(rt, nh, info->rti_filterdata) == 0)
> + return (ENOENT);
> + else
> + return (0);
> + }
> + if ((gw != NULL) && !match_nhop_gw(nh, gw))
> + return (ESRCH);
> +
> + return (0);
> +}
> +
> +/*
> + * Checks if nexhop @nh can be rewritten by data in @info because
> + *  of higher "priority". Currently the only case for such scenario
> + *  is kernel installing interface routes, marked by RTF_PINNED flag.
> + *
> + * Returns:
> + * 1 if @info data has higher priority
> + * 0 if priority is the same
> + * -1 if priority is lower
> + */
> +int
> +can_override_nhop(const struct rt_addrinfo *info, const struct
> nhop_object *nh) +{
> +
> + if (info->rti_flags & RTF_PINNED) {
> + return (NH_IS_PINNED(nh)) ? 0 : 1;
> + } else {
> + return (NH_IS_PINNED(nh)) ? -1 : 0;
> + }
> +}
> +
> +/*
> + * Runs exact prefix match based on @dst and @netmask.
> + * Returns matched @rtentry if found or NULL.
> + * If rtentry was found, saves nexthop / weight value into @rnd.
> + */
> +static struct rtentry *
> +lookup_prefix_bysa(struct rib_head *rnh, const struct sockaddr *dst,
> +const struct sockaddr *netmask, struct route_nhop_data *rnd)
> +{
> + struct rtentry *rt;
> +
> + RIB_LOCK_ASSERT(rnh);
> +
> 

svn commit: r365521 - head/sys/net/route

2020-09-09 Thread Alexander V. Chernikov
Author: melifaro
Date: Wed Sep  9 22:07:54 2020
New Revision: 365521
URL: https://svnweb.freebsd.org/changeset/base/365521

Log:
  Update nexthop handling for route addition/deletion in preparation for mpath.
  
  Currently kernel requests deletion for the certain routes with specified 
gateway,
   but this gateway is not actually checked. With multipath routes, internal 
gateway
   checking becomes mandatory. Add the logic performing this check.
  
  Generalise RTF_PINNED routes to the generic route priorities, simplifying the 
logic.
  
  Add lookup_prefix() function to perform exact match search based on data in 
@info.
  
  Differential Revision:https://reviews.freebsd.org/D26356

Modified:
  head/sys/net/route/route_ctl.c
  head/sys/net/route/route_var.h

Modified: head/sys/net/route/route_ctl.c
==
--- head/sys/net/route/route_ctl.c  Wed Sep  9 22:02:30 2020
(r365520)
+++ head/sys/net/route/route_ctl.c  Wed Sep  9 22:07:54 2020
(r365521)
@@ -86,6 +86,10 @@ static int change_route(struct rib_head *rnh, struct r
 static int change_route_nhop(struct rib_head *rnh, struct rtentry *rt,
 struct rt_addrinfo *info, struct route_nhop_data *rnd,
 struct rib_cmd_info *rc);
+
+static int rt_unlinkrte(struct rib_head *rnh, struct rt_addrinfo *info,
+struct rib_cmd_info *rc);
+
 static void rib_notify(struct rib_head *rnh, enum rib_subscription_type type,
 struct rib_cmd_info *rc);
 
@@ -172,6 +176,141 @@ get_rnh(uint32_t fibnum, const struct rt_addrinfo *inf
 }
 
 /*
+ * Check if specified @gw matches gw data in the nexthop @nh.
+ *
+ * Returns true if matches, false otherwise.
+ */
+static bool
+match_nhop_gw(const struct nhop_object *nh, const struct sockaddr *gw)
+{
+
+   if (nh->gw_sa.sa_family != gw->sa_family)
+   return (false);
+
+   switch (gw->sa_family) {
+   case AF_INET:
+   return (nh->gw4_sa.sin_addr.s_addr ==
+   ((const struct sockaddr_in *)gw)->sin_addr.s_addr);
+   case AF_INET6:
+   {
+   const struct sockaddr_in6 *gw6;
+   gw6 = (const struct sockaddr_in6 *)gw;
+
+   /*
+* Currently (2020-09) IPv6 gws in kernel have their
+* scope embedded. Once this becomes false, this code
+* has to be revisited.
+*/
+   if (IN6_ARE_ADDR_EQUAL(>gw6_sa.sin6_addr,
+   >sin6_addr))
+   return (true);
+   return (false);
+   }
+   case AF_LINK:
+   {
+   const struct sockaddr_dl *sdl;
+   sdl = (const struct sockaddr_dl *)gw;
+   return (nh->gwl_sa.sdl_index == sdl->sdl_index);
+   }
+   default:
+   return (memcmp(>gw_sa, gw, nh->gw_sa.sa_len) == 0);
+   }
+
+   /* NOTREACHED */
+   return (false);
+}
+
+/*
+ * Checks if data in @info matches nexhop @nh.
+ *
+ * Returns 0 on success,
+ * ESRCH if not matched,
+ * ENOENT if filter function returned false
+ */
+int
+check_info_match_nhop(const struct rt_addrinfo *info, const struct rtentry *rt,
+const struct nhop_object *nh)
+{
+   const struct sockaddr *gw = info->rti_info[RTAX_GATEWAY];
+
+   if (info->rti_filter != NULL) {
+   if (info->rti_filter(rt, nh, info->rti_filterdata) == 0)
+   return (ENOENT);
+   else
+   return (0);
+   }
+   if ((gw != NULL) && !match_nhop_gw(nh, gw))
+   return (ESRCH);
+
+   return (0);
+}
+
+/*
+ * Checks if nexhop @nh can be rewritten by data in @info because
+ *  of higher "priority". Currently the only case for such scenario
+ *  is kernel installing interface routes, marked by RTF_PINNED flag.
+ *
+ * Returns:
+ * 1 if @info data has higher priority
+ * 0 if priority is the same
+ * -1 if priority is lower
+ */
+int
+can_override_nhop(const struct rt_addrinfo *info, const struct nhop_object *nh)
+{
+
+   if (info->rti_flags & RTF_PINNED) {
+   return (NH_IS_PINNED(nh)) ? 0 : 1;
+   } else {
+   return (NH_IS_PINNED(nh)) ? -1 : 0;
+   }
+}
+
+/*
+ * Runs exact prefix match based on @dst and @netmask.
+ * Returns matched @rtentry if found or NULL.
+ * If rtentry was found, saves nexthop / weight value into @rnd.
+ */
+static struct rtentry *
+lookup_prefix_bysa(struct rib_head *rnh, const struct sockaddr *dst,
+const struct sockaddr *netmask, struct route_nhop_data *rnd)
+{
+   struct rtentry *rt;
+
+   RIB_LOCK_ASSERT(rnh);
+
+   rt = (struct rtentry *)rnh->rnh_lookup(__DECONST(void *, dst),
+   __DECONST(void *, netmask), >head);
+   if (rt != NULL) {
+   rnd->rnd_nhop = rt->rt_nhop;
+