Add new rib4/rib6 series of functions returning per-rte info
packed on stack. Convert ng_netflow to use new routing API.
This commit is contained in:
parent
930d2a42c9
commit
043d919e33
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/routing/; revision=274212
@ -117,6 +117,8 @@ int fwd_destroy_fib(struct fwd_module *fm, u_int fib);
|
||||
|
||||
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 *rte, struct in_addr dst,
|
||||
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.
|
||||
@ -588,6 +623,50 @@ fib4_free_nh_ext(uint32_t fibnum, struct nhop4_extended *pnh4)
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
@ -897,6 +976,36 @@ fib6_lla_to_nh_extended(struct in6_addr *dst, uint32_t scopeid,
|
||||
return (0);
|
||||
}
|
||||
|
||||
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)
|
||||
@ -979,6 +1088,37 @@ fib6_rte_to_nh_extended(struct rtentry *rte, struct in6_addr *dst,
|
||||
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)
|
||||
@ -990,6 +1130,7 @@ fib6_lookup_nh_ifp(uint32_t fibnum, struct in6_addr *dst, uint32_t scopeid,
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@ -1124,6 +1265,59 @@ 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)
|
||||
{
|
||||
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
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
@ -230,6 +235,9 @@ int fib4_lookup_nh_ext(uint32_t fibnum, struct in_addr dst,
|
||||
uint32_t flowid, uint32_t flags, struct nhop4_extended *pnh4);
|
||||
void fib4_free_nh_ext(uint32_t fibnum, struct nhop4_extended *pnh4);
|
||||
#define NHOP_LOOKUP_REF 0x01
|
||||
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,
|
||||
@ -240,6 +248,9 @@ int fib6_lookup_nh_ext(uint32_t fibnum, struct in6_addr *dst,
|
||||
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);
|
||||
|
||||
|
@ -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_hash_entry *hsh, struct flow_rec *r,
|
||||
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_hash_entry *hsh, struct flow_rec *r,
|
||||
* 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_hash_entry *hsh6, struct flow6_rec *r,
|
||||
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_hash_entry *hsh6, struct flow6_rec *r,
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user