Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Aug 2015 18:28:50 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r287068 - in projects/routing/sys: net netgraph/netflow
Message-ID:  <201508231828.t7NISocn047526@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Sun Aug 23 18:28:50 2015
New Revision: 287068
URL: https://svnweb.freebsd.org/changeset/base/287068

Log:
  Add new rib4/rib6 series of functions returning per-rte
   info packed on stack. Convert ng_netflow to use new routing API.

Modified:
  projects/routing/sys/net/rt_nhops.c
  projects/routing/sys/net/rt_nhops.h
  projects/routing/sys/netgraph/netflow/netflow.c

Modified: projects/routing/sys/net/rt_nhops.c
==============================================================================
--- projects/routing/sys/net/rt_nhops.c	Sun Aug 23 18:28:17 2015	(r287067)
+++ projects/routing/sys/net/rt_nhops.c	Sun Aug 23 18:28:50 2015	(r287068)
@@ -117,6 +117,8 @@ int fwd_destroy_fib(struct fwd_module *f
 
 static inline uint16_t fib_rte_to_nh_flags(int rt_flags);
 #ifdef INET
+static void rib4_rte_to_nh_extended(struct rtentry *rte, struct in_addr dst,
+    struct rt4_extended *prt4);
 static void fib4_rte_to_nh_extended(struct rtentry *rte, struct in_addr dst,
     struct nhop4_extended *pnh4);
 static void fib4_rte_to_nh_basic(struct rtentry *rte, struct in_addr dst,
@@ -452,6 +454,39 @@ fib4_rte_to_nh_extended(struct rtentry *
 	pnh4->nh_src = IA_SIN(ia)->sin_addr;
 }
 
+static void
+rib4_rte_to_nh_extended(struct rtentry *rte, struct in_addr dst,
+    struct rt4_extended *prt4)
+{
+	struct sockaddr_in *gw;
+	struct in_ifaddr *ia;
+
+	/* Do explicit nexthop zero unless we're copying it */
+	memset(prt4, 0, sizeof(*prt4));
+
+    	gw = ((struct sockaddr_in *)rt_key(rte));
+	prt4->rt_addr = gw->sin_addr;
+    	gw = ((struct sockaddr_in *)rt_mask(rte));
+	prt4->rt_mask.s_addr = (gw != NULL) ?
+	    gw->sin_addr.s_addr : INADDR_BROADCAST;
+
+	if (rte->rt_flags & RTF_GATEWAY) {
+		gw = (struct sockaddr_in *)rte->rt_gateway;
+		prt4->rt_gateway = gw->sin_addr;
+	} else
+		prt4->rt_gateway = dst;
+
+	prt4->rt_lifp = rte->rt_ifp;
+	prt4->rt_aifp = rte->rt_ifa->ifa_ifp;
+	prt4->rt_flags = rte->rt_flags;
+	prt4->rt_mtu = min(rte->rt_mtu, rte->rt_ifp->if_mtu);
+
+	prt4->rt_nhop = 0; /* XXX: fill real nexthop */
+
+	ia = ifatoia(rte->rt_ifa);
+	prt4->rt_src = IA_SIN(ia)->sin_addr;
+}
+
 /*
  * Performs IPv4 route table lookup on @dst. Returns 0 on success.
  * Stores nexthop info provided @pnh4 structure.
@@ -597,6 +632,50 @@ fib4_source_to_sa_ext(const struct nhopu
 	sin->sin_addr = pnhu->u.nh4.nh_src;
 }
 
+int
+rib4_lookup_nh_ext(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
+    uint32_t flags, struct rt4_extended *prt4)
+{
+	struct radix_node_head *rnh;
+	struct radix_node *rn;
+	struct sockaddr_in sin;
+	struct rtentry *rte;
+
+	KASSERT((fibnum < rt_numfibs), ("rib4_lookup_nh_ext: bad fibnum"));
+	rnh = rt_tables_get_rnh(fibnum, AF_INET);
+	if (rnh == NULL)
+		return (ENOENT);
+
+	/* Prepare lookup key */
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_len = sizeof(struct sockaddr_in);
+	sin.sin_addr = dst;
+
+	RADIX_NODE_HEAD_RLOCK(rnh);
+	rn = rnh->rnh_matchaddr((void *)&sin, rnh);
+	if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
+		rte = RNTORT(rn);
+		/* Ensure route & ifp is UP */
+		if (RT_LINK_IS_UP(rte->rt_ifp)) {
+			rib4_rte_to_nh_extended(rte, dst, prt4);
+			if ((flags & NHOP_LOOKUP_REF) != 0) {
+				/* TODO: Do lwref on egress ifp's */
+			}
+			RADIX_NODE_HEAD_RUNLOCK(rnh);
+			return (0);
+		}
+	}
+	RADIX_NODE_HEAD_RUNLOCK(rnh);
+
+	return (ENOENT);
+}
+
+void
+rib4_free_nh_ext(uint32_t fibnum, struct rt4_extended *prt4)
+{
+
+}
+
 #endif
 
 #ifdef INET6
@@ -907,6 +986,36 @@ fib6_lla_to_nh_extended(struct in6_addr 
 }
 
 static int
+rib6_lla_to_nh_extended(struct in6_addr *dst, uint32_t scopeid,
+    struct rt6_extended *prt6)
+{
+	struct ifnet *ifp;
+
+	ifp = ifnet_byindex_locked(scopeid);
+	if (ifp == NULL)
+		return (ENOENT);
+
+	/* Do explicit nexthop zero unless we're copying it */
+	memset(prt6, 0, sizeof(*prt6));
+
+	prt6->rt_addr.s6_addr16[0] = htons(0xFE80);
+	prt6->rt_mask = 64; /* XXX check RFC */
+
+	prt6->rt_aifp = ifp;
+	prt6->rt_lifp = ifp;
+	/* Check id this is for-us address */
+	if (in6_ifawithifp_lla(ifp, dst)) {
+		if ((ifp = V_loif) != NULL)
+			prt6->rt_lifp = ifp;
+	}
+
+	prt6->rt_mtu = IN6_LINKMTU(ifp);
+	/* No flags set */
+
+	return (0);
+}
+
+static int
 fib6_lla_to_nh(struct in6_addr *dst, uint32_t scopeid,
     struct nhop_prepend *nh, struct ifnet **lifp)
 {
@@ -988,6 +1097,37 @@ fib6_rte_to_nh_extended(struct rtentry *
 	ia = ifatoia6(rte->rt_ifa);
 }
 
+#define ipv6_masklen(x)		bitcount32((x).__u6_addr.__u6_addr32[0]) + \
+				bitcount32((x).__u6_addr.__u6_addr32[1]) + \
+				bitcount32((x).__u6_addr.__u6_addr32[2]) + \
+				bitcount32((x).__u6_addr.__u6_addr32[3])
+static void
+rib6_rte_to_nh_extended(struct rtentry *rte, struct in6_addr *dst,
+    struct rt6_extended *prt6)
+{
+	struct sockaddr_in6 *gw;
+
+	/* Do explicit nexthop zero unless we're copying it */
+	memset(prt6, 0, sizeof(*prt6));
+
+    	gw = ((struct sockaddr_in6 *)rt_key(rte));
+	prt6->rt_addr = gw->sin6_addr;
+    	gw = ((struct sockaddr_in6 *)rt_mask(rte));
+	prt6->rt_mask = (gw != NULL) ? ipv6_masklen(gw->sin6_addr) : 128;
+
+	if (rte->rt_flags & RTF_GATEWAY) {
+		gw = (struct sockaddr_in6 *)rte->rt_gateway;
+		prt6->rt_gateway = gw->sin6_addr;
+		in6_clearscope(&prt6->rt_gateway);
+	} else
+		prt6->rt_gateway = *dst;
+
+	prt6->rt_lifp = rte->rt_ifp;
+	prt6->rt_aifp = ifnet_byindex(fib6_get_ifa(rte));
+	prt6->rt_flags = fib_rte_to_nh_flags(rte->rt_flags);
+	prt6->rt_mtu = min(rte->rt_mtu, IN6_LINKMTU(rte->rt_ifp));
+}
+
 int
 fib6_lookup_nh_ifp(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
     uint32_t flowid, struct nhop6_basic *pnh6)
@@ -999,6 +1139,7 @@ fib6_lookup_nh_ifp(uint32_t fibnum, stru
 
 	if (IN6_IS_SCOPE_LINKLOCAL(dst)) {
 		/* Do not lookup link-local addresses in rtable */
+		/* XXX: Check if dst is local */
 		return (fib6_lla_to_nh_basic(dst, scopeid, pnh6));
 	}
 
@@ -1133,6 +1274,59 @@ fib6_free_nh_ext(uint32_t fibnum, struct
 
 }
 
+int
+rib6_lookup_nh_ext(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
+    uint32_t flowid, uint32_t flags, struct rt6_extended *prt6)
+{
+	struct radix_node_head *rnh;
+	struct radix_node *rn;
+	struct sockaddr_in6 sin6;
+	struct rtentry *rte;
+
+	if (IN6_IS_SCOPE_LINKLOCAL(dst)) {
+		/* Do not lookup link-local addresses in rtable */
+		/* XXX: Do lwref on egress ifp */
+		return (rib6_lla_to_nh_extended(dst, scopeid, prt6));
+	}
+
+	KASSERT((fibnum < rt_numfibs), ("rib6_lookup_nh_ext: bad fibnum"));
+	rnh = rt_tables_get_rnh(fibnum, AF_INET6);
+	if (rnh == NULL)
+		return (ENOENT);
+
+	/* Prepare lookup key */
+	memset(&sin6, 0, sizeof(sin6));
+	sin6.sin6_len = sizeof(struct sockaddr_in6);
+	sin6.sin6_addr = *dst;
+	sin6.sin6_scope_id = scopeid;
+	sa6_embedscope(&sin6, 0);
+
+	RADIX_NODE_HEAD_RLOCK(rnh);
+	rn = rnh->rnh_matchaddr((void *)&sin6, rnh);
+	if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
+		rte = RNTORT(rn);
+		/* Ensure route & ifp is UP */
+		if (RT_LINK_IS_UP(rte->rt_ifp)) {
+			rib6_rte_to_nh_extended(rte, dst, prt6);
+			if ((flags & NHOP_LOOKUP_REF) != 0) {
+				/* TODO: Do lwref on egress ifp's */
+			}
+			RADIX_NODE_HEAD_RUNLOCK(rnh);
+
+			return (0);
+		}
+	}
+	RADIX_NODE_HEAD_RUNLOCK(rnh);
+
+	return (ENOENT);
+}
+
+void
+rib6_free_nh_ext(uint32_t fibnum, struct nhop6_extended *prt6)
+{
+
+}
+
 #endif
 
 void

Modified: projects/routing/sys/net/rt_nhops.h
==============================================================================
--- projects/routing/sys/net/rt_nhops.h	Sun Aug 23 18:28:17 2015	(r287067)
+++ projects/routing/sys/net/rt_nhops.h	Sun Aug 23 18:28:50 2015	(r287068)
@@ -180,23 +180,28 @@ struct nhop6_extended {
 };
 
 /* route info used for control plane purposes */
-struct rt4_basic {
+struct rt4_extended {
 	struct in_addr	rt_addr;	/* route prefix */
 	struct in_addr	rt_gateway;	/* GW used */
+	struct ifnet	*rt_lifp;	/* logical interface */
+	struct ifnet	*rt_aifp;	/* address interface */
 	int		rt_flags;	/* Copy of rte flags */
 	uint16_t	rt_mtu;
 	uint16_t	rt_nhop;	/* nexthop id (might bi mpath) */
 	struct in_addr	rt_mask;	/* route mask */
+	struct in_addr	rt_src;
 	uint16_t	spare[2];
 };
 
-struct rt6_basic {
+struct rt6_extended {
 	struct in6_addr	rt_addr;
 	struct in6_addr	rt_gateway;
+	struct ifnet	*rt_lifp;	/* logical interface */
+	struct ifnet	*rt_aifp;	/* address interface */
 	int		rt_flags;
 	uint16_t	rt_mtu;
 	uint16_t	rt_nhop;
-	uint8_t		rt_mask;
+	uint8_t		rt_mask;	/*Hopefully, no more non-config masks */
 	uint8_t		spare[7];
 };
 
@@ -232,6 +237,9 @@ void fib4_free_nh_ext(uint32_t fibnum, s
 #define	NHOP_LOOKUP_REF	0x01
 void fib4_source_to_sa_ext(const struct nhopu_extended *pnhu,
     struct sockaddr_in *sin);
+int rib4_lookup_nh_ext(uint32_t fibnum, struct in_addr dst, uint32_t flowid,
+    uint32_t flags, struct rt4_extended *prt4);
+void rib4_free_nh_ext(uint32_t fibnum, struct rt4_extended *prt4);
 
 
 int fib6_lookup_nh_ifp(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
@@ -242,6 +250,9 @@ int fib6_lookup_nh_ext(uint32_t fibnum, 
     uint32_t scopeid, uint32_t flowid, uint32_t flags,
     struct nhop6_extended *pnh6);
 void fib6_free_nh_ext(uint32_t fibnum, struct nhop6_extended *pnh6);
+int rib6_lookup_nh_ext(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
+    uint32_t flowid, uint32_t flags, struct rt6_extended *prt6);
+void rib6_free_nh_ext(uint32_t fibnum, struct nhop6_extended *prt6);
 
 void fib_free_nh_ext(uint32_t fibnum, struct nhopu_extended *pnhu);
 

Modified: projects/routing/sys/netgraph/netflow/netflow.c
==============================================================================
--- projects/routing/sys/netgraph/netflow/netflow.c	Sun Aug 23 18:28:17 2015	(r287067)
+++ projects/routing/sys/netgraph/netflow/netflow.c	Sun Aug 23 18:28:50 2015	(r287068)
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
 #include <net/if.h>
 #include <net/if_var.h>
 #include <net/route.h>
-#include <net/route_internal.h>
 #include <net/ethernet.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
@@ -53,6 +52,7 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip6.h>
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
+#include <net/rt_nhops.h>
 
 #include <netgraph/ng_message.h>
 #include <netgraph/netgraph.h>
@@ -307,8 +307,7 @@ hash_insert(priv_p priv, struct flow_has
 	int plen, uint8_t flags, uint8_t tcp_flags)
 {
 	struct flow_entry *fle;
-	struct sockaddr_in sin;
-	struct rtentry *rt;
+	struct rt4_extended rt4;
 
 	mtx_assert(&hsh->mtx, MA_OWNED);
 
@@ -335,46 +334,20 @@ hash_insert(priv_p priv, struct flow_has
 	 * fill in out_ifx, dst_mask, nexthop, and dst_as in future releases.
 	 */
 	if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0) {
-		bzero(&sin, sizeof(sin));
-		sin.sin_len = sizeof(struct sockaddr_in);
-		sin.sin_family = AF_INET;
-		sin.sin_addr = fle->f.r.r_dst;
-		rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, r->fib);
-		if (rt != NULL) {
-			fle->f.fle_o_ifx = rt->rt_ifp->if_index;
-
-			if (rt->rt_flags & RTF_GATEWAY &&
-			    rt->rt_gateway->sa_family == AF_INET)
-				fle->f.next_hop =
-				    ((struct sockaddr_in *)(rt->rt_gateway))->sin_addr;
-
-			if (rt_mask(rt))
-				fle->f.dst_mask =
-				    bitcount32(((struct sockaddr_in *)rt_mask(rt))->sin_addr.s_addr);
-			else if (rt->rt_flags & RTF_HOST)
-				/* Give up. We can't determine mask :( */
-				fle->f.dst_mask = 32;
-
-			RTFREE_LOCKED(rt);
+		if (rib4_lookup_nh_ext(r->fib, fle->f.r.r_dst, 0, 0, &rt4) != 0) {
+			fle->f.fle_o_ifx = rt4.rt_lifp->if_index;
+			if (rt4.rt_flags & RTF_GATEWAY)
+				fle->f.next_hop = rt4.rt_gateway;
+			fle->f.dst_mask = bitcount32(rt4.rt_mask.s_addr);
 		}
 	}
 
 	/* Do route lookup on source address, to fill in src_mask. */
 	if ((flags & NG_NETFLOW_CONF_NOSRCLOOKUP) == 0) {
-		bzero(&sin, sizeof(sin));
-		sin.sin_len = sizeof(struct sockaddr_in);
-		sin.sin_family = AF_INET;
-		sin.sin_addr = fle->f.r.r_src;
-		rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, r->fib);
-		if (rt != NULL) {
-			if (rt_mask(rt))
-				fle->f.src_mask =
-				    bitcount32(((struct sockaddr_in *)rt_mask(rt))->sin_addr.s_addr);
-			else if (rt->rt_flags & RTF_HOST)
-				/* Give up. We can't determine mask :( */
-				fle->f.src_mask = 32;
-
-			RTFREE_LOCKED(rt);
+		if (rib4_lookup_nh_ext(r->fib, fle->f.r.r_src, 0, 0, &rt4) != 0) {
+			if (rt4.rt_flags & RTF_GATEWAY)
+				fle->f.next_hop = rt4.rt_gateway;
+			fle->f.src_mask = bitcount32(rt4.rt_mask.s_addr);
 		}
 	}
 
@@ -396,9 +369,7 @@ hash6_insert(priv_p priv, struct flow_ha
 	int plen, uint8_t flags, uint8_t tcp_flags)
 {
 	struct flow6_entry *fle6;
-	struct sockaddr_in6 *src, *dst;
-	struct rtentry *rt;
-	struct route_in6 rin6;
+	struct rt6_extended rt6;
 
 	mtx_assert(&hsh6->mtx, MA_OWNED);
 
@@ -426,51 +397,18 @@ hash6_insert(priv_p priv, struct flow_ha
 	 * fill in out_ifx, dst_mask, nexthop, and dst_as in future releases.
 	 */
 	if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0) {
-		bzero(&rin6, sizeof(struct route_in6));
-		dst = (struct sockaddr_in6 *)&rin6.ro_dst;
-		dst->sin6_len = sizeof(struct sockaddr_in6);
-		dst->sin6_family = AF_INET6;
-		dst->sin6_addr = r->dst.r_dst6;
-
-		rin6.ro_rt = rtalloc1_fib((struct sockaddr *)dst, 0, 0, r->fib);
-
-		if (rin6.ro_rt != NULL) {
-			rt = rin6.ro_rt;
-			fle6->f.fle_o_ifx = rt->rt_ifp->if_index;
-
-			if (rt->rt_flags & RTF_GATEWAY &&
-			    rt->rt_gateway->sa_family == AF_INET6)
-				fle6->f.n.next_hop6 =
-				    ((struct sockaddr_in6 *)(rt->rt_gateway))->sin6_addr;
-
-			if (rt_mask(rt))
-				fle6->f.dst_mask = RT_MASK6(rt);
-			else
-				fle6->f.dst_mask = 128;
-
-			RTFREE_LOCKED(rt);
+		if (rib6_lookup_nh_ext(r->fib, &r->dst.r_dst6, 0, 0, 0, &rt6) == 0) {
+			fle6->f.fle_o_ifx = rt6.rt_lifp->if_index;
+			if ((rt6.rt_flags & RTF_GATEWAY) != 0)
+				fle6->f.n.next_hop6 = rt6.rt_gateway;
+			fle6->f.dst_mask = rt6.rt_mask;
 		}
 	}
 
 	if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0) {
 		/* Do route lookup on source address, to fill in src_mask. */
-		bzero(&rin6, sizeof(struct route_in6));
-		src = (struct sockaddr_in6 *)&rin6.ro_dst;
-		src->sin6_len = sizeof(struct sockaddr_in6);
-		src->sin6_family = AF_INET6;
-		src->sin6_addr = r->src.r_src6;
-
-		rin6.ro_rt = rtalloc1_fib((struct sockaddr *)src, 0, 0, r->fib);
-
-		if (rin6.ro_rt != NULL) {
-			rt = rin6.ro_rt;
-
-			if (rt_mask(rt))
-				fle6->f.src_mask = RT_MASK6(rt);
-			else
-				fle6->f.src_mask = 128;
-
-			RTFREE_LOCKED(rt);
+		if (rib6_lookup_nh_ext(r->fib, &r->src.r_src6, 0, 0, 0, &rt6) == 0) {
+			fle6->f.dst_mask = rt6.rt_mask;
 		}
 	}
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508231828.t7NISocn047526>