mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-13 10:02:38 +00:00
netinet6: fix ndp proxying
We could insert proxy NDP entries by the ndp command, but the host with proxy ndp entries had not responded to Neighbor Solicitations. Change the following points for proxy NDP to work as expected: * join solicited-node multicast addresses for proxy NDP entries in order to receive Neighbor Solicitations. * look up proxy NDP entries not on the routing table but on the link-level address table when receiving Neighbor Solicitations. Reviewed By: melifaro Differential Revision: https://reviews.freebsd.org/D35307 MFC after: 2 weeks
This commit is contained in:
parent
77001f9b6d
commit
d6cd20cc5c
10
sys/net/if.c
10
sys/net/if.c
@ -1017,6 +1017,16 @@ if_purgeaddrs(struct ifnet *ifp)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
|
||||
#ifdef INET6
|
||||
/*
|
||||
* Need to leave multicast addresses of proxy NDP llentries
|
||||
* before in6_purgeifaddr() because the llentries are keys
|
||||
* for in6_multi objects of proxy NDP entries.
|
||||
* in6_purgeifaddr()s clean up llentries including proxy NDPs
|
||||
* then we would lose the keys if they are called earlier.
|
||||
*/
|
||||
in6_purge_proxy_ndp(ifp);
|
||||
#endif
|
||||
while (1) {
|
||||
struct epoch_tracker et;
|
||||
|
||||
|
@ -730,6 +730,51 @@ lltable_prefix_free(int af, struct sockaddr *addr, struct sockaddr *mask,
|
||||
LLTABLE_LIST_RUNLOCK();
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete llentries that func() returns true.
|
||||
*/
|
||||
struct lle_match_data {
|
||||
struct llentries dchain;
|
||||
llt_match_cb_t *func;
|
||||
void *farg;
|
||||
};
|
||||
|
||||
static int
|
||||
lltable_delete_conditional_cb(struct lltable *llt, struct llentry *lle,
|
||||
void *farg)
|
||||
{
|
||||
struct lle_match_data *lmd;
|
||||
|
||||
lmd = (struct lle_match_data *)farg;
|
||||
if (lmd->func(llt, lle, lmd->farg)) {
|
||||
LLE_WLOCK(lle);
|
||||
CK_LIST_INSERT_HEAD(&lmd->dchain, lle, lle_chain);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
lltable_delete_conditional(struct lltable *llt, llt_match_cb_t *func,
|
||||
void *farg)
|
||||
{
|
||||
struct llentry *lle, *next;
|
||||
struct lle_match_data lmd;
|
||||
|
||||
bzero(&lmd, sizeof(lmd));
|
||||
CK_LIST_INIT(&lmd.dchain);
|
||||
lmd.func = func;
|
||||
lmd.farg = farg;
|
||||
|
||||
IF_AFDATA_WLOCK(llt->llt_ifp);
|
||||
lltable_foreach_lle(llt, lltable_delete_conditional_cb, &lmd);
|
||||
llentries_unlink(llt, &lmd.dchain);
|
||||
IF_AFDATA_WUNLOCK(llt->llt_ifp);
|
||||
|
||||
CK_LIST_FOREACH_SAFE(lle, &lmd.dchain, lle_chain, next)
|
||||
llt->llt_delete_entry(llt, lle);
|
||||
}
|
||||
|
||||
struct lltable *
|
||||
lltable_allocate_htbl(uint32_t hsize)
|
||||
{
|
||||
@ -955,6 +1000,9 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
|
||||
lltable_unlink_entry(llt, lle_tmp);
|
||||
}
|
||||
lltable_link_entry(llt, lle);
|
||||
if ((lle->la_flags & LLE_PUB) != 0 &&
|
||||
(llt->llt_flags & LLT_ADDEDPROXY) == 0)
|
||||
llt->llt_flags |= LLT_ADDEDPROXY;
|
||||
IF_AFDATA_WUNLOCK(ifp);
|
||||
|
||||
if (lle_tmp != NULL) {
|
||||
|
@ -164,11 +164,13 @@ typedef void (llt_post_resolved_t)(struct lltable *, struct llentry *);
|
||||
|
||||
typedef int (llt_foreach_cb_t)(struct lltable *, struct llentry *, void *);
|
||||
typedef int (llt_foreach_entry_t)(struct lltable *, llt_foreach_cb_t *, void *);
|
||||
typedef bool (llt_match_cb_t)(struct lltable *, struct llentry *, void *);
|
||||
|
||||
struct lltable {
|
||||
SLIST_ENTRY(lltable) llt_link;
|
||||
sa_family_t llt_af;
|
||||
uint8_t llt_spare[3];
|
||||
uint8_t llt_flags;
|
||||
uint8_t llt_spare[2];
|
||||
int llt_hsize;
|
||||
int llt_entries;
|
||||
int llt_maxentries;
|
||||
@ -194,6 +196,11 @@ struct lltable {
|
||||
|
||||
MALLOC_DECLARE(M_LLTABLE);
|
||||
|
||||
/*
|
||||
* LLtable flags
|
||||
*/
|
||||
#define LLT_ADDEDPROXY 0x01 /* added a proxy llentry */
|
||||
|
||||
/*
|
||||
* LLentry flags
|
||||
*/
|
||||
@ -258,6 +265,9 @@ bool lltable_acquire_wlock(struct ifnet *ifp, struct llentry *lle);
|
||||
|
||||
int lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f,
|
||||
void *farg);
|
||||
void lltable_delete_conditional(struct lltable *llt, llt_match_cb_t *func,
|
||||
void *farg);
|
||||
|
||||
/*
|
||||
* Generic link layer address lookup function.
|
||||
*/
|
||||
|
@ -162,6 +162,9 @@ static int in6_update_ifa_internal(struct ifnet *, struct in6_aliasreq *,
|
||||
static int in6_broadcast_ifa(struct ifnet *, struct in6_aliasreq *,
|
||||
struct in6_ifaddr *, int);
|
||||
|
||||
static void in6_join_proxy_ndp_mc(struct ifnet *, const struct in6_addr *);
|
||||
static void in6_leave_proxy_ndp_mc(struct ifnet *, const struct in6_addr *);
|
||||
|
||||
#define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa))
|
||||
#define ia62ifa(ia6) (&((ia6)->ia_ifa))
|
||||
|
||||
@ -741,6 +744,26 @@ in6_joingroup_legacy(struct ifnet *ifp, const struct in6_addr *mcaddr,
|
||||
|
||||
return (imm);
|
||||
}
|
||||
|
||||
static int
|
||||
in6_solicited_node_maddr(struct in6_addr *maddr,
|
||||
struct ifnet *ifp, const struct in6_addr *base)
|
||||
{
|
||||
int error;
|
||||
|
||||
bzero(maddr, sizeof(struct in6_addr));
|
||||
maddr->s6_addr32[0] = IPV6_ADDR_INT32_MLL;
|
||||
maddr->s6_addr32[2] = htonl(1);
|
||||
maddr->s6_addr32[3] = base->s6_addr32[3];
|
||||
maddr->s6_addr8[12] = 0xff;
|
||||
if ((error = in6_setscope(maddr, ifp, NULL)) != 0) {
|
||||
/* XXX: should not happen */
|
||||
log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Join necessary multicast groups. Factored out from in6_update_ifa().
|
||||
* This entire work should only be done once, for the default FIB.
|
||||
@ -757,16 +780,9 @@ in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra,
|
||||
KASSERT(in6m_sol != NULL, ("%s: in6m_sol is NULL", __func__));
|
||||
|
||||
/* Join solicited multicast addr for new host id. */
|
||||
bzero(&mltaddr, sizeof(struct in6_addr));
|
||||
mltaddr.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
|
||||
mltaddr.s6_addr32[2] = htonl(1);
|
||||
mltaddr.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
|
||||
mltaddr.s6_addr8[12] = 0xff;
|
||||
if ((error = in6_setscope(&mltaddr, ifp, NULL)) != 0) {
|
||||
/* XXX: should not happen */
|
||||
log(LOG_ERR, "%s: in6_setscope failed\n", __func__);
|
||||
if ((error = in6_solicited_node_maddr(&mltaddr, ifp,
|
||||
&ifra->ifra_addr.sin6_addr)) != 0)
|
||||
goto cleanup;
|
||||
}
|
||||
delay = error = 0;
|
||||
if ((flags & IN6_IFAUPDATE_DADDELAY)) {
|
||||
/*
|
||||
@ -2285,6 +2301,10 @@ in6_lltable_delete_entry(struct lltable *llt, struct llentry *lle)
|
||||
{
|
||||
|
||||
lle->la_flags |= LLE_DELETED;
|
||||
|
||||
/* Leave the solicited multicast group. */
|
||||
if ((lle->la_flags & LLE_PUB) != 0)
|
||||
in6_leave_proxy_ndp_mc(llt->llt_ifp, &lle->r_l3addr.addr6);
|
||||
EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED);
|
||||
#ifdef DIAGNOSTIC
|
||||
log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
|
||||
@ -2463,7 +2483,9 @@ in6_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
|
||||
static void
|
||||
in6_lltable_post_resolved(struct lltable *llt, struct llentry *lle)
|
||||
{
|
||||
/* Handle proxy NDP entries (not yet). */
|
||||
/* Join the solicited multicast group for dst. */
|
||||
if ((lle->la_flags & LLE_PUB) == LLE_PUB)
|
||||
in6_join_proxy_ndp_mc(llt->llt_ifp, &lle->r_l3addr.addr6);
|
||||
}
|
||||
|
||||
static struct lltable *
|
||||
@ -2621,3 +2643,72 @@ in6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
|
||||
free(*nam, M_SONAME);
|
||||
*nam = (struct sockaddr *)sin6_p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Join/leave the solicited multicast groups for proxy NDP entries.
|
||||
*/
|
||||
static void
|
||||
in6_join_proxy_ndp_mc(struct ifnet *ifp, const struct in6_addr *dst)
|
||||
{
|
||||
struct in6_multi *inm;
|
||||
struct in6_addr mltaddr;
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
int error;
|
||||
|
||||
if (in6_solicited_node_maddr(&mltaddr, ifp, dst) != 0)
|
||||
return; /* error logged in in6_solicited_node_maddr. */
|
||||
|
||||
error = in6_joingroup(ifp, &mltaddr, NULL, &inm, 0);
|
||||
if (error != 0) {
|
||||
nd6log((LOG_WARNING,
|
||||
"%s: in6_joingroup failed for %s on %s (errno=%d)\n",
|
||||
__func__, ip6_sprintf(ip6buf, &mltaddr), if_name(ifp),
|
||||
error));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
in6_leave_proxy_ndp_mc(struct ifnet *ifp, const struct in6_addr *dst)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct in6_multi *inm;
|
||||
struct in6_addr mltaddr;
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (in6_solicited_node_maddr(&mltaddr, ifp, dst) != 0)
|
||||
return; /* error logged in in6_solicited_node_maddr. */
|
||||
|
||||
NET_EPOCH_ENTER(et);
|
||||
inm = in6m_lookup(ifp, &mltaddr);
|
||||
NET_EPOCH_EXIT(et);
|
||||
if (inm != NULL)
|
||||
in6_leavegroup(inm, NULL);
|
||||
else
|
||||
nd6log((LOG_WARNING, "%s: in6m_lookup failed for %s on %s\n",
|
||||
__func__, ip6_sprintf(ip6buf, &mltaddr), if_name(ifp)));
|
||||
}
|
||||
|
||||
static bool
|
||||
in6_lle_match_pub(struct lltable *llt, struct llentry *lle, void *farg)
|
||||
{
|
||||
return ((lle->la_flags & LLE_PUB) != 0);
|
||||
}
|
||||
|
||||
void
|
||||
in6_purge_proxy_ndp(struct ifnet *ifp)
|
||||
{
|
||||
struct lltable *llt;
|
||||
bool need_purge;
|
||||
|
||||
llt = LLTABLE6(ifp);
|
||||
IF_AFDATA_WLOCK(ifp);
|
||||
need_purge = ((llt->llt_flags & LLT_ADDEDPROXY) != 0);
|
||||
IF_AFDATA_WUNLOCK(ifp);
|
||||
|
||||
/*
|
||||
* Ever added proxy ndp entries, leave solicited node multicast
|
||||
* before deleting the llentry.
|
||||
*/
|
||||
if (need_purge)
|
||||
lltable_delete_conditional(llt, in6_lle_match_pub, NULL);
|
||||
}
|
||||
|
@ -916,6 +916,8 @@ int in6_is_addr_deprecated(struct sockaddr_in6 *);
|
||||
int in6_src_ioctl(u_long, caddr_t);
|
||||
|
||||
void in6_newaddrmsg(struct in6_ifaddr *, int);
|
||||
|
||||
void in6_purge_proxy_ndp(struct ifnet *);
|
||||
/*
|
||||
* Extended API for IPv6 FIB support.
|
||||
*/
|
||||
|
@ -96,6 +96,9 @@ static void nd6_na_output_fib(struct ifnet *, const struct in6_addr *,
|
||||
static void nd6_ns_output_fib(struct ifnet *, const struct in6_addr *,
|
||||
const struct in6_addr *, const struct in6_addr *, uint8_t *, u_int);
|
||||
|
||||
static struct ifaddr *nd6_proxy_fill_sdl(struct ifnet *,
|
||||
const struct in6_addr *, struct sockaddr_dl *);
|
||||
|
||||
VNET_DEFINE_STATIC(int, dad_enhanced) = 1;
|
||||
#define V_dad_enhanced VNET(dad_enhanced)
|
||||
|
||||
@ -255,34 +258,8 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
||||
/* (2) check. */
|
||||
proxy = 0;
|
||||
if (ifa == NULL) {
|
||||
struct sockaddr_dl rt_gateway;
|
||||
struct rt_addrinfo info;
|
||||
struct sockaddr_in6 dst6;
|
||||
|
||||
bzero(&dst6, sizeof(dst6));
|
||||
dst6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
dst6.sin6_family = AF_INET6;
|
||||
dst6.sin6_addr = taddr6;
|
||||
|
||||
bzero(&rt_gateway, sizeof(rt_gateway));
|
||||
rt_gateway.sdl_len = sizeof(rt_gateway);
|
||||
bzero(&info, sizeof(info));
|
||||
info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&rt_gateway;
|
||||
|
||||
if (rib_lookup_info(ifp->if_fib, (struct sockaddr *)&dst6,
|
||||
0, 0, &info) == 0) {
|
||||
if ((info.rti_flags & RTF_ANNOUNCE) != 0 &&
|
||||
rt_gateway.sdl_family == AF_LINK) {
|
||||
/*
|
||||
* proxy NDP for single entry
|
||||
*/
|
||||
proxydl = *SDL(&rt_gateway);
|
||||
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(
|
||||
ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
|
||||
if (ifa)
|
||||
proxy = 1;
|
||||
}
|
||||
}
|
||||
if ((ifa = nd6_proxy_fill_sdl(ifp, &taddr6, &proxydl)) != NULL)
|
||||
proxy = 1;
|
||||
}
|
||||
if (ifa == NULL) {
|
||||
/*
|
||||
@ -386,6 +363,30 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
||||
m_freem(m);
|
||||
}
|
||||
|
||||
static struct ifaddr *
|
||||
nd6_proxy_fill_sdl(struct ifnet *ifp, const struct in6_addr *taddr6,
|
||||
struct sockaddr_dl *sdl)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
struct llentry *ln;
|
||||
|
||||
ifa = NULL;
|
||||
ln = nd6_lookup(taddr6, LLE_SF(AF_INET6, 0), ifp);
|
||||
if (ln == NULL)
|
||||
return (ifa);
|
||||
if ((ln->la_flags & (LLE_PUB | LLE_VALID)) == (LLE_PUB | LLE_VALID)) {
|
||||
link_init_sdl(ifp, (struct sockaddr *)sdl, ifp->if_type);
|
||||
sdl->sdl_alen = ifp->if_addrlen;
|
||||
bcopy(ln->ll_addr, &sdl->sdl_data, ifp->if_addrlen);
|
||||
LLE_RUNLOCK(ln);
|
||||
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
|
||||
IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
|
||||
} else
|
||||
LLE_RUNLOCK(ln);
|
||||
|
||||
return (ifa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a Neighbor Solicitation Message. Caller specifies:
|
||||
* - ICMP6 header source IP6 address
|
||||
|
@ -15,7 +15,8 @@ ATF_TESTS_SH= \
|
||||
output6 \
|
||||
lpm6 \
|
||||
fibs6 \
|
||||
ndp
|
||||
ndp \
|
||||
proxy_ndp
|
||||
TEST_METADATA.output6+= required_programs="python"
|
||||
|
||||
${PACKAGE}FILES+= exthdr.py
|
||||
|
222
tests/sys/netinet6/proxy_ndp.sh
Executable file
222
tests/sys/netinet6/proxy_ndp.sh
Executable file
@ -0,0 +1,222 @@
|
||||
#!/usr/bin/env atf-sh
|
||||
#-
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Copyright (c) 2022 KUROSAWA Takahiro <takahiro.kurosawa@gmail.com>
|
||||
#
|
||||
# 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
|
||||
|
||||
atf_test_case "pndp_add_gu_success" "cleanup"
|
||||
pndp_add_gu_success_head() {
|
||||
atf_set descr 'Test proxy ndp record addition'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
pndp_add_gu_success_body() {
|
||||
|
||||
vnet_init
|
||||
|
||||
jname="v6t-pndp_add_success"
|
||||
|
||||
epair0=$(vnet_mkepair)
|
||||
|
||||
vnet_mkjail ${jname} ${epair0}a
|
||||
jexec ${jname} ndp -i ${epair0}a -- -disabled
|
||||
jexec ${jname} ifconfig ${epair0}a up
|
||||
|
||||
jexec ${jname} ifconfig ${epair0}a inet6 2001:db8::1/64
|
||||
proxy_mac=`jexec ${jname} ifconfig ${epair0}a ether | awk '$1~/ether/{print$2}'`
|
||||
|
||||
# wait for DAD to complete
|
||||
while [ `jexec ${jname} ifconfig | grep inet6 | grep -c tentative` != "0" ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
atf_check jexec ${jname} ndp -s 2001:db8::2 ${proxy_mac} proxy
|
||||
while [ `jexec ${jname} ifmcstat | grep -c undefined` != "0" ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
# checking the output of ndp -an is covered by ndp.sh.
|
||||
# we check the output of ifmcstat output here.
|
||||
t=`jexec ${jname} ifmcstat -i ${epair0}a -f inet6 | grep -A1 'group ff02::1:ff00:2'`
|
||||
atf_check -o match:'mcast-macaddr 33:33:ff:00:00:02' echo $t
|
||||
}
|
||||
|
||||
pndp_add_gu_success_cleanup() {
|
||||
vnet_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "pndp_del_gu_success" "cleanup"
|
||||
pndp_del_gu_success_head() {
|
||||
atf_set descr 'Test proxy ndp record deletion'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
pndp_del_gu_success_body() {
|
||||
|
||||
vnet_init
|
||||
|
||||
jname="v6t-pndp_del_gu_success"
|
||||
|
||||
epair0=$(vnet_mkepair)
|
||||
|
||||
vnet_mkjail ${jname} ${epair0}a
|
||||
|
||||
jexec ${jname} ndp -i ${epair0}a -- -disabled
|
||||
jexec ${jname} ifconfig ${epair0}a up
|
||||
|
||||
jexec ${jname} ifconfig ${epair0}a inet6 2001:db8::1/64
|
||||
proxy_mac=`jexec ${jname} ifconfig ${epair0}a ether | awk '$1~/ether/{print$2}'`
|
||||
|
||||
# wait for DAD to complete
|
||||
while [ `jexec ${jname} ifconfig | grep inet6 | grep -c tentative` != "0" ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
atf_check jexec ${jname} ndp -s 2001:db8::2 ${proxy_mac} proxy
|
||||
while [ `jexec ${jname} ifmcstat | grep -c undefined` != "0" ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
jexec ${jname} ping -c1 -t1 2001:db8::2
|
||||
|
||||
atf_check -o match:"2001:db8::2 \(2001:db8::2\) deleted" jexec ${jname} ndp -nd 2001:db8::2
|
||||
while [ `jexec ${jname} ifmcstat | grep -c undefined` != "0" ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
atf_check \
|
||||
-o not-match:'group ff02::1:ff00:2' \
|
||||
-o not-match:'mcast-macaddr 33:33:ff:00:00:02' \
|
||||
jexec ${jname} ifmcstat -i ${epair0}a -f inet6
|
||||
}
|
||||
|
||||
pndp_del_gu_success_cleanup() {
|
||||
vnet_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "pndp_ifdestroy_success" "cleanup"
|
||||
pndp_ifdetroy_success_head() {
|
||||
atf_set descr 'Test interface destruction with proxy ndp'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
pndp_ifdestroy_success_body() {
|
||||
|
||||
vnet_init
|
||||
|
||||
jname="v6t-pndp_ifdestroy_success"
|
||||
|
||||
epair0=$(vnet_mkepair)
|
||||
|
||||
vnet_mkjail ${jname} ${epair0}a
|
||||
|
||||
jexec ${jname} ndp -i ${epair0}a -- -disabled
|
||||
jexec ${jname} ifconfig ${epair0}a up
|
||||
|
||||
jexec ${jname} ifconfig ${epair0}a inet6 2001:db8::1/64
|
||||
proxy_mac=`jexec ${jname} ifconfig ${epair0}a ether | awk '$1~/ether/{print$2}'`
|
||||
|
||||
# wait for DAD to complete
|
||||
while [ `jexec ${jname} ifconfig | grep inet6 | grep -c tentative` != "0" ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
atf_check jexec ${jname} ndp -s 2001:db8::2 ${proxy_mac} proxy
|
||||
while [ `jexec ${jname} ifmcstat | grep -c undefined` != "0" ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
atf_check jexec ${jname} ifconfig ${epair0}a destroy
|
||||
}
|
||||
|
||||
pndp_ifdestroy_success_cleanup() {
|
||||
vnet_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "pndp_neighbor_advert" "cleanup"
|
||||
pndp_neighbor_advert_head() {
|
||||
atf_set descr 'Test Neighbor Advertisement for proxy ndp'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
pndp_neighbor_advert_body() {
|
||||
|
||||
vnet_init
|
||||
|
||||
jname_a="v6t-pndp_neighbor_advert_a" # NA sender (w/proxy ndp entry)
|
||||
jname_b="v6t-pndp_neighbor_advert_b" # NA receiver (checker)
|
||||
proxy_addr="2001:db8::aaaa"
|
||||
|
||||
epair0=$(vnet_mkepair)
|
||||
|
||||
vnet_mkjail ${jname_a} ${epair0}a
|
||||
jexec ${jname_a} ndp -i ${epair0}a -- -disabled
|
||||
jexec ${jname_a} ifconfig ${epair0}a up
|
||||
jexec ${jname_a} ifconfig ${epair0}a inet6 2001:db8::1/64
|
||||
proxy_mac=`jexec ${jname_a} ifconfig ${epair0}a ether | awk '$1~/ether/{print$2}'`
|
||||
# wait for DAD to complete
|
||||
while [ `jexec ${jname_a} ifconfig | grep inet6 | grep -c tentative` != "0" ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
atf_check jexec ${jname_a} ndp -s ${proxy_addr} ${proxy_mac} proxy
|
||||
while [ `jexec ${jname_a} ifmcstat | grep -c undefined` != "0" ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
vnet_mkjail ${jname_b} ${epair0}b
|
||||
jexec ${jname_b} ndp -i ${epair0}b -- -disabled
|
||||
jexec ${jname_b} ifconfig ${epair0}b up
|
||||
jexec ${jname_b} ifconfig ${epair0}b inet6 2001:db8::2/64
|
||||
# wait for DAD to complete
|
||||
while [ `jexec ${jname_b} ifconfig | grep inet6 | grep -c tentative` != "0" ]; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
jexec ${jname_b} ndp -nc
|
||||
# jname_b sends a NS before ICMPv6 Echo Request for the proxy address.
|
||||
# jname_a responds with a NA resolving the proxy address.
|
||||
# Then there must be a NDP entry of the proxy address in jname_b.
|
||||
jexec ${jname_b} ping -c1 -t1 ${proxy_addr}
|
||||
atf_check -o match:"${proxy_addr} +${proxy_mac} +${epair0}b" \
|
||||
jexec ${jname_b} ndp -an
|
||||
}
|
||||
|
||||
pndp_neighbor_advert_cleanup() {
|
||||
vnet_cleanup
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
|
||||
atf_add_test_case "pndp_add_gu_success"
|
||||
atf_add_test_case "pndp_del_gu_success"
|
||||
atf_add_test_case "pndp_ifdestroy_success"
|
||||
atf_add_test_case "pndp_neighbor_advert"
|
||||
}
|
||||
|
||||
# end
|
||||
|
Loading…
Reference in New Issue
Block a user