aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/addrconf.h4
-rw-r--r--net/ipv6/addrconf.c26
-rw-r--r--net/ipv6/anycast.c9
-rw-r--r--net/ipv6/datagram.c5
-rw-r--r--net/ipv6/ip6_tunnel.c12
-rw-r--r--net/ipv6/ndisc.c2
-rw-r--r--net/ipv6/route.c131
-rwxr-xr-xtools/testing/selftests/net/fib_tests.sh359
8 files changed, 390 insertions, 158 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index c4185a7b0e90..132e5b95167a 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -69,8 +69,8 @@ int addrconf_set_dstaddr(struct net *net, void __user *arg);
int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
const struct net_device *dev, int strict);
int ipv6_chk_addr_and_flags(struct net *net, const struct in6_addr *addr,
- const struct net_device *dev, int strict,
- u32 banned_flags);
+ const struct net_device *dev, bool skip_dev_check,
+ int strict, u32 banned_flags);
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b5fd116c046a..6fd4bbdc444f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1851,22 +1851,42 @@ static int ipv6_count_addresses(const struct inet6_dev *idev)
int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
const struct net_device *dev, int strict)
{
- return ipv6_chk_addr_and_flags(net, addr, dev, strict, IFA_F_TENTATIVE);
+ return ipv6_chk_addr_and_flags(net, addr, dev, !dev,
+ strict, IFA_F_TENTATIVE);
}
EXPORT_SYMBOL(ipv6_chk_addr);
+/* device argument is used to find the L3 domain of interest. If
+ * skip_dev_check is set, then the ifp device is not checked against
+ * the passed in dev argument. So the 2 cases for addresses checks are:
+ * 1. does the address exist in the L3 domain that dev is part of
+ * (skip_dev_check = true), or
+ *
+ * 2. does the address exist on the specific device
+ * (skip_dev_check = false)
+ */
int ipv6_chk_addr_and_flags(struct net *net, const struct in6_addr *addr,
- const struct net_device *dev, int strict,
- u32 banned_flags)
+ const struct net_device *dev, bool skip_dev_check,
+ int strict, u32 banned_flags)
{
unsigned int hash = inet6_addr_hash(net, addr);
+ const struct net_device *l3mdev;
struct inet6_ifaddr *ifp;
u32 ifp_flags;
rcu_read_lock();
+
+ l3mdev = l3mdev_master_dev_rcu(dev);
+ if (skip_dev_check)
+ dev = NULL;
+
hlist_for_each_entry_rcu(ifp, &inet6_addr_lst[hash], addr_lst) {
if (!net_eq(dev_net(ifp->idev->dev), net))
continue;
+
+ if (l3mdev_master_dev_rcu(ifp->idev->dev) != l3mdev)
+ continue;
+
/* Decouple optimistic from tentative for evaluation here.
* Ban optimistic addresses explicitly, when required.
*/
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index c61718dba2e6..d580d4d456a5 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -66,7 +66,11 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
return -EPERM;
if (ipv6_addr_is_multicast(addr))
return -EINVAL;
- if (ipv6_chk_addr(net, addr, NULL, 0))
+
+ if (ifindex)
+ dev = __dev_get_by_index(net, ifindex);
+
+ if (ipv6_chk_addr_and_flags(net, addr, dev, true, 0, IFA_F_TENTATIVE))
return -EINVAL;
pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL);
@@ -90,8 +94,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
dev = __dev_get_by_flags(net, IFF_UP,
IFF_UP | IFF_LOOPBACK);
}
- } else
- dev = __dev_get_by_index(net, ifindex);
+ }
if (!dev) {
err = -ENODEV;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index fbf08ce3f5ab..b27333d7b099 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -801,8 +801,9 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
if (addr_type != IPV6_ADDR_ANY) {
int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL;
if (!(inet_sk(sk)->freebind || inet_sk(sk)->transparent) &&
- !ipv6_chk_addr(net, &src_info->ipi6_addr,
- strict ? dev : NULL, 0) &&
+ !ipv6_chk_addr_and_flags(net, &src_info->ipi6_addr,
+ dev, !strict, 0,
+ IFA_F_TENTATIVE) &&
!ipv6_chk_acast_addr_src(net, dev,
&src_info->ipi6_addr))
err = -EINVAL;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 5c045fa407da..456fcf942f95 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -758,9 +758,11 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t,
ldev = dev_get_by_index_rcu(net, p->link);
if ((ipv6_addr_is_multicast(laddr) ||
- likely(ipv6_chk_addr(net, laddr, ldev, 0))) &&
+ likely(ipv6_chk_addr_and_flags(net, laddr, ldev, false,
+ 0, IFA_F_TENTATIVE))) &&
((p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) ||
- likely(!ipv6_chk_addr(net, raddr, NULL, 0))))
+ likely(!ipv6_chk_addr_and_flags(net, raddr, ldev, true,
+ 0, IFA_F_TENTATIVE))))
ret = 1;
}
return ret;
@@ -990,12 +992,14 @@ int ip6_tnl_xmit_ctl(struct ip6_tnl *t,
if (p->link)
ldev = dev_get_by_index_rcu(net, p->link);
- if (unlikely(!ipv6_chk_addr(net, laddr, ldev, 0)))
+ if (unlikely(!ipv6_chk_addr_and_flags(net, laddr, ldev, false,
+ 0, IFA_F_TENTATIVE)))
pr_warn("%s xmit: Local address not yet configured!\n",
p->name);
else if (!(p->flags & IP6_TNL_F_ALLOW_LOCAL_REMOTE) &&
!ipv6_addr_is_multicast(raddr) &&
- unlikely(ipv6_chk_addr(net, raddr, NULL, 0)))
+ unlikely(ipv6_chk_addr_and_flags(net, raddr, ldev,
+ true, 0, IFA_F_TENTATIVE)))
pr_warn("%s xmit: Routing loop! Remote address found on this node!\n",
p->name);
else
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 8af5eef464c1..10024eb0c521 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -707,7 +707,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
int probes = atomic_read(&neigh->probes);
if (skb && ipv6_chk_addr_and_flags(dev_net(dev), &ipv6_hdr(skb)->saddr,
- dev, 1,
+ dev, false, 1,
IFA_F_TENTATIVE|IFA_F_OPTIMISTIC))
saddr = &ipv6_hdr(skb)->saddr;
probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 81711e3e2604..939d122e71b4 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2550,7 +2550,7 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net,
static int ip6_route_check_nh_onlink(struct net *net,
struct fib6_config *cfg,
- struct net_device *dev,
+ const struct net_device *dev,
struct netlink_ext_ack *extack)
{
u32 tbid = l3mdev_fib_table(dev) ? : RT_TABLE_MAIN;
@@ -2626,6 +2626,79 @@ out:
return err;
}
+static int ip6_validate_gw(struct net *net, struct fib6_config *cfg,
+ struct net_device **_dev, struct inet6_dev **idev,
+ struct netlink_ext_ack *extack)
+{
+ const struct in6_addr *gw_addr = &cfg->fc_gateway;
+ int gwa_type = ipv6_addr_type(gw_addr);
+ bool skip_dev = gwa_type & IPV6_ADDR_LINKLOCAL ? false : true;
+ const struct net_device *dev = *_dev;
+ bool need_addr_check = !dev;
+ int err = -EINVAL;
+
+ /* if gw_addr is local we will fail to detect this in case
+ * address is still TENTATIVE (DAD in progress). rt6_lookup()
+ * will return already-added prefix route via interface that
+ * prefix route was assigned to, which might be non-loopback.
+ */
+ if (dev &&
+ ipv6_chk_addr_and_flags(net, gw_addr, dev, skip_dev, 0, 0)) {
+ NL_SET_ERR_MSG(extack, "Gateway can not be a local address");
+ goto out;
+ }
+
+ if (gwa_type != (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST)) {
+ /* IPv6 strictly inhibits using not link-local
+ * addresses as nexthop address.
+ * Otherwise, router will not able to send redirects.
+ * It is very good, but in some (rare!) circumstances
+ * (SIT, PtP, NBMA NOARP links) it is handy to allow
+ * some exceptions. --ANK
+ * We allow IPv4-mapped nexthops to support RFC4798-type
+ * addressing
+ */
+ if (!(gwa_type & (IPV6_ADDR_UNICAST | IPV6_ADDR_MAPPED))) {
+ NL_SET_ERR_MSG(extack, "Invalid gateway address");
+ goto out;
+ }
+
+ if (cfg->fc_flags & RTNH_F_ONLINK)
+ err = ip6_route_check_nh_onlink(net, cfg, dev, extack);
+ else
+ err = ip6_route_check_nh(net, cfg, _dev, idev);
+
+ if (err)
+ goto out;
+ }
+
+ /* reload in case device was changed */
+ dev = *_dev;
+
+ err = -EINVAL;
+ if (!dev) {
+ NL_SET_ERR_MSG(extack, "Egress device not specified");
+ goto out;
+ } else if (dev->flags & IFF_LOOPBACK) {
+ NL_SET_ERR_MSG(extack,
+ "Egress device can not be loopback device for this route");
+ goto out;
+ }
+
+ /* if we did not check gw_addr above, do so now that the
+ * egress device has been resolved.
+ */
+ if (need_addr_check &&
+ ipv6_chk_addr_and_flags(net, gw_addr, dev, skip_dev, 0, 0)) {
+ NL_SET_ERR_MSG(extack, "Gateway can not be a local address");
+ goto out;
+ }
+
+ err = 0;
+out:
+ return err;
+}
+
static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
struct netlink_ext_ack *extack)
{
@@ -2808,61 +2881,11 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
}
if (cfg->fc_flags & RTF_GATEWAY) {
- const struct in6_addr *gw_addr;
- int gwa_type;
-
- gw_addr = &cfg->fc_gateway;
- gwa_type = ipv6_addr_type(gw_addr);
-
- /* if gw_addr is local we will fail to detect this in case
- * address is still TENTATIVE (DAD in progress). rt6_lookup()
- * will return already-added prefix route via interface that
- * prefix route was assigned to, which might be non-loopback.
- */
- err = -EINVAL;
- if (ipv6_chk_addr_and_flags(net, gw_addr,
- gwa_type & IPV6_ADDR_LINKLOCAL ?
- dev : NULL, 0, 0)) {
- NL_SET_ERR_MSG(extack, "Invalid gateway address");
+ err = ip6_validate_gw(net, cfg, &dev, &idev, extack);
+ if (err)
goto out;
- }
- rt->rt6i_gateway = *gw_addr;
-
- if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
- /* IPv6 strictly inhibits using not link-local
- addresses as nexthop address.
- Otherwise, router will not able to send redirects.
- It is very good, but in some (rare!) circumstances
- (SIT, PtP, NBMA NOARP links) it is handy to allow
- some exceptions. --ANK
- We allow IPv4-mapped nexthops to support RFC4798-type
- addressing
- */
- if (!(gwa_type & (IPV6_ADDR_UNICAST |
- IPV6_ADDR_MAPPED))) {
- NL_SET_ERR_MSG(extack,
- "Invalid gateway address");
- goto out;
- }
- if (cfg->fc_flags & RTNH_F_ONLINK) {
- err = ip6_route_check_nh_onlink(net, cfg, dev,
- extack);
- } else {
- err = ip6_route_check_nh(net, cfg, &dev, &idev);
- }
- if (err)
- goto out;
- }
- err = -EINVAL;
- if (!dev) {
- NL_SET_ERR_MSG(extack, "Egress device not specified");
- goto out;
- } else if (dev->flags & IFF_LOOPBACK) {
- NL_SET_ERR_MSG(extack,
- "Egress device can not be loopback device for this route");
- goto out;
- }
+ rt->rt6i_gateway = cfg->fc_gateway;
}
err = -ENODEV;
diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh
index b617985ecdc1..9164e60d4b66 100755
--- a/tools/testing/selftests/net/fib_tests.sh
+++ b/tools/testing/selftests/net/fib_tests.sh
@@ -6,7 +6,9 @@
ret=0
+VERBOSE=${VERBOSE:=0}
PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
+IP="ip -netns testns"
log_test()
{
@@ -15,10 +17,10 @@ log_test()
local msg="$3"
if [ ${rc} -eq ${expected} ]; then
- printf " %-60s [ OK ]\n" "${msg}"
+ printf " TEST: %-60s [ OK ]\n" "${msg}"
else
ret=1
- printf " %-60s [FAIL]\n" "${msg}"
+ printf " TEST: %-60s [FAIL]\n" "${msg}"
if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
echo
echo "hit enter to continue, 'q' to quit"
@@ -32,22 +34,44 @@ setup()
{
set -e
ip netns add testns
- ip -netns testns link set dev lo up
+ $IP link set dev lo up
- ip -netns testns link add dummy0 type dummy
- ip -netns testns link set dev dummy0 up
- ip -netns testns address add 198.51.100.1/24 dev dummy0
- ip -netns testns -6 address add 2001:db8:1::1/64 dev dummy0
+ $IP link add dummy0 type dummy
+ $IP link set dev dummy0 up
+ $IP address add 198.51.100.1/24 dev dummy0
+ $IP -6 address add 2001:db8:1::1/64 dev dummy0
set +e
}
cleanup()
{
- ip -netns testns link del dev dummy0 &> /dev/null
+ $IP link del dev dummy0 &> /dev/null
ip netns del testns
}
+get_linklocal()
+{
+ local dev=$1
+ local addr
+
+ addr=$($IP -6 -br addr show dev ${dev} | \
+ awk '{
+ for (i = 3; i <= NF; ++i) {
+ if ($i ~ /^fe80/)
+ print $i
+ }
+ }'
+ )
+ addr=${addr/\/*}
+
+ [ -z "$addr" ] && return 1
+
+ echo $addr
+
+ return 0
+}
+
fib_unreg_unicast_test()
{
echo
@@ -56,19 +80,19 @@ fib_unreg_unicast_test()
setup
echo " Start point"
- ip -netns testns route get fibmatch 198.51.100.2 &> /dev/null
+ $IP route get fibmatch 198.51.100.2 &> /dev/null
log_test $? 0 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:1::2 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
log_test $? 0 "IPv6 fibmatch"
set -e
- ip -netns testns link del dev dummy0
+ $IP link del dev dummy0
set +e
echo " Nexthop device deleted"
- ip -netns testns route get fibmatch 198.51.100.2 &> /dev/null
+ $IP route get fibmatch 198.51.100.2 &> /dev/null
log_test $? 2 "IPv4 fibmatch - no route"
- ip -netns testns -6 route get fibmatch 2001:db8:1::2 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
log_test $? 2 "IPv6 fibmatch - no route"
cleanup
@@ -83,43 +107,43 @@ fib_unreg_multipath_test()
setup
set -e
- ip -netns testns link add dummy1 type dummy
- ip -netns testns link set dev dummy1 up
- ip -netns testns address add 192.0.2.1/24 dev dummy1
- ip -netns testns -6 address add 2001:db8:2::1/64 dev dummy1
+ $IP link add dummy1 type dummy
+ $IP link set dev dummy1 up
+ $IP address add 192.0.2.1/24 dev dummy1
+ $IP -6 address add 2001:db8:2::1/64 dev dummy1
- ip -netns testns route add 203.0.113.0/24 \
+ $IP route add 203.0.113.0/24 \
nexthop via 198.51.100.2 dev dummy0 \
nexthop via 192.0.2.2 dev dummy1
- ip -netns testns -6 route add 2001:db8:3::/64 \
+ $IP -6 route add 2001:db8:3::/64 \
nexthop via 2001:db8:1::2 dev dummy0 \
nexthop via 2001:db8:2::2 dev dummy1
set +e
echo " Start point"
- ip -netns testns route get fibmatch 203.0.113.1 &> /dev/null
+ $IP route get fibmatch 203.0.113.1 &> /dev/null
log_test $? 0 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:3::1 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
log_test $? 0 "IPv6 fibmatch"
set -e
- ip -netns testns link del dev dummy0
+ $IP link del dev dummy0
set +e
echo " One nexthop device deleted"
- ip -netns testns route get fibmatch 203.0.113.1 &> /dev/null
+ $IP route get fibmatch 203.0.113.1 &> /dev/null
log_test $? 2 "IPv4 - multipath route removed on delete"
- ip -netns testns -6 route get fibmatch 2001:db8:3::1 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
# In IPv6 we do not flush the entire multipath route.
log_test $? 0 "IPv6 - multipath down to single path"
set -e
- ip -netns testns link del dev dummy1
+ $IP link del dev dummy1
set +e
echo " Second nexthop device deleted"
- ip -netns testns -6 route get fibmatch 2001:db8:3::1 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
log_test $? 2 "IPv6 - no route"
cleanup
@@ -139,19 +163,19 @@ fib_down_unicast_test()
setup
echo " Start point"
- ip -netns testns route get fibmatch 198.51.100.2 &> /dev/null
+ $IP route get fibmatch 198.51.100.2 &> /dev/null
log_test $? 0 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:1::2 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
log_test $? 0 "IPv6 fibmatch"
set -e
- ip -netns testns link set dev dummy0 down
+ $IP link set dev dummy0 down
set +e
echo " Route deleted on down"
- ip -netns testns route get fibmatch 198.51.100.2 &> /dev/null
+ $IP route get fibmatch 198.51.100.2 &> /dev/null
log_test $? 2 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:1::2 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
log_test $? 2 "IPv6 fibmatch"
cleanup
@@ -162,31 +186,31 @@ fib_down_multipath_test_do()
local down_dev=$1
local up_dev=$2
- ip -netns testns route get fibmatch 203.0.113.1 \
+ $IP route get fibmatch 203.0.113.1 \
oif $down_dev &> /dev/null
log_test $? 2 "IPv4 fibmatch on down device"
- ip -netns testns -6 route get fibmatch 2001:db8:3::1 \
+ $IP -6 route get fibmatch 2001:db8:3::1 \
oif $down_dev &> /dev/null
log_test $? 2 "IPv6 fibmatch on down device"
- ip -netns testns route get fibmatch 203.0.113.1 \
+ $IP route get fibmatch 203.0.113.1 \
oif $up_dev &> /dev/null
log_test $? 0 "IPv4 fibmatch on up device"
- ip -netns testns -6 route get fibmatch 2001:db8:3::1 \
+ $IP -6 route get fibmatch 2001:db8:3::1 \
oif $up_dev &> /dev/null
log_test $? 0 "IPv6 fibmatch on up device"
- ip -netns testns route get fibmatch 203.0.113.1 | \
+ $IP route get fibmatch 203.0.113.1 | \
grep $down_dev | grep -q "dead linkdown"
log_test $? 0 "IPv4 flags on down device"
- ip -netns testns -6 route get fibmatch 2001:db8:3::1 | \
+ $IP -6 route get fibmatch 2001:db8:3::1 | \
grep $down_dev | grep -q "dead linkdown"
log_test $? 0 "IPv6 flags on down device"
- ip -netns testns route get fibmatch 203.0.113.1 | \
+ $IP route get fibmatch 203.0.113.1 | \
grep $up_dev | grep -q "dead linkdown"
log_test $? 1 "IPv4 flags on up device"
- ip -netns testns -6 route get fibmatch 2001:db8:3::1 | \
+ $IP -6 route get fibmatch 2001:db8:3::1 | \
grep $up_dev | grep -q "dead linkdown"
log_test $? 1 "IPv6 flags on up device"
}
@@ -199,53 +223,53 @@ fib_down_multipath_test()
setup
set -e
- ip -netns testns link add dummy1 type dummy
- ip -netns testns link set dev dummy1 up
+ $IP link add dummy1 type dummy
+ $IP link set dev dummy1 up
- ip -netns testns address add 192.0.2.1/24 dev dummy1
- ip -netns testns -6 address add 2001:db8:2::1/64 dev dummy1
+ $IP address add 192.0.2.1/24 dev dummy1
+ $IP -6 address add 2001:db8:2::1/64 dev dummy1
- ip -netns testns route add 203.0.113.0/24 \
+ $IP route add 203.0.113.0/24 \
nexthop via 198.51.100.2 dev dummy0 \
nexthop via 192.0.2.2 dev dummy1
- ip -netns testns -6 route add 2001:db8:3::/64 \
+ $IP -6 route add 2001:db8:3::/64 \
nexthop via 2001:db8:1::2 dev dummy0 \
nexthop via 2001:db8:2::2 dev dummy1
set +e
echo " Verify start point"
- ip -netns testns route get fibmatch 203.0.113.1 &> /dev/null
+ $IP route get fibmatch 203.0.113.1 &> /dev/null
log_test $? 0 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:3::1 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
log_test $? 0 "IPv6 fibmatch"
set -e
- ip -netns testns link set dev dummy0 down
+ $IP link set dev dummy0 down
set +e
echo " One device down, one up"
fib_down_multipath_test_do "dummy0" "dummy1"
set -e
- ip -netns testns link set dev dummy0 up
- ip -netns testns link set dev dummy1 down
+ $IP link set dev dummy0 up
+ $IP link set dev dummy1 down
set +e
echo " Other device down and up"
fib_down_multipath_test_do "dummy1" "dummy0"
set -e
- ip -netns testns link set dev dummy0 down
+ $IP link set dev dummy0 down
set +e
echo " Both devices down"
- ip -netns testns route get fibmatch 203.0.113.1 &> /dev/null
+ $IP route get fibmatch 203.0.113.1 &> /dev/null
log_test $? 2 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:3::1 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
log_test $? 2 "IPv6 fibmatch"
- ip -netns testns link del dev dummy1
+ $IP link del dev dummy1
cleanup
}
@@ -264,55 +288,55 @@ fib_carrier_local_test()
setup
set -e
- ip -netns testns link set dev dummy0 carrier on
+ $IP link set dev dummy0 carrier on
set +e
echo " Start point"
- ip -netns testns route get fibmatch 198.51.100.1 &> /dev/null
+ $IP route get fibmatch 198.51.100.1 &> /dev/null
log_test $? 0 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:1::1 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
log_test $? 0 "IPv6 fibmatch"
- ip -netns testns route get fibmatch 198.51.100.1 | \
+ $IP route get fibmatch 198.51.100.1 | \
grep -q "linkdown"
log_test $? 1 "IPv4 - no linkdown flag"
- ip -netns testns -6 route get fibmatch 2001:db8:1::1 | \
+ $IP -6 route get fibmatch 2001:db8:1::1 | \
grep -q "linkdown"
log_test $? 1 "IPv6 - no linkdown flag"
set -e
- ip -netns testns link set dev dummy0 carrier off
+ $IP link set dev dummy0 carrier off
sleep 1
set +e
echo " Carrier off on nexthop"
- ip -netns testns route get fibmatch 198.51.100.1 &> /dev/null
+ $IP route get fibmatch 198.51.100.1 &> /dev/null
log_test $? 0 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:1::1 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
log_test $? 0 "IPv6 fibmatch"
- ip -netns testns route get fibmatch 198.51.100.1 | \
+ $IP route get fibmatch 198.51.100.1 | \
grep -q "linkdown"
log_test $? 1 "IPv4 - linkdown flag set"
- ip -netns testns -6 route get fibmatch 2001:db8:1::1 | \
+ $IP -6 route get fibmatch 2001:db8:1::1 | \
grep -q "linkdown"
log_test $? 1 "IPv6 - linkdown flag set"
set -e
- ip -netns testns address add 192.0.2.1/24 dev dummy0
- ip -netns testns -6 address add 2001:db8:2::1/64 dev dummy0
+ $IP address add 192.0.2.1/24 dev dummy0
+ $IP -6 address add 2001:db8:2::1/64 dev dummy0
set +e
echo " Route to local address with carrier down"
- ip -netns testns route get fibmatch 192.0.2.1 &> /dev/null
+ $IP route get fibmatch 192.0.2.1 &> /dev/null
log_test $? 0 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:2::1 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null
log_test $? 0 "IPv6 fibmatch"
- ip -netns testns route get fibmatch 192.0.2.1 | \
+ $IP route get fibmatch 192.0.2.1 | \
grep -q "linkdown"
log_test $? 1 "IPv4 linkdown flag set"
- ip -netns testns -6 route get fibmatch 2001:db8:2::1 | \
+ $IP -6 route get fibmatch 2001:db8:2::1 | \
grep -q "linkdown"
log_test $? 1 "IPv6 linkdown flag set"
@@ -329,54 +353,54 @@ fib_carrier_unicast_test()
setup
set -e
- ip -netns testns link set dev dummy0 carrier on
+ $IP link set dev dummy0 carrier on
set +e
echo " Start point"
- ip -netns testns route get fibmatch 198.51.100.2 &> /dev/null
+ $IP route get fibmatch 198.51.100.2 &> /dev/null
log_test $? 0 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:1::2 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
log_test $? 0 "IPv6 fibmatch"
- ip -netns testns route get fibmatch 198.51.100.2 | \
+ $IP route get fibmatch 198.51.100.2 | \
grep -q "linkdown"
log_test $? 1 "IPv4 no linkdown flag"
- ip -netns testns -6 route get fibmatch 2001:db8:1::2 | \
+ $IP -6 route get fibmatch 2001:db8:1::2 | \
grep -q "linkdown"
log_test $? 1 "IPv6 no linkdown flag"
set -e
- ip -netns testns link set dev dummy0 carrier off
+ $IP link set dev dummy0 carrier off
set +e
echo " Carrier down"
- ip -netns testns route get fibmatch 198.51.100.2 &> /dev/null
+ $IP route get fibmatch 198.51.100.2 &> /dev/null
log_test $? 0 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:1::2 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
log_test $? 0 "IPv6 fibmatch"
- ip -netns testns route get fibmatch 198.51.100.2 | \
+ $IP route get fibmatch 198.51.100.2 | \
grep -q "linkdown"
log_test $? 0 "IPv4 linkdown flag set"
- ip -netns testns -6 route get fibmatch 2001:db8:1::2 | \
+ $IP -6 route get fibmatch 2001:db8:1::2 | \
grep -q "linkdown"
log_test $? 0 "IPv6 linkdown flag set"
set -e
- ip -netns testns address add 192.0.2.1/24 dev dummy0
- ip -netns testns -6 address add 2001:db8:2::1/64 dev dummy0
+ $IP address add 192.0.2.1/24 dev dummy0
+ $IP -6 address add 2001:db8:2::1/64 dev dummy0
set +e
echo " Second address added with carrier down"
- ip -netns testns route get fibmatch 192.0.2.2 &> /dev/null
+ $IP route get fibmatch 192.0.2.2 &> /dev/null
log_test $? 0 "IPv4 fibmatch"
- ip -netns testns -6 route get fibmatch 2001:db8:2::2 &> /dev/null
+ $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null
log_test $? 0 "IPv6 fibmatch"
- ip -netns testns route get fibmatch 192.0.2.2 | \
+ $IP route get fibmatch 192.0.2.2 | \
grep -q "linkdown"
log_test $? 0 "IPv4 linkdown flag set"
- ip -netns testns -6 route get fibmatch 2001:db8:2::2 | \
+ $IP -6 route get fibmatch 2001:db8:2::2 | \
grep -q "linkdown"
log_test $? 0 "IPv6 linkdown flag set"
@@ -389,11 +413,168 @@ fib_carrier_test()
fib_carrier_unicast_test
}
+################################################################################
+# Tests on nexthop spec
+
+# run 'ip route add' with given spec
+add_rt()
+{
+ local desc="$1"
+ local erc=$2
+ local vrf=$3
+ local pfx=$4
+ local gw=$5
+ local dev=$6
+ local cmd out rc
+
+ [ "$vrf" = "-" ] && vrf="default"
+ [ -n "$gw" ] && gw="via $gw"
+ [ -n "$dev" ] && dev="dev $dev"
+
+ cmd="$IP route add vrf $vrf $pfx $gw $dev"
+ if [ "$VERBOSE" = "1" ]; then
+ printf "\n COMMAND: $cmd\n"
+ fi
+
+ out=$(eval $cmd 2>&1)
+ rc=$?
+ if [ "$VERBOSE" = "1" -a -n "$out" ]; then
+ echo " $out"
+ fi
+ log_test $rc $erc "$desc"
+}
+
+fib4_nexthop()
+{
+ echo
+ echo "IPv4 nexthop tests"
+
+ echo "<<< write me >>>"
+}
+
+fib6_nexthop()
+{
+ local lldummy=$(get_linklocal dummy0)
+ local llv1=$(get_linklocal dummy0)
+
+ if [ -z "$lldummy" ]; then
+ echo "Failed to get linklocal address for dummy0"
+ return 1
+ fi
+ if [ -z "$llv1" ]; then
+ echo "Failed to get linklocal address for veth1"
+ return 1
+ fi
+
+ echo
+ echo "IPv6 nexthop tests"
+
+ add_rt "Directly connected nexthop, unicast address" 0 \
+ - 2001:db8:101::/64 2001:db8:1::2
+ add_rt "Directly connected nexthop, unicast address with device" 0 \
+ - 2001:db8:102::/64 2001:db8:1::2 "dummy0"
+ add_rt "Gateway is linklocal address" 0 \
+ - 2001:db8:103::1/64 $llv1 "veth0"
+
+ # fails because LL address requires a device
+ add_rt "Gateway is linklocal address, no device" 2 \
+ - 2001:db8:104::1/64 $llv1
+
+ # local address can not be a gateway
+ add_rt "Gateway can not be local unicast address" 2 \
+ - 2001:db8:105::/64 2001:db8:1::1
+ add_rt "Gateway can not be local unicast address, with device" 2 \
+ - 2001:db8:106::/64 2001:db8:1::1 "dummy0"
+ add_rt "Gateway can not be a local linklocal address" 2 \
+ - 2001:db8:107::1/64 $lldummy "dummy0"
+
+ # VRF tests
+ add_rt "Gateway can be local address in a VRF" 0 \
+ - 2001:db8:108::/64 2001:db8:51::2
+ add_rt "Gateway can be local address in a VRF, with device" 0 \
+ - 2001:db8:109::/64 2001:db8:51::2 "veth0"
+ add_rt "Gateway can be local linklocal address in a VRF" 0 \
+ - 2001:db8:110::1/64 $llv1 "veth0"
+
+ add_rt "Redirect to VRF lookup" 0 \
+ - 2001:db8:111::/64 "" "red"
+
+ add_rt "VRF route, gateway can be local address in default VRF" 0 \
+ red 2001:db8:112::/64 2001:db8:51::1
+
+ # local address in same VRF fails
+ add_rt "VRF route, gateway can not be a local address" 2 \
+ red 2001:db8:113::1/64 2001:db8:2::1
+ add_rt "VRF route, gateway can not be a local addr with device" 2 \
+ red 2001:db8:114::1/64 2001:db8:2::1 "dummy1"
+}
+
+# Default VRF:
+# dummy0 - 198.51.100.1/24 2001:db8:1::1/64
+# veth0 - 192.0.2.1/24 2001:db8:51::1/64
+#
+# VRF red:
+# dummy1 - 192.168.2.1/24 2001:db8:2::1/64
+# veth1 - 192.0.2.2/24 2001:db8:51::2/64
+#
+# [ dummy0 veth0 ]--[ veth1 dummy1 ]
+
+fib_nexthop_test()
+{
+ setup
+
+ set -e
+
+ $IP -4 rule add pref 32765 table local
+ $IP -4 rule del pref 0
+ $IP -6 rule add pref 32765 table local
+ $IP -6 rule del pref 0
+
+ $IP link add red type vrf table 1
+ $IP link set red up
+ $IP -4 route add vrf red unreachable default metric 4278198272
+ $IP -6 route add vrf red unreachable default metric 4278198272
+
+ $IP link add veth0 type veth peer name veth1
+ $IP link set dev veth0 up
+ $IP address add 192.0.2.1/24 dev veth0
+ $IP -6 address add 2001:db8:51::1/64 dev veth0
+
+ $IP link set dev veth1 vrf red up
+ $IP address add 192.0.2.2/24 dev veth1
+ $IP -6 address add 2001:db8:51::2/64 dev veth1
+
+ $IP link add dummy1 type dummy
+ $IP link set dev dummy1 vrf red up
+ $IP address add 192.168.2.1/24 dev dummy1
+ $IP -6 address add 2001:db8:2::1/64 dev dummy1
+ set +e
+
+ sleep 1
+ fib4_nexthop
+ fib6_nexthop
+
+ (
+ $IP link del dev dummy1
+ $IP link del veth0
+ $IP link del red
+ ) 2>/dev/null
+ cleanup
+}
+
+################################################################################
+#
+
fib_test()
{
- fib_unreg_test
- fib_down_test
- fib_carrier_test
+ if [ -n "$TEST" ]; then
+ eval $TEST
+ else
+ fib_unreg_test
+ fib_down_test
+ fib_carrier_test
+ fib_nexthop_test
+ fi
}
if [ "$(id -u)" -ne 0 ];then