Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102771460
D23051.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
25 KB
Referenced Files
None
Subscribers
None
D23051.diff
View Options
Index: sys/net/radix.h
===================================================================
--- sys/net/radix.h
+++ sys/net/radix.h
@@ -65,7 +65,8 @@
struct radix_node *rn_Dupedkey;
} rn_leaf;
struct { /* node only data: */
- int rn_Off; /* where to start compare */
+ int16_t rn_Off; /* where to start compare */
+ int16_t rn_Salen; /* total length of sockaddr */
struct radix_node *rn_L;/* progeny */
struct radix_node *rn_R;/* progeny */
} rn_node;
@@ -81,6 +82,7 @@
#define rn_key rn_u.rn_leaf.rn_Key
#define rn_mask rn_u.rn_leaf.rn_Mask
#define rn_offset rn_u.rn_node.rn_Off
+#define rn_salen rn_u.rn_node.rn_Salen
#define rn_left rn_u.rn_node.rn_L
#define rn_right rn_u.rn_node.rn_R
@@ -106,7 +108,7 @@
struct radix_head;
typedef int walktree_f_t(struct radix_node *, void *);
-typedef struct radix_node *rn_matchaddr_f_t(void *v,
+typedef struct radix_node *rn_matchaddr_f_t(const void *v,
struct radix_head *head);
typedef struct radix_node *rn_addaddr_f_t(void *v, void *mask,
struct radix_head *head, struct radix_node nodes[]);
@@ -175,13 +177,15 @@
int rn_inithead(void **, int);
int rn_detachhead(void **);
+void rn_setkeylen(struct radix_head *, int keylen);
int rn_refines(void *, void *);
struct radix_node *rn_addroute(void *, void *, struct radix_head *,
struct radix_node[2]);
struct radix_node *rn_delete(void *, void *, struct radix_head *);
struct radix_node *rn_lookup (void *v_arg, void *m_arg,
struct radix_head *head);
-struct radix_node *rn_match(void *, struct radix_head *);
+struct radix_node *rn_match(const void *, struct radix_head *);
+struct radix_node *rn_match_fixed(const void *, struct radix_head *);
int rn_walktree_from(struct radix_head *h, void *a, void *m,
walktree_f_t *f, void *w);
int rn_walktree(struct radix_head *, walktree_f_t *, void *);
Index: sys/net/radix.c
===================================================================
--- sys/net/radix.c
+++ sys/net/radix.c
@@ -63,7 +63,7 @@
struct radix_node [2]),
*rn_newpair(void *, int, struct radix_node[2]),
*rn_search(void *, struct radix_node *),
- *rn_search_m(void *, struct radix_node *, void *);
+ *rn_search_m(const void *, struct radix_node *, void *);
static struct radix_node *rn_addmask(void *, struct radix_mask_head *, int,int);
static void rn_detachhead_internal(struct radix_head *);
@@ -83,8 +83,8 @@
static struct radix_mask *
rn_new_radix_mask(struct radix_node *tt,
struct radix_mask *next);
-static int rn_satisfies_leaf(char *trial, struct radix_node *leaf,
- int skip);
+static int rn_satisfies_leaf(const char *trial, struct radix_node *leaf,
+ int skip, int salen);
/*
* The data structure for the keys is a radix tree with one way
@@ -166,10 +166,10 @@
* XXX note this function is used only once.
*/
static struct radix_node *
-rn_search_m(void *v_arg, struct radix_node *head, void *m_arg)
+rn_search_m(const void *v_arg, struct radix_node *head, void *m_arg)
{
struct radix_node *x;
- caddr_t v = v_arg, m = m_arg;
+ c_caddr_t v = v_arg, m = m_arg;
for (x = head; x->rn_bit >= 0;) {
if ((x->rn_bmask & m[x->rn_offset]) &&
@@ -255,11 +255,12 @@
}
static int
-rn_satisfies_leaf(char *trial, struct radix_node *leaf, int skip)
+rn_satisfies_leaf(const char *trial, struct radix_node *leaf, int skip,
+ int salen)
{
- char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask;
- char *cplim;
- int length = min(LEN(cp), LEN(cp2));
+ const char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask;
+ const char *cplim;
+ int length = min(salen, LEN(cp2) - skip);
if (cp3 == NULL)
cp3 = rn_ones;
@@ -275,15 +276,15 @@
/*
* Search for longest-prefix match in given @head
*/
-struct radix_node *
-rn_match(void *v_arg, struct radix_head *head)
+static inline struct radix_node *
+rn_match_internal(const void *v_arg, struct radix_head *head, int salen)
{
- caddr_t v = v_arg;
+ c_caddr_t v = v_arg;
struct radix_node *t = head->rnh_treetop, *x;
- caddr_t cp = v, cp2;
- caddr_t cplim;
+ c_caddr_t cp = v, cp2;
+ c_caddr_t cplim;
struct radix_node *saved_t, *top = t;
- int off = t->rn_offset, vlen = LEN(cp), matched_off;
+ int off = t->rn_offset, vlen = salen, matched_off;
int test, b, rn_bit;
/*
@@ -344,7 +345,7 @@
if (t->rn_flags & RNF_NORMAL) {
if (rn_bit <= t->rn_bit)
return (t);
- } else if (rn_satisfies_leaf(v, t, matched_off))
+ } else if (rn_satisfies_leaf(v, t, matched_off, salen))
return (t);
t = saved_t;
/* start searching up the tree */
@@ -367,7 +368,7 @@
x = rn_search_m(v, t, m->rm_mask);
while (x && x->rn_mask != m->rm_mask)
x = x->rn_dupedkey;
- if (x && rn_satisfies_leaf(v, x, off))
+ if (x && rn_satisfies_leaf(v, x, off, salen))
return (x);
}
m = m->rm_mklist;
@@ -376,6 +377,21 @@
return (0);
}
+struct radix_node *
+rn_match(const void *v_arg, struct radix_head *head)
+{
+
+ return (rn_match_internal(v_arg, head, LEN(v_arg)));
+}
+
+struct radix_node *
+rn_match_fixed(const void *v_arg, struct radix_head *head)
+{
+
+ return (rn_match_internal(v_arg, head, head->rnh_treetop->rn_salen));
+}
+
+
#ifdef RN_DEBUG
int rn_nodenum;
struct radix_node *rn_clist;
@@ -1111,7 +1127,8 @@
* bits starting at 'off'.
*/
void
-rn_inithead_internal(struct radix_head *rh, struct radix_node *base_nodes, int off)
+rn_inithead_internal(struct radix_head *rh, struct radix_node *base_nodes,
+ int off)
{
struct radix_node *t, *tt, *ttt;
@@ -1179,6 +1196,18 @@
return (1);
}
+
+
+/* Sets lookup _key_ length for the constant-length keys */
+void
+rn_setkeylen(struct radix_head *rh, int keylen)
+{
+ struct radix_node *t;
+
+ t = rh->rnh_treetop;
+ t->rn_salen = t->rn_offset + keylen;
+}
+
static int
rn_freeentry(struct radix_node *rn, void *arg)
Index: sys/net/route.h
===================================================================
--- sys/net/route.h
+++ sys/net/route.h
@@ -455,7 +455,7 @@
void rt_newmaddrmsg(int, struct ifmultiaddr *);
int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *);
void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *);
-struct rib_head *rt_table_init(int, int, u_int);
+struct rib_head *rt_table_init(int, int, int, u_int);
void rt_table_destroy(struct rib_head *);
u_int rt_tables_get_gen(int table, int fam);
Index: sys/net/route.c
===================================================================
--- sys/net/route.c
+++ sys/net/route.c
@@ -348,7 +348,7 @@
#endif
struct rib_head *
-rt_table_init(int offset, int family, u_int fibnum)
+rt_table_init(int offset, int keylen, int family, u_int fibnum)
{
struct rib_head *rh;
@@ -357,6 +357,7 @@
/* TODO: These details should be hidded inside radix.c */
/* Init masks tree */
rn_inithead_internal(&rh->head, rh->rnh_nodes, offset);
+ rn_setkeylen(&rh->head, keylen);
rn_inithead_internal(&rh->rmhead.head, rh->rmhead.mask_nodes, 0);
rh->head.rnh_masks = &rh->rmhead;
@@ -375,7 +376,7 @@
/* Finally, set base callbacks */
rh->rnh_addaddr = rn_addroute;
rh->rnh_deladdr = rn_delete;
- rh->rnh_matchaddr = rn_match;
+ rh->rnh_matchaddr = rn_match_fixed;
rh->rnh_lookup = rn_lookup;
rh->rnh_walktree = rn_walktree;
rh->rnh_walktree_from = rn_walktree_from;
Index: sys/netinet/in_fib.c
===================================================================
--- sys/netinet/in_fib.c
+++ sys/netinet/in_fib.c
@@ -66,6 +66,7 @@
uint32_t flags, struct nhop4_extended *pnh4);
#define RNTORT(p) ((struct rtentry *)(p))
+#define FIB4_LOOKUP_KEY(a) (void *)(__containerof(a, struct sockaddr_in, sin_addr))
static void
fib4_rte_to_nh_basic(struct rtentry *rte, struct in_addr dst,
@@ -134,7 +135,7 @@
RIB_RLOCK_TRACKER;
struct rib_head *rh;
struct radix_node *rn;
- struct sockaddr_in sin;
+ struct in_addr addr;
struct rtentry *rte;
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_basic: bad fibnum"));
@@ -143,12 +144,10 @@
return (ENOENT);
/* Prepare lookup key */
- memset(&sin, 0, sizeof(sin));
- sin.sin_len = sizeof(struct sockaddr_in);
- sin.sin_addr = dst;
+ addr = dst;
RIB_RLOCK(rh);
- rn = rh->rnh_matchaddr((void *)&sin, &rh->head);
+ rn = rh->rnh_matchaddr(FIB4_LOOKUP_KEY(&addr), &rh->head);
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
rte = RNTORT(rn);
/* Ensure route & ifp is UP */
@@ -183,7 +182,7 @@
RIB_RLOCK_TRACKER;
struct rib_head *rh;
struct radix_node *rn;
- struct sockaddr_in sin;
+ struct in_addr addr;
struct rtentry *rte;
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_nh_ext: bad fibnum"));
@@ -192,12 +191,10 @@
return (ENOENT);
/* Prepare lookup key */
- memset(&sin, 0, sizeof(sin));
- sin.sin_len = sizeof(struct sockaddr_in);
- sin.sin_addr = dst;
+ addr = dst;
RIB_RLOCK(rh);
- rn = rh->rnh_matchaddr((void *)&sin, &rh->head);
+ rn = rh->rnh_matchaddr(FIB4_LOOKUP_KEY(&addr), &rh->head);
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
rte = RNTORT(rn);
#ifdef RADIX_MPATH
Index: sys/netinet/in_rmx.c
===================================================================
--- sys/netinet/in_rmx.c
+++ sys/netinet/in_rmx.c
@@ -120,7 +120,7 @@
{
struct rib_head *rh;
- rh = rt_table_init(32, AF_INET, fibnum);
+ rh = rt_table_init(32, sizeof(struct in_addr), AF_INET, fibnum);
if (rh == NULL)
return (0);
Index: sys/netinet6/in6_fib.c
===================================================================
--- sys/netinet6/in6_fib.c
+++ sys/netinet6/in6_fib.c
@@ -75,6 +75,8 @@
static struct ifnet *fib6_get_ifaifp(struct rtentry *rte);
#define RNTORT(p) ((struct rtentry *)(p))
+#define FIB6_LOOKUP_KEY(a) (void *)(__containerof(a, struct sockaddr_in6, sin6_addr))
+
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
CHK_STRUCT_ROUTE_COMPAT(struct route_in6, ro_dst);
@@ -179,7 +181,7 @@
RIB_RLOCK_TRACKER;
struct rib_head *rh;
struct radix_node *rn;
- struct sockaddr_in6 sin6;
+ struct in6_addr addr6;
struct rtentry *rte;
KASSERT((fibnum < rt_numfibs), ("fib6_lookup_nh_basic: bad fibnum"));
@@ -188,20 +190,18 @@
return (ENOENT);
/* Prepare lookup key */
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_addr = *dst;
- sin6.sin6_len = sizeof(struct sockaddr_in6);
+ addr6 = *dst;
/* Assume scopeid is valid and embed it directly */
if (IN6_IS_SCOPE_LINKLOCAL(dst))
- sin6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff);
+ addr6.s6_addr16[1] = htons(scopeid & 0xffff);
RIB_RLOCK(rh);
- rn = rh->rnh_matchaddr((void *)&sin6, &rh->head);
+ rn = rh->rnh_matchaddr(FIB6_LOOKUP_KEY(&addr6), &rh->head);
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)) {
- fib6_rte_to_nh_basic(rte, &sin6.sin6_addr, flags, pnh6);
+ fib6_rte_to_nh_basic(rte, &addr6, flags, pnh6);
RIB_RUNLOCK(rh);
return (0);
}
@@ -229,7 +229,7 @@
RIB_RLOCK_TRACKER;
struct rib_head *rh;
struct radix_node *rn;
- struct sockaddr_in6 sin6;
+ struct in6_addr addr6;
struct rtentry *rte;
KASSERT((fibnum < rt_numfibs), ("fib6_lookup_nh_ext: bad fibnum"));
@@ -238,15 +238,13 @@
return (ENOENT);
/* Prepare lookup key */
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_len = sizeof(struct sockaddr_in6);
- sin6.sin6_addr = *dst;
+ addr6 = *dst;
/* Assume scopeid is valid and embed it directly */
if (IN6_IS_SCOPE_LINKLOCAL(dst))
- sin6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff);
+ addr6.s6_addr16[1] = htons(scopeid & 0xffff);
RIB_RLOCK(rh);
- rn = rh->rnh_matchaddr((void *)&sin6, &rh->head);
+ rn = rh->rnh_matchaddr(FIB6_LOOKUP_KEY(&addr6), &rh->head);
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
rte = RNTORT(rn);
#ifdef RADIX_MPATH
@@ -258,8 +256,7 @@
#endif
/* Ensure route & ifp is UP */
if (RT_LINK_IS_UP(rte->rt_ifp)) {
- fib6_rte_to_nh_extended(rte, &sin6.sin6_addr, flags,
- pnh6);
+ fib6_rte_to_nh_extended(rte, &addr6, flags, pnh6);
if ((flags & NHR_REF) != 0) {
/* TODO: Do lwref on egress ifp's */
}
Index: sys/netinet6/in6_rmx.c
===================================================================
--- sys/netinet6/in6_rmx.c
+++ sys/netinet6/in6_rmx.c
@@ -162,7 +162,7 @@
struct rib_head *rh;
rh = rt_table_init(offsetof(struct sockaddr_in6, sin6_addr) << 3,
- AF_INET6, fibnum);
+ sizeof(struct in6_addr), AF_INET6, fibnum);
if (rh == NULL)
return (0);
Index: tests/sys/netinet/Makefile
===================================================================
--- tests/sys/netinet/Makefile
+++ tests/sys/netinet/Makefile
@@ -9,7 +9,7 @@
so_reuseport_lb_test \
socket_afinet
-ATF_TESTS_SH= fibs_test redirect divert forward output
+ATF_TESTS_SH= fibs_test redirect divert forward output lpm
PROGS= udp_dontroute tcp_user_cookie
Index: tests/sys/netinet/lpm.sh
===================================================================
--- /dev/null
+++ tests/sys/netinet/lpm.sh
@@ -0,0 +1,179 @@
+#!/usr/bin/env atf-sh
+#-
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2020 Alexander V. Chernikov
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+. $(atf_get_srcdir)/../common/vnet.subr
+
+setup_networking()
+{
+ jname="$1"
+ lo_dst="$2"
+ epair0="$3"
+ epair1="$4"
+
+ vnet_mkjail ${jname}a ${epair0}a ${epair1}a
+ # Setup transit IPv4 networks
+ jexec ${jname}a ifconfig ${epair0}a up
+ jexec ${jname}a ifconfig ${epair0}a inet 203.0.113.1/30
+ jexec ${jname}a ifconfig ${epair1}a up
+ jexec ${jname}a ifconfig ${epair1}a inet 203.0.113.5/30
+
+ vnet_mkjail ${jname}b ${epair0}b ${epair1}b ${lo_dst}
+ jexec ${jname}b ifconfig ${epair0}b up
+ jexec ${jname}b ifconfig ${epair0}b inet 203.0.113.2/30
+ jexec ${jname}b ifconfig ${epair1}b up
+ jexec ${jname}b ifconfig ${epair1}b inet 203.0.113.6/30
+ jexec ${jname}b ifconfig ${lo_dst} up
+
+}
+
+atf_test_case "lpm_test1_success" "cleanup"
+lpm_test1_success_head()
+{
+
+ atf_set descr 'Test IPv4 LPM for /30 and /31'
+ atf_set require.user root
+}
+
+lpm_test1_success_body()
+{
+
+ vnet_init
+
+ jname="v4t-lpm_test1_success"
+
+ lo_dst=$(vnet_mkloopback)
+ epair0=$(vnet_mkepair)
+ epair1=$(vnet_mkepair)
+
+ setup_networking ${jname} ${lo_dst} ${epair0} ${epair1}
+
+ jexec ${jname}b ifconfig ${lo_dst} inet 198.51.100.0/32
+ jexec ${jname}b ifconfig ${lo_dst} alias 198.51.100.2/32
+
+ # Add routes
+ # A -> towards B via epair0a
+ jexec ${jname}a route add -4 -net 198.51.100.0/30 203.0.113.2
+ # A -> towards B via epair1a
+ jexec ${jname}a route add -4 -net 198.51.100.0/31 203.0.113.6
+
+ count=20
+ valid_message="${count} packets transmitted, ${count} packets received"
+
+ # Check that 198.51.100.0 goes via epair1
+ atf_check -o match:"${valid_message}" jexec ${jname}a ping -f -nc${count} 198.51.100.0
+ pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'`
+ pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'`
+ if [ ${pkt_1} -le ${count} ]; then
+ echo "LPM failure: 1: ${pkt_0} 2: ${pkt_1} (should be ${count})"
+ exit 1
+ fi
+
+ # Check that 198.51.100.2 goes via epair0
+ atf_check -o match:"${valid_message}" jexec ${jname}a ping -f -nc${count} 198.51.100.2
+ pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'`
+ pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'`
+ if [ ${pkt_0} -le ${count} ]; then
+ echo "LPM failure: 1: ${pkt_0} (should be ${count}) 2: ${pkt_1}"
+ exit 1
+ fi
+
+ echo "RAW BALANCING: 1: ${pkt_0} 2: ${pkt_1}"
+}
+
+lpm_test1_success_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "lpm_test2_success" "cleanup"
+lpm_test2_success_head()
+{
+
+ atf_set descr 'Test IPv4 LPM for the host routes'
+ atf_set require.user root
+}
+
+lpm_test2_success_body()
+{
+
+ vnet_init
+
+ jname="v4t-lpm_test2_success"
+
+ lo_dst=$(vnet_mkloopback)
+ epair0=$(vnet_mkepair)
+ epair1=$(vnet_mkepair)
+
+ setup_networking ${jname} ${lo_dst} ${epair0} ${epair1}
+
+ jexec ${jname}b ifconfig ${lo_dst} inet 198.51.100.0/32
+ jexec ${jname}b ifconfig ${lo_dst} alias 198.51.100.1/32
+
+ # Add routes
+ # A -> towards B via epair0a
+ jexec ${jname}a route add -4 -host 198.51.100.0 203.0.113.2
+ # A -> towards B via epair1a
+ jexec ${jname}a route add -4 -host 198.51.100.1 203.0.113.6
+
+ count=20
+ valid_message="${count} packets transmitted, ${count} packets received"
+
+ # Check that 198.51.100.0 goes via epair0
+ atf_check -o match:"${valid_message}" jexec ${jname}a ping -f -nc${count} 198.51.100.0
+ pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'`
+ pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'`
+ if [ ${pkt_0} -le ${count} ]; then
+ echo "LPM failure: 1: ${pkt_0} (should be ${count}) 2: ${pkt_1}"
+ exit 1
+ fi
+
+ # Check that 198.51.100.1 goes via epair1
+ atf_check -o match:"${valid_message}" jexec ${jname}a ping -f -nc${count} 198.51.100.1
+ pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'`
+ pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'`
+ if [ ${pkt_1} -le ${count} ]; then
+ echo "LPM failure: 1: ${pkt_0} 2: ${pkt_1} (should be ${count})"
+ exit 1
+ fi
+
+ echo "RAW BALANCING: 1: ${pkt_0} 2: ${pkt_1}"
+}
+
+lpm_test2_success_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case "lpm_test1_success"
+ atf_add_test_case "lpm_test2_success"
+}
+
Index: tests/sys/netinet6/Makefile
===================================================================
--- tests/sys/netinet6/Makefile
+++ tests/sys/netinet6/Makefile
@@ -12,7 +12,8 @@
redirect \
divert \
forward6 \
- output6
+ output6 \
+ lpm6
${PACKAGE}FILES+= exthdr.py
${PACKAGE}FILES+= mld.py
Index: tests/sys/netinet6/lpm6.sh
===================================================================
--- /dev/null
+++ tests/sys/netinet6/lpm6.sh
@@ -0,0 +1,199 @@
+#!/usr/bin/env atf-sh
+#-
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2020 Alexander V. Chernikov
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+. $(atf_get_srcdir)/../common/vnet.subr
+
+setup_networking()
+{
+ jname="$1"
+ lo_dst="$2"
+ epair0="$3"
+ epair1="$4"
+
+ vnet_mkjail ${jname}a ${epair0}a ${epair1}a ${lo_src}
+ # enable link-local IPv6
+ jexec ${jname}a ndp -i ${epair0}a -- -disabled
+ jexec ${jname}a ifconfig ${epair0}a up
+ jexec ${jname}a ndp -i ${epair1}a -- -disabled
+ jexec ${jname}a ifconfig ${epair1}a up
+ jexec ${jname}a ifconfig ${lo_src} up
+
+ vnet_mkjail ${jname}b ${epair0}b ${epair1}b ${lo_dst}
+ jexec ${jname}b ndp -i ${epair0}b -- -disabled
+ jexec ${jname}b ifconfig ${epair0}b up
+ jexec ${jname}b ndp -i ${epair1}b -- -disabled
+ jexec ${jname}b ifconfig ${epair1}b up
+ jexec ${jname}b ifconfig ${lo_dst} up
+
+ # wait for DAD to complete
+ while [ `jexec ${jname}b ifconfig | grep inet6 | grep -c tentative` != "0" ]; do
+ sleep 0.1
+ done
+ while [ `jexec ${jname}a ifconfig | grep inet6 | grep -c tentative` != "0" ]; do
+ sleep 0.1
+ done
+}
+
+
+atf_test_case "lpm6_test1_success" "cleanup"
+lpm6_test1_success_head()
+{
+
+ atf_set descr 'Test IPv6 LPM for the host routes'
+ atf_set require.user root
+}
+
+lpm6_test1_success_body()
+{
+
+ vnet_init
+
+ net_dst="2001:db8:"
+
+ jname="v6t-lpm6_test1_success"
+
+ epair0=$(vnet_mkepair)
+ epair1=$(vnet_mkepair)
+ lo_dst=$(vnet_mkloopback)
+
+ setup_networking ${jname} ${lo_dst} ${epair0} ${epair1}
+
+ jexec ${jname}b ifconfig ${lo_dst} inet6 ${net_dst}:2:0/128
+ jexec ${jname}b ifconfig ${lo_dst} inet6 ${net_dst}:2:1/128
+
+ # Add routes
+ # A -> towards B via epair0a LL
+ ll=`jexec ${jname}b ifconfig ${epair0}b inet6 | awk '$2~/^fe80:/{print$2}' | awk -F% '{print$1}'`
+ jexec ${jname}a route add -6 -host ${net_dst}:2:0 ${ll}%${epair0}a
+ # A -> towards B via epair1a LL
+ ll=`jexec ${jname}b ifconfig ${epair1}b inet6 | awk '$2~/^fe80:/{print$2}' | awk -F% '{print$1}'`
+ jexec ${jname}a route add -6 -host ${net_dst}:2:1 ${ll}%${epair1}a
+
+ count=20
+ valid_message="${count} packets transmitted, ${count} packets received"
+
+ # Check that ${net_dst}:2:0 goes via epair0
+ atf_check -o match:"${valid_message}" jexec ${jname}a ping6 -f -nc${count} ${net_dst}:2:0
+ pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'`
+ pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'`
+ if [ ${pkt_0} -le ${count} ]; then
+ echo "LPM failure: 1: ${pkt_0} (should be ${count}) 2: ${pkt_1}"
+ exit 1
+ fi
+
+ # Check that ${net_dst}:2:1 goes via epair1
+ atf_check -o match:"${valid_message}" jexec ${jname}a ping6 -f -nc${count} ${net_dst}:2:1
+ pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'`
+ pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'`
+ if [ ${pkt_1} -le ${count} ]; then
+ echo "LPM failure: 1: ${pkt_0} 2: ${pkt_1} (should be ${count})"
+ exit 1
+ fi
+
+ echo "RAW BALANCING: 1: ${pkt_0} 2: ${pkt_1}"
+}
+
+lpm6_test1_success_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "lpm6_test2_success" "cleanup"
+lpm6_test2_success_head()
+{
+
+ atf_set descr 'Test IPv6 LPM for /126 and /127'
+ atf_set require.user root
+}
+
+lpm6_test2_success_body()
+{
+
+ vnet_init
+
+ net_dst="2001:db8:"
+
+ jname="v6t-lpm6_test2_success"
+
+ epair0=$(vnet_mkepair)
+ epair1=$(vnet_mkepair)
+ lo_dst=$(vnet_mkloopback)
+
+ setup_networking ${jname} ${lo_dst} ${epair0} ${epair1}
+
+ jexec ${jname}b ifconfig ${lo_dst} inet6 ${net_dst}:2:0/128
+ jexec ${jname}b ifconfig ${lo_dst} inet6 ${net_dst}:2:2/128
+
+ # Add routes
+ # A -> towards B via epair0a LL
+ ll=`jexec ${jname}b ifconfig ${epair0}b inet6 | awk '$2~/^fe80:/{print$2}' | awk -F% '{print$1}'`
+ jexec ${jname}a route add -6 -net ${net_dst}:2:0/126 ${ll}%${epair0}a
+ # A -> towards B via epair1a LL
+ ll=`jexec ${jname}b ifconfig ${epair1}b inet6 | awk '$2~/^fe80:/{print$2}' | awk -F% '{print$1}'`
+ jexec ${jname}a route add -6 -net ${net_dst}:2:0/127 ${ll}%${epair1}a
+
+ count=20
+ valid_message="${count} packets transmitted, ${count} packets received"
+
+ # Check that ${net_dst}:2:0 goes via epair1
+ atf_check -o match:"${valid_message}" jexec ${jname}a ping6 -f -nc${count} ${net_dst}:2:0
+ pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'`
+ pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'`
+ if [ ${pkt_1} -le ${count} ]; then
+ echo "LPM failure: 1: ${pkt_0} 2: ${pkt_1} (should be ${count})"
+ exit 1
+ fi
+
+ # Check that ${net_dst}:2:2 goes via epair0
+ atf_check -o match:"${valid_message}" jexec ${jname}a ping6 -f -nc${count} ${net_dst}:2:2
+ pkt_0=`jexec ${jname}a netstat -Wf link -I ${epair0}a | head | awk '$1!~/^Name/{print$8}'`
+ pkt_1=`jexec ${jname}a netstat -Wf link -I ${epair1}a | head | awk '$1!~/^Name/{print$8}'`
+ if [ ${pkt_0} -le ${count} ]; then
+ echo "LPM failure: 1: ${pkt_0} (should be ${count}) 2: ${pkt_1}"
+ exit 1
+ fi
+
+ echo "RAW BALANCING: 1: ${pkt_0} 2: ${pkt_1}"
+}
+
+lpm6_test2_success_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case "lpm6_test1_success"
+ atf_add_test_case "lpm6_test2_success"
+}
+
+# end
+
+
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 17, 11:17 PM (21 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14686281
Default Alt Text
D23051.diff (25 KB)
Attached To
Mode
D23051: Allow address lookups in rn_match().
Attached
Detach File
Event Timeline
Log In to Comment