summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/net/arp_ndisc_evict_nocarrier.sh
blob: 4a110bb01e53e7c0155a7bf0e32a6817d9161517 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Tests sysctl options {arp,ndisc}_evict_nocarrier={0,1}
#
# Create a veth pair and set IPs/routes on both. Then ping to establish
# an entry in the ARP/ND table. Depending on the test set sysctl option to
# 1 or 0. Set remote veth down which will cause local veth to go into a no
# carrier state. Depending on the test check the ARP/ND table:
#
# {arp,ndisc}_evict_nocarrier=1 should contain no ARP/ND after no carrier
# {arp,ndisc}_evict_nocarrer=0 should still contain the single ARP/ND entry
#

readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)"
readonly V4_ADDR0=10.0.10.1
readonly V4_ADDR1=10.0.10.2
readonly V6_ADDR0=2001:db8:91::1
readonly V6_ADDR1=2001:db8:91::2
nsid=100
ret=0

cleanup_v6()
{
    ip netns del me
    ip netns del peer

    sysctl -w net.ipv6.conf.veth1.ndisc_evict_nocarrier=1 >/dev/null 2>&1
    sysctl -w net.ipv6.conf.all.ndisc_evict_nocarrier=1 >/dev/null 2>&1
}

create_ns()
{
    local n=${1}

    ip netns del ${n} 2>/dev/null

    ip netns add ${n}
    ip netns set ${n} $((nsid++))
    ip -netns ${n} link set lo up
}


setup_v6() {
    create_ns me
    create_ns peer

    IP="ip -netns me"

    $IP li add veth1 type veth peer name veth2
    $IP li set veth1 up
    $IP -6 addr add $V6_ADDR0/64 dev veth1 nodad
    $IP li set veth2 netns peer up
    ip -netns peer -6 addr add $V6_ADDR1/64 dev veth2 nodad

    ip netns exec me sysctl -w $1 >/dev/null 2>&1

    # Establish an ND cache entry
    ip netns exec me ping -6 -c1 -Iveth1 $V6_ADDR1 >/dev/null 2>&1
    # Should have the veth1 entry in ND table
    ip netns exec me ip -6 neigh get $V6_ADDR1 dev veth1 >/dev/null 2>&1
    if [ $? -ne 0 ]; then
        cleanup_v6
        echo "failed"
        exit 1
    fi

    # Set veth2 down, which will put veth1 in NOCARRIER state
    ip netns exec peer ip link set veth2 down
}

setup_v4() {
    ip netns add "${PEER_NS}"
    ip link add name veth0 type veth peer name veth1
    ip link set dev veth0 up
    ip link set dev veth1 netns "${PEER_NS}"
    ip netns exec "${PEER_NS}" ip link set dev veth1 up
    ip addr add $V4_ADDR0/24 dev veth0
    ip netns exec "${PEER_NS}" ip addr add $V4_ADDR1/24 dev veth1
    ip netns exec ${PEER_NS} ip route add default via $V4_ADDR1 dev veth1
    ip route add default via $V4_ADDR0 dev veth0

    sysctl -w "$1" >/dev/null 2>&1

    # Establish an ARP cache entry
    ping -c1 -I veth0 $V4_ADDR1 -q >/dev/null 2>&1
    # Should have the veth1 entry in ARP table
    ip neigh get $V4_ADDR1 dev veth0 >/dev/null 2>&1
    if [ $? -ne 0 ]; then
        cleanup_v4
        echo "failed"
        exit 1
    fi

    # Set veth1 down, which will put veth0 in NOCARRIER state
    ip netns exec "${PEER_NS}" ip link set veth1 down
}

cleanup_v4() {
    ip neigh flush dev veth0
    ip link del veth0
    local -r ns="$(ip netns list|grep $PEER_NS)"
    [ -n "$ns" ] && ip netns del $ns 2>/dev/null

    sysctl -w net.ipv4.conf.veth0.arp_evict_nocarrier=1 >/dev/null 2>&1
    sysctl -w net.ipv4.conf.all.arp_evict_nocarrier=1 >/dev/null 2>&1
}

# Run test when arp_evict_nocarrier = 1 (default).
run_arp_evict_nocarrier_enabled() {
    echo "run arp_evict_nocarrier=1 test"
    setup_v4 "net.ipv4.conf.veth0.arp_evict_nocarrier=1"

    # ARP table should be empty
    ip neigh get $V4_ADDR1 dev veth0 >/dev/null 2>&1

    if [ $? -eq 0 ];then
        echo "failed"
        ret=1
    else
        echo "ok"
    fi

    cleanup_v4
}

# Run test when arp_evict_nocarrier = 0
run_arp_evict_nocarrier_disabled() {
    echo "run arp_evict_nocarrier=0 test"
    setup_v4 "net.ipv4.conf.veth0.arp_evict_nocarrier=0"

    # ARP table should still contain the entry
    ip neigh get $V4_ADDR1 dev veth0 >/dev/null 2>&1

    if [ $? -eq 0 ];then
        echo "ok"
    else
        echo "failed"
        ret=1
    fi

    cleanup_v4
}

run_arp_evict_nocarrier_disabled_all() {
    echo "run all.arp_evict_nocarrier=0 test"
    setup_v4 "net.ipv4.conf.all.arp_evict_nocarrier=0"

    # ARP table should still contain the entry
    ip neigh get $V4_ADDR1 dev veth0 >/dev/null 2>&1

    if [ $? -eq 0 ];then
        echo "ok"
    else
        echo "failed"
    fi

    cleanup_v4
}

run_ndisc_evict_nocarrier_enabled() {
    echo "run ndisc_evict_nocarrier=1 test"

    setup_v6 "net.ipv6.conf.veth1.ndisc_evict_nocarrier=1"

    ip netns exec me ip -6 neigh get $V6_ADDR1 dev veth1 >/dev/null 2>&1

    if [ $? -eq 0 ];then
        echo "failed"
        ret=1
    else
        echo "ok"
    fi

    cleanup_v6
}

run_ndisc_evict_nocarrier_disabled() {
    echo "run ndisc_evict_nocarrier=0 test"

    setup_v6 "net.ipv6.conf.veth1.ndisc_evict_nocarrier=0"

    ip netns exec me ip -6 neigh get $V6_ADDR1 dev veth1 >/dev/null 2>&1

    if [ $? -eq 0 ];then
        echo "ok"
    else
        echo "failed"
        ret=1
    fi

    cleanup_v6
}

run_ndisc_evict_nocarrier_disabled_all() {
    echo "run all.ndisc_evict_nocarrier=0 test"

    setup_v6 "net.ipv6.conf.all.ndisc_evict_nocarrier=0"

    ip netns exec me ip -6 neigh get $V6_ADDR1 dev veth1 >/dev/null 2>&1

    if [ $? -eq 0 ];then
        echo "ok"
    else
        echo "failed"
        ret=1
    fi

    cleanup_v6
}

run_all_tests() {
    run_arp_evict_nocarrier_enabled
    run_arp_evict_nocarrier_disabled
    run_arp_evict_nocarrier_disabled_all
    run_ndisc_evict_nocarrier_enabled
    run_ndisc_evict_nocarrier_disabled
    run_ndisc_evict_nocarrier_disabled_all
}

if [ "$(id -u)" -ne 0 ];then
	echo "SKIP: Need root privileges"
	exit $ksft_skip;
fi

run_all_tests
exit $ret