git: 823a08d7403c - main - nhops: split nh_family into nh_upper_family and nh_neigh_family.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Wed, 29 Dec 2021 21:30:33 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=823a08d7403c475fea0ecbbfff021fa8db274879

commit 823a08d7403c475fea0ecbbfff021fa8db274879
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2021-12-26 18:07:37 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2021-12-29 21:03:19 +0000

    nhops: split nh_family into nh_upper_family and nh_neigh_family.
    
    With IPv4 over IPv6 nexthops and IP->MPLS support, there is a need
     to distingush "upper" e.g. traffic family and "neighbor" e.g. LLE/gateway
     address family. Store them explicitly in the private part of the nexthop data.
    
    While here, store nhop fibnum in nhop_prip datastructure to make it self-contained.
    
    MFC after:      2 weeks
    Differential Revision: https://reviews.freebsd.org/D33663
---
 sys/net/route/nhop.h     |  3 +++
 sys/net/route/nhop_ctl.c | 60 +++++++++++++++++++++++++++++++++++++++---------
 sys/net/route/nhop_var.h |  5 ++--
 3 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/sys/net/route/nhop.h b/sys/net/route/nhop.h
index ce18cc04e163..1d37a84b68b4 100644
--- a/sys/net/route/nhop.h
+++ b/sys/net/route/nhop.h
@@ -179,6 +179,9 @@ enum nhop_type nhop_get_type(const struct nhop_object *nh);
 int nhop_get_rtflags(const struct nhop_object *nh);
 struct vnet *nhop_get_vnet(const struct nhop_object *nh);
 struct nhop_object *nhop_select_func(struct nhop_object *nh, uint32_t flowid);
+int nhop_get_upper_family(const struct nhop_object *nh);
+int nhop_get_neigh_family(const struct nhop_object *nh);
+uint32_t nhop_get_fibnum(const struct nhop_object *nh);
 
 #endif /* _KERNEL */
 
diff --git a/sys/net/route/nhop_ctl.c b/sys/net/route/nhop_ctl.c
index 21aefcc7a83b..45830cbb14c8 100644
--- a/sys/net/route/nhop_ctl.c
+++ b/sys/net/route/nhop_ctl.c
@@ -28,6 +28,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 #include "opt_inet.h"
+#include "opt_inet6.h"
 #include "opt_route.h"
 
 #include <sys/param.h>
@@ -58,7 +59,7 @@ __FBSDID("$FreeBSD$");
  * Nexthops in the original sense are the objects containing all the necessary
  * information to forward the packet to the selected destination.
  * In particular, nexthop is defined by a combination of
- *  ifp, ifa, aifp, mtu, gw addr(if set), nh_type, nh_family, mask of rt_flags and
+ *  ifp, ifa, aifp, mtu, gw addr(if set), nh_type, nh_upper_family, mask of rt_flags and
  *    NHF_DEFAULT
  *
  * Additionally, each nexthop gets assigned its unique index (nexthop index).
@@ -278,13 +279,17 @@ fill_nhop_from_info(struct nhop_priv *nh_priv, struct rt_addrinfo *info)
 	rt_flags = info->rti_flags & NHOP_RT_FLAG_MASK;
 
 	nh->nh_priv->rt_flags = rt_flags;
-	nh_priv->nh_family = info->rti_info[RTAX_DST]->sa_family;
+	nh_priv->nh_upper_family = info->rti_info[RTAX_DST]->sa_family;
 	nh_priv->nh_type = 0; // hook responsibility to set nhop type
-
 	nh->nh_flags = convert_rt_to_nh_flags(rt_flags);
+
 	set_nhop_mtu_from_info(nh, info);
 	if ((error = set_nhop_gw_from_info(nh, info)) != 0)
 		return (error);
+	if (nh->gw_sa.sa_family == AF_LINK)
+		nh_priv->nh_neigh_family = nh_priv->nh_upper_family;
+	else
+		nh_priv->nh_neigh_family = nh->gw_sa.sa_family;
 
 	nh->nh_ifp = (info->rti_ifp != NULL) ? info->rti_ifp : info->rti_ifa->ifa_ifp;
 	nh->nh_ifa = info->rti_ifa;
@@ -401,6 +406,7 @@ get_nhop(struct rib_head *rnh, struct rt_addrinfo *info,
 static int
 alter_nhop_from_info(struct nhop_object *nh, struct rt_addrinfo *info)
 {
+	struct nhop_priv *nh_priv = nh->nh_priv;
 	struct sockaddr *info_gw;
 	int error;
 
@@ -410,8 +416,8 @@ alter_nhop_from_info(struct nhop_object *nh, struct rt_addrinfo *info)
 	/* XXX: allow only one of BLACKHOLE,REJECT,GATEWAY */
 
 	/* Allow some flags (FLAG1,STATIC,BLACKHOLE,REJECT) to be toggled on change. */
-	nh->nh_priv->rt_flags &= ~RTF_FMASK;
-	nh->nh_priv->rt_flags |= info->rti_flags & RTF_FMASK;
+	nh_priv->rt_flags &= ~RTF_FMASK;
+	nh_priv->rt_flags |= info->rti_flags & RTF_FMASK;
 
 	/* Consider gateway change */
 	info_gw = info->rti_info[RTAX_GATEWAY];
@@ -419,12 +425,16 @@ alter_nhop_from_info(struct nhop_object *nh, struct rt_addrinfo *info)
 		error = set_nhop_gw_from_info(nh, info);
 		if (error != 0)
 			return (error);
+		if (nh->gw_sa.sa_family == AF_LINK)
+			nh_priv->nh_neigh_family = nh_priv->nh_upper_family;
+		else
+			nh_priv->nh_neigh_family = nh->gw_sa.sa_family;
 		/* Update RTF_GATEWAY flag status */
-		nh->nh_priv->rt_flags &= ~RTF_GATEWAY;
-		nh->nh_priv->rt_flags |= (RTF_GATEWAY & info->rti_flags);
+		nh_priv->rt_flags &= ~RTF_GATEWAY;
+		nh_priv->rt_flags |= (RTF_GATEWAY & info->rti_flags);
 	}
 	/* Update datapath flags */
-	nh->nh_flags = convert_rt_to_nh_flags(nh->nh_priv->rt_flags);
+	nh->nh_flags = convert_rt_to_nh_flags(nh_priv->rt_flags);
 
 	if (info->rti_ifa != NULL)
 		nh->nh_ifa = info->rti_ifa;
@@ -458,7 +468,8 @@ nhop_create_from_nhop(struct rib_head *rnh, const struct nhop_object *nh_orig,
 	nh = nh_priv->nh;
 
 	/* Start with copying data from original nexthop */
-	nh_priv->nh_family = nh_orig->nh_priv->nh_family;
+	nh_priv->nh_upper_family = nh_orig->nh_priv->nh_upper_family;
+	nh_priv->nh_neigh_family = nh_orig->nh_priv->nh_neigh_family;
 	nh_priv->rt_flags = nh_orig->nh_priv->rt_flags;
 	nh_priv->nh_type = nh_orig->nh_priv->nh_type;
 
@@ -561,6 +572,8 @@ finalize_nhop(struct nh_control *ctl, struct rt_addrinfo *info,
 	/* Please see nhop_free() comments on the initial value */
 	refcount_init(&nh_priv->nh_linked, 2);
 
+	nh_priv->nh_fibnum = ctl->ctl_rh->rib_fibnum;
+
 	print_nhop("FINALIZE", nh);
 
 	if (link_nhop(ctl, nh_priv) == 0) {
@@ -608,7 +621,7 @@ print_nhop(const char *prefix, const struct nhop_object *nh)
 	print_nhop_sa(addr_buf, sizeof(addr_buf), &nh->gw_sa);
 
 	DPRINTF("%s nhop priv %p: AF %d ifp %p %s addr %s src %p %s aifp %p %s mtu %d nh_flags %X",
-	    prefix, nh->nh_priv, nh->nh_priv->nh_family, nh->nh_ifp,
+	    prefix, nh->nh_priv, nh->nh_priv->nh_upper_family, nh->nh_ifp,
 	    if_name(nh->nh_ifp), addr_buf, nh->nh_ifa, src_buf, nh->nh_aifp,
 	    if_name(nh->nh_aifp), nh->nh_mtu, nh->nh_flags);
 }
@@ -782,6 +795,31 @@ nhop_select_func(struct nhop_object *nh, uint32_t flowid)
 	return (nhop_select(nh, flowid));
 }
 
+/*
+ * Returns address family of the traffic uses the nexthop.
+ */
+int
+nhop_get_upper_family(const struct nhop_object *nh)
+{
+	return (nh->nh_priv->nh_upper_family);
+}
+
+/*
+ * Returns address family of the LLE or gateway that is used
+ * to forward the traffic to.
+ */
+int
+nhop_get_neigh_family(const struct nhop_object *nh)
+{
+	return (nh->nh_priv->nh_neigh_family);
+}
+
+uint32_t
+nhop_get_fibnum(const struct nhop_object *nh)
+{
+	return (nh->nh_priv->nh_fibnum);
+}
+
 void
 nhops_update_ifmtu(struct rib_head *rh, struct ifnet *ifp, uint32_t mtu)
 {
@@ -845,7 +883,7 @@ dump_nhop_entry(struct rib_head *rh, struct nhop_object *nh, struct sysctl_req *
 	pnhe->nh_fib = rh->rib_fibnum;
 	pnhe->ifindex = nh->nh_ifp->if_index;
 	pnhe->aifindex = nh->nh_aifp->if_index;
-	pnhe->nh_family = nh->nh_priv->nh_family;
+	pnhe->nh_family = nh->nh_priv->nh_upper_family;
 	pnhe->nh_type = nh->nh_priv->nh_type;
 	pnhe->nh_mtu = nh->nh_mtu;
 	pnhe->nh_flags = nh->nh_flags;
diff --git a/sys/net/route/nhop_var.h b/sys/net/route/nhop_var.h
index 76984df0497f..facf8a7a546b 100644
--- a/sys/net/route/nhop_var.h
+++ b/sys/net/route/nhop_var.h
@@ -74,12 +74,13 @@ struct nh_control {
 struct nhop_object;
 struct nhop_priv {
 	/* nhop lookup comparison start */
-	uint8_t			nh_family;	/* address family of the lookup */
-	uint8_t			spare;
+	uint8_t			nh_upper_family;/* address family of the lookup */
+	uint8_t			nh_neigh_family;/* neighbor address family */
 	uint16_t		nh_type;	/* nexthop type */
 	uint32_t		rt_flags;	/* routing flags for the control plane */
 	/* nhop lookup comparison end */
 	uint32_t		nh_idx;		/* nexthop index */
+	uint32_t		nh_fibnum;	/* nexthop fib */
 	void			*cb_func;	/* function handling additional rewrite caps */
 	u_int			nh_refcnt;	/* number of references, refcount(9)  */
 	u_int			nh_linked;	/* refcount(9), == 2 if linked to the list */