1*cd72e61bSNicolas Dichtel#!/bin/bash
2*cd72e61bSNicolas Dichtel# SPDX-License-Identifier: GPL-2.0
3*cd72e61bSNicolas Dichtel#
4*cd72e61bSNicolas Dichtel# ns: h1               | ns: h2
5*cd72e61bSNicolas Dichtel#   192.168.0.1/24     |
6*cd72e61bSNicolas Dichtel#            eth0      |
7*cd72e61bSNicolas Dichtel#                      |       192.168.1.1/32
8*cd72e61bSNicolas Dichtel#            veth0 <---|---> veth1
9*cd72e61bSNicolas Dichtel# Validate source address selection for route without gateway
10*cd72e61bSNicolas Dichtel
11*cd72e61bSNicolas DichtelPAUSE_ON_FAIL=no
12*cd72e61bSNicolas DichtelVERBOSE=0
13*cd72e61bSNicolas Dichtelret=0
14*cd72e61bSNicolas Dichtel
15*cd72e61bSNicolas Dichtel################################################################################
16*cd72e61bSNicolas Dichtel# helpers
17*cd72e61bSNicolas Dichtel
18*cd72e61bSNicolas Dichtellog_test()
19*cd72e61bSNicolas Dichtel{
20*cd72e61bSNicolas Dichtel	local rc=$1
21*cd72e61bSNicolas Dichtel	local expected=$2
22*cd72e61bSNicolas Dichtel	local msg="$3"
23*cd72e61bSNicolas Dichtel
24*cd72e61bSNicolas Dichtel	if [ ${rc} -eq ${expected} ]; then
25*cd72e61bSNicolas Dichtel		printf "TEST: %-60s  [ OK ]\n" "${msg}"
26*cd72e61bSNicolas Dichtel		nsuccess=$((nsuccess+1))
27*cd72e61bSNicolas Dichtel	else
28*cd72e61bSNicolas Dichtel		ret=1
29*cd72e61bSNicolas Dichtel		nfail=$((nfail+1))
30*cd72e61bSNicolas Dichtel		printf "TEST: %-60s  [FAIL]\n" "${msg}"
31*cd72e61bSNicolas Dichtel		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
32*cd72e61bSNicolas Dichtel			echo
33*cd72e61bSNicolas Dichtel			echo "hit enter to continue, 'q' to quit"
34*cd72e61bSNicolas Dichtel			read a
35*cd72e61bSNicolas Dichtel			[ "$a" = "q" ] && exit 1
36*cd72e61bSNicolas Dichtel		fi
37*cd72e61bSNicolas Dichtel	fi
38*cd72e61bSNicolas Dichtel
39*cd72e61bSNicolas Dichtel	[ "$VERBOSE" = "1" ] && echo
40*cd72e61bSNicolas Dichtel}
41*cd72e61bSNicolas Dichtel
42*cd72e61bSNicolas Dichtelrun_cmd()
43*cd72e61bSNicolas Dichtel{
44*cd72e61bSNicolas Dichtel	local cmd="$*"
45*cd72e61bSNicolas Dichtel	local out
46*cd72e61bSNicolas Dichtel	local rc
47*cd72e61bSNicolas Dichtel
48*cd72e61bSNicolas Dichtel	if [ "$VERBOSE" = "1" ]; then
49*cd72e61bSNicolas Dichtel		echo "COMMAND: $cmd"
50*cd72e61bSNicolas Dichtel	fi
51*cd72e61bSNicolas Dichtel
52*cd72e61bSNicolas Dichtel	out=$(eval $cmd 2>&1)
53*cd72e61bSNicolas Dichtel	rc=$?
54*cd72e61bSNicolas Dichtel	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
55*cd72e61bSNicolas Dichtel		echo "$out"
56*cd72e61bSNicolas Dichtel	fi
57*cd72e61bSNicolas Dichtel
58*cd72e61bSNicolas Dichtel	[ "$VERBOSE" = "1" ] && echo
59*cd72e61bSNicolas Dichtel
60*cd72e61bSNicolas Dichtel	return $rc
61*cd72e61bSNicolas Dichtel}
62*cd72e61bSNicolas Dichtel
63*cd72e61bSNicolas Dichtel################################################################################
64*cd72e61bSNicolas Dichtel# config
65*cd72e61bSNicolas Dichtelsetup()
66*cd72e61bSNicolas Dichtel{
67*cd72e61bSNicolas Dichtel	ip netns add h1
68*cd72e61bSNicolas Dichtel	ip -n h1 link set lo up
69*cd72e61bSNicolas Dichtel	ip netns add h2
70*cd72e61bSNicolas Dichtel	ip -n h2 link set lo up
71*cd72e61bSNicolas Dichtel
72*cd72e61bSNicolas Dichtel	# Add a fake eth0 to support an ip address
73*cd72e61bSNicolas Dichtel	ip -n h1 link add name eth0 type dummy
74*cd72e61bSNicolas Dichtel	ip -n h1 link set eth0 up
75*cd72e61bSNicolas Dichtel	ip -n h1 address add 192.168.0.1/24 dev eth0
76*cd72e61bSNicolas Dichtel
77*cd72e61bSNicolas Dichtel	# Configure veths (same @mac, arp off)
78*cd72e61bSNicolas Dichtel	ip -n h1 link add name veth0 type veth peer name veth1 netns h2
79*cd72e61bSNicolas Dichtel	ip -n h1 link set veth0 up
80*cd72e61bSNicolas Dichtel
81*cd72e61bSNicolas Dichtel	ip -n h2 link set veth1 up
82*cd72e61bSNicolas Dichtel
83*cd72e61bSNicolas Dichtel	# Configure @IP in the peer netns
84*cd72e61bSNicolas Dichtel	ip -n h2 address add 192.168.1.1/32 dev veth1
85*cd72e61bSNicolas Dichtel	ip -n h2 route add default dev veth1
86*cd72e61bSNicolas Dichtel
87*cd72e61bSNicolas Dichtel	# Add a nexthop without @gw and use it in a route
88*cd72e61bSNicolas Dichtel	ip -n h1 nexthop add id 1 dev veth0
89*cd72e61bSNicolas Dichtel	ip -n h1 route add 192.168.1.1 nhid 1
90*cd72e61bSNicolas Dichtel}
91*cd72e61bSNicolas Dichtel
92*cd72e61bSNicolas Dichtelcleanup()
93*cd72e61bSNicolas Dichtel{
94*cd72e61bSNicolas Dichtel	ip netns del h1 2>/dev/null
95*cd72e61bSNicolas Dichtel	ip netns del h2 2>/dev/null
96*cd72e61bSNicolas Dichtel}
97*cd72e61bSNicolas Dichtel
98*cd72e61bSNicolas Dichteltrap cleanup EXIT
99*cd72e61bSNicolas Dichtel
100*cd72e61bSNicolas Dichtel################################################################################
101*cd72e61bSNicolas Dichtel# main
102*cd72e61bSNicolas Dichtel
103*cd72e61bSNicolas Dichtelwhile getopts :pv o
104*cd72e61bSNicolas Dichteldo
105*cd72e61bSNicolas Dichtel	case $o in
106*cd72e61bSNicolas Dichtel		p) PAUSE_ON_FAIL=yes;;
107*cd72e61bSNicolas Dichtel		v) VERBOSE=1;;
108*cd72e61bSNicolas Dichtel	esac
109*cd72e61bSNicolas Dichteldone
110*cd72e61bSNicolas Dichtel
111*cd72e61bSNicolas Dichtelcleanup
112*cd72e61bSNicolas Dichtelsetup
113*cd72e61bSNicolas Dichtel
114*cd72e61bSNicolas Dichtelrun_cmd ip -netns h1 route get 192.168.1.1
115*cd72e61bSNicolas Dichtellog_test $? 0 "nexthop: get route with nexthop without gw"
116*cd72e61bSNicolas Dichtelrun_cmd ip netns exec h1 ping -c1 192.168.1.1
117*cd72e61bSNicolas Dichtellog_test $? 0 "nexthop: ping through nexthop without gw"
118*cd72e61bSNicolas Dichtel
119*cd72e61bSNicolas Dichtelexit $ret
120