1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Tests sysctl options {arp,ndisc}_evict_nocarrier={0,1}
5#
6# Create a veth pair and set IPs/routes on both. Then ping to establish
7# an entry in the ARP/ND table. Depending on the test set sysctl option to
8# 1 or 0. Set remote veth down which will cause local veth to go into a no
9# carrier state. Depending on the test check the ARP/ND table:
10#
11# {arp,ndisc}_evict_nocarrier=1 should contain no ARP/ND after no carrier
12# {arp,ndisc}_evict_nocarrer=0 should still contain the single ARP/ND entry
13#
14
15source lib.sh
16
17readonly V4_ADDR0=10.0.10.1
18readonly V4_ADDR1=10.0.10.2
19readonly V6_ADDR0=2001:db8:91::1
20readonly V6_ADDR1=2001:db8:91::2
21nsid=100
22ret=0
23
24cleanup_v6()
25{
26    cleanup_ns ${me} ${peer}
27
28    sysctl -w net.ipv6.conf.veth1.ndisc_evict_nocarrier=1 >/dev/null 2>&1
29    sysctl -w net.ipv6.conf.all.ndisc_evict_nocarrier=1 >/dev/null 2>&1
30}
31
32setup_v6() {
33    setup_ns me peer
34
35    IP="ip -netns ${me}"
36
37    $IP li add veth1 type veth peer name veth2
38    $IP li set veth1 up
39    $IP -6 addr add $V6_ADDR0/64 dev veth1 nodad
40    $IP li set veth2 netns ${peer} up
41    ip -netns ${peer} -6 addr add $V6_ADDR1/64 dev veth2 nodad
42
43    ip netns exec ${me} sysctl -w $1 >/dev/null 2>&1
44
45    # Establish an ND cache entry
46    ip netns exec ${me} ping -6 -c1 -Iveth1 $V6_ADDR1 >/dev/null 2>&1
47    # Should have the veth1 entry in ND table
48    ip netns exec ${me} ip -6 neigh get $V6_ADDR1 dev veth1 >/dev/null 2>&1
49    if [ $? -ne 0 ]; then
50        cleanup_v6
51        echo "failed"
52        exit 1
53    fi
54
55    # Set veth2 down, which will put veth1 in NOCARRIER state
56    ip netns exec ${peer} ip link set veth2 down
57}
58
59setup_v4() {
60    setup_ns PEER_NS
61    ip link add name veth0 type veth peer name veth1
62    ip link set dev veth0 up
63    ip link set dev veth1 netns "${PEER_NS}"
64    ip netns exec "${PEER_NS}" ip link set dev veth1 up
65    ip addr add $V4_ADDR0/24 dev veth0
66    ip netns exec "${PEER_NS}" ip addr add $V4_ADDR1/24 dev veth1
67    ip netns exec ${PEER_NS} ip route add default via $V4_ADDR1 dev veth1
68    ip route add default via $V4_ADDR0 dev veth0
69
70    sysctl -w "$1" >/dev/null 2>&1
71
72    # Establish an ARP cache entry
73    ping -c1 -I veth0 $V4_ADDR1 -q >/dev/null 2>&1
74    # Should have the veth1 entry in ARP table
75    ip neigh get $V4_ADDR1 dev veth0 >/dev/null 2>&1
76    if [ $? -ne 0 ]; then
77        cleanup_v4
78        echo "failed"
79        exit 1
80    fi
81
82    # Set veth1 down, which will put veth0 in NOCARRIER state
83    ip netns exec "${PEER_NS}" ip link set veth1 down
84}
85
86cleanup_v4() {
87    ip neigh flush dev veth0
88    ip link del veth0
89    cleanup_ns $PEER_NS
90
91    sysctl -w net.ipv4.conf.veth0.arp_evict_nocarrier=1 >/dev/null 2>&1
92    sysctl -w net.ipv4.conf.all.arp_evict_nocarrier=1 >/dev/null 2>&1
93}
94
95# Run test when arp_evict_nocarrier = 1 (default).
96run_arp_evict_nocarrier_enabled() {
97    echo "run arp_evict_nocarrier=1 test"
98    setup_v4 "net.ipv4.conf.veth0.arp_evict_nocarrier=1"
99
100    # ARP table should be empty
101    ip neigh get $V4_ADDR1 dev veth0 >/dev/null 2>&1
102
103    if [ $? -eq 0 ];then
104        echo "failed"
105        ret=1
106    else
107        echo "ok"
108    fi
109
110    cleanup_v4
111}
112
113# Run test when arp_evict_nocarrier = 0
114run_arp_evict_nocarrier_disabled() {
115    echo "run arp_evict_nocarrier=0 test"
116    setup_v4 "net.ipv4.conf.veth0.arp_evict_nocarrier=0"
117
118    # ARP table should still contain the entry
119    ip neigh get $V4_ADDR1 dev veth0 >/dev/null 2>&1
120
121    if [ $? -eq 0 ];then
122        echo "ok"
123    else
124        echo "failed"
125        ret=1
126    fi
127
128    cleanup_v4
129}
130
131run_arp_evict_nocarrier_disabled_all() {
132    echo "run all.arp_evict_nocarrier=0 test"
133    setup_v4 "net.ipv4.conf.all.arp_evict_nocarrier=0"
134
135    # ARP table should still contain the entry
136    ip neigh get $V4_ADDR1 dev veth0 >/dev/null 2>&1
137
138    if [ $? -eq 0 ];then
139        echo "ok"
140    else
141        echo "failed"
142    fi
143
144    cleanup_v4
145}
146
147run_ndisc_evict_nocarrier_enabled() {
148    echo "run ndisc_evict_nocarrier=1 test"
149
150    setup_v6 "net.ipv6.conf.veth1.ndisc_evict_nocarrier=1"
151
152    ip netns exec ${me} ip -6 neigh get $V6_ADDR1 dev veth1 >/dev/null 2>&1
153
154    if [ $? -eq 0 ];then
155        echo "failed"
156        ret=1
157    else
158        echo "ok"
159    fi
160
161    cleanup_v6
162}
163
164run_ndisc_evict_nocarrier_disabled() {
165    echo "run ndisc_evict_nocarrier=0 test"
166
167    setup_v6 "net.ipv6.conf.veth1.ndisc_evict_nocarrier=0"
168
169    ip netns exec ${me} ip -6 neigh get $V6_ADDR1 dev veth1 >/dev/null 2>&1
170
171    if [ $? -eq 0 ];then
172        echo "ok"
173    else
174        echo "failed"
175        ret=1
176    fi
177
178    cleanup_v6
179}
180
181run_ndisc_evict_nocarrier_disabled_all() {
182    echo "run all.ndisc_evict_nocarrier=0 test"
183
184    setup_v6 "net.ipv6.conf.all.ndisc_evict_nocarrier=0"
185
186    ip netns exec ${me} ip -6 neigh get $V6_ADDR1 dev veth1 >/dev/null 2>&1
187
188    if [ $? -eq 0 ];then
189        echo "ok"
190    else
191        echo "failed"
192        ret=1
193    fi
194
195    cleanup_v6
196}
197
198run_all_tests() {
199    run_arp_evict_nocarrier_enabled
200    run_arp_evict_nocarrier_disabled
201    run_arp_evict_nocarrier_disabled_all
202    run_ndisc_evict_nocarrier_enabled
203    run_ndisc_evict_nocarrier_disabled
204    run_ndisc_evict_nocarrier_disabled_all
205}
206
207if [ "$(id -u)" -ne 0 ];then
208	echo "SKIP: Need root privileges"
209	exit $ksft_skip;
210fi
211
212run_all_tests
213exit $ret
214