Page MenuHomeFreeBSD

D23051.diff
No OneTemporary

D23051.diff

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

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)

Event Timeline