blob: e99ae500f38735e56e15737dd42c8687fb733f4b (
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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
|
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Test unicast FIB offload indication.
lib_dir=$(dirname $0)/../../../net/forwarding
ALL_TESTS="
ipv6_route_add
ipv6_route_replace
ipv6_route_nexthop_group_share
ipv6_route_rate
"
NUM_NETIFS=4
source $lib_dir/lib.sh
source $lib_dir/devlink_lib.sh
tor1_create()
{
simple_if_init $tor1_p1 2001:db8:1::2/128 2001:db8:1::3/128
}
tor1_destroy()
{
simple_if_fini $tor1_p1 2001:db8:1::2/128 2001:db8:1::3/128
}
tor2_create()
{
simple_if_init $tor2_p1 2001:db8:2::2/128 2001:db8:2::3/128
}
tor2_destroy()
{
simple_if_fini $tor2_p1 2001:db8:2::2/128 2001:db8:2::3/128
}
spine_create()
{
ip link set dev $spine_p1 up
ip link set dev $spine_p2 up
__addr_add_del $spine_p1 add 2001:db8:1::1/64
__addr_add_del $spine_p2 add 2001:db8:2::1/64
}
spine_destroy()
{
__addr_add_del $spine_p2 del 2001:db8:2::1/64
__addr_add_del $spine_p1 del 2001:db8:1::1/64
ip link set dev $spine_p2 down
ip link set dev $spine_p1 down
}
ipv6_offload_check()
{
local pfx="$1"; shift
local expected_num=$1; shift
local num
# Try to avoid races with route offload
sleep .1
num=$(ip -6 route show match ${pfx} | grep "offload" | wc -l)
if [ $num -eq $expected_num ]; then
return 0
fi
return 1
}
ipv6_route_add_prefix()
{
RET=0
# Add a prefix route and check that it is offloaded.
ip -6 route add 2001:db8:3::/64 dev $spine_p1 metric 100
ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 1
check_err $? "prefix route not offloaded"
# Append an identical prefix route with an higher metric and check that
# offload indication did not change.
ip -6 route append 2001:db8:3::/64 dev $spine_p1 metric 200
ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 1
check_err $? "lowest metric not offloaded after append"
ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 200" 0
check_err $? "highest metric offloaded when should not"
# Prepend an identical prefix route with lower metric and check that
# it is offloaded and the others are not.
ip -6 route append 2001:db8:3::/64 dev $spine_p1 metric 10
ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 10" 1
check_err $? "lowest metric not offloaded after prepend"
ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 0
check_err $? "mid metric offloaded when should not"
ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 200" 0
check_err $? "highest metric offloaded when should not"
# Delete the routes and add the same route with a different nexthop
# device. Check that it is offloaded.
ip -6 route flush 2001:db8:3::/64 dev $spine_p1
ip -6 route add 2001:db8:3::/64 dev $spine_p2
ipv6_offload_check "2001:db8:3::/64 dev $spine_p2" 1
log_test "IPv6 prefix route add"
ip -6 route flush 2001:db8:3::/64
}
ipv6_route_add_mpath()
{
RET=0
# Add a multipath route and check that it is offloaded.
ip -6 route add 2001:db8:3::/64 metric 100 \
nexthop via 2001:db8:1::2 dev $spine_p1 \
nexthop via 2001:db8:2::2 dev $spine_p2
ipv6_offload_check "2001:db8:3::/64 metric 100" 2
check_err $? "multipath route not offloaded when should"
# Append another nexthop and check that it is offloaded as well.
ip -6 route append 2001:db8:3::/64 metric 100 \
nexthop via 2001:db8:1::3 dev $spine_p1
ipv6_offload_check "2001:db8:3::/64 metric 100" 3
check_err $? "appended nexthop not offloaded when should"
# Mimic route replace by removing the route and adding it back with
# only two nexthops.
ip -6 route del 2001:db8:3::/64
ip -6 route add 2001:db8:3::/64 metric 100 \
nexthop via 2001:db8:1::2 dev $spine_p1 \
nexthop via 2001:db8:2::2 dev $spine_p2
ipv6_offload_check "2001:db8:3::/64 metric 100" 2
check_err $? "multipath route not offloaded after delete & add"
# Append a nexthop with an higher metric and check that the offload
# indication did not change.
ip -6 route append 2001:db8:3::/64 metric 200 \
nexthop via 2001:db8:1::3 dev $spine_p1
ipv6_offload_check "2001:db8:3::/64 metric 100" 2
check_err $? "lowest metric not offloaded after append"
ipv6_offload_check "2001:db8:3::/64 metric 200" 0
check_err $? "highest metric offloaded when should not"
# Prepend a nexthop with a lower metric and check that it is offloaded
# and the others are not.
ip -6 route append 2001:db8:3::/64 metric 10 \
nexthop via 2001:db8:1::3 dev $spine_p1
ipv6_offload_check "2001:db8:3::/64 metric 10" 1
check_err $? "lowest metric not offloaded after prepend"
ipv6_offload_check "2001:db8:3::/64 metric 100" 0
check_err $? "mid metric offloaded when should not"
ipv6_offload_check "2001:db8:3::/64 metric 200" 0
check_err $? "highest metric offloaded when should not"
log_test "IPv6 multipath route add"
ip -6 route flush 2001:db8:3::/64
}
ipv6_route_add()
{
ipv6_route_add_prefix
ipv6_route_add_mpath
}
ipv6_route_replace()
{
RET=0
# Replace prefix route with prefix route.
ip -6 route add 2001:db8:3::/64 metric 100 dev $spine_p1
ipv6_offload_check "2001:db8:3::/64 metric 100" 1
check_err $? "prefix route not offloaded when should"
ip -6 route replace 2001:db8:3::/64 metric 100 dev $spine_p2
ipv6_offload_check "2001:db8:3::/64 metric 100" 1
check_err $? "prefix route not offloaded after replace"
# Replace prefix route with multipath route.
ip -6 route replace 2001:db8:3::/64 metric 100 \
nexthop via 2001:db8:1::2 dev $spine_p1 \
nexthop via 2001:db8:2::2 dev $spine_p2
ipv6_offload_check "2001:db8:3::/64 metric 100" 2
check_err $? "multipath route not offloaded after replace"
# Replace multipath route with prefix route. A prefix route cannot
# replace a multipath route, so it is appended.
ip -6 route replace 2001:db8:3::/64 metric 100 dev $spine_p1
ipv6_offload_check "2001:db8:3::/64 metric 100 dev $spine_p1" 0
check_err $? "prefix route offloaded after 'replacing' multipath route"
ipv6_offload_check "2001:db8:3::/64 metric 100" 2
check_err $? "multipath route not offloaded after being 'replaced' by prefix route"
# Replace multipath route with multipath route.
ip -6 route replace 2001:db8:3::/64 metric 100 \
nexthop via 2001:db8:1::3 dev $spine_p1 \
nexthop via 2001:db8:2::3 dev $spine_p2
ipv6_offload_check "2001:db8:3::/64 metric 100" 2
check_err $? "multipath route not offloaded after replacing multipath route"
# Replace a non-existing multipath route with a multipath route and
# check that it is appended and not offloaded.
ip -6 route replace 2001:db8:3::/64 metric 200 \
nexthop via 2001:db8:1::3 dev $spine_p1 \
nexthop via 2001:db8:2::3 dev $spine_p2
ipv6_offload_check "2001:db8:3::/64 metric 100" 2
check_err $? "multipath route not offloaded after non-existing route was 'replaced'"
ipv6_offload_check "2001:db8:3::/64 metric 200" 0
check_err $? "multipath route offloaded after 'replacing' non-existing route"
log_test "IPv6 route replace"
ip -6 route flush 2001:db8:3::/64
}
ipv6_route_nexthop_group_share()
{
RET=0
# The driver consolidates identical nexthop groups in order to reduce
# the resource usage in its adjacency table. Check that the deletion
# of one multipath route using the group does not affect the other.
ip -6 route add 2001:db8:3::/64 \
nexthop via 2001:db8:1::2 dev $spine_p1 \
nexthop via 2001:db8:2::2 dev $spine_p2
ip -6 route add 2001:db8:4::/64 \
nexthop via 2001:db8:1::2 dev $spine_p1 \
nexthop via 2001:db8:2::2 dev $spine_p2
ipv6_offload_check "2001:db8:3::/64" 2
check_err $? "multipath route not offloaded when should"
ipv6_offload_check "2001:db8:4::/64" 2
check_err $? "multipath route not offloaded when should"
ip -6 route del 2001:db8:3::/64
ipv6_offload_check "2001:db8:4::/64" 2
check_err $? "multipath route not offloaded after deletion of route sharing the nexthop group"
# Check that after unsharing a nexthop group the routes are still
# marked as offloaded.
ip -6 route add 2001:db8:3::/64 \
nexthop via 2001:db8:1::2 dev $spine_p1 \
nexthop via 2001:db8:2::2 dev $spine_p2
ip -6 route del 2001:db8:4::/64 \
nexthop via 2001:db8:1::2 dev $spine_p1
ipv6_offload_check "2001:db8:4::/64" 1
check_err $? "singlepath route not offloaded after unsharing the nexthop group"
ipv6_offload_check "2001:db8:3::/64" 2
check_err $? "multipath route not offloaded after unsharing the nexthop group"
log_test "IPv6 nexthop group sharing"
ip -6 route flush 2001:db8:3::/64
ip -6 route flush 2001:db8:4::/64
}
ipv6_route_rate()
{
local batch_dir=$(mktemp -d)
local num_rts=$((40 * 1024))
local num_nhs=16
local total
local start
local diff
local end
local nhs
local i
RET=0
# Prepare 40K /64 multipath routes with 16 nexthops each and check how
# long it takes to add them. A limit of 60 seconds is set. It is much
# higher than insertion should take and meant to flag a serious
# regression.
total=$((nums_nhs * num_rts))
for i in $(seq 1 $num_nhs); do
ip -6 address add 2001:db8:1::10:$i/128 dev $tor1_p1
nexthops+=" nexthop via 2001:db8:1::10:$i dev $spine_p1"
done
for i in $(seq 1 $num_rts); do
echo "route add 2001:db8:8:$(printf "%x" $i)::/64$nexthops" \
>> $batch_dir/add.batch
echo "route del 2001:db8:8:$(printf "%x" $i)::/64$nexthops" \
>> $batch_dir/del.batch
done
start=$(date +%s.%N)
ip -batch $batch_dir/add.batch
count=$(ip -6 route show | grep offload | wc -l)
while [ $count -lt $total ]; do
sleep .01
count=$(ip -6 route show | grep offload | wc -l)
done
end=$(date +%s.%N)
diff=$(echo "$end - $start" | bc -l)
test "$(echo "$diff > 60" | bc -l)" -eq 0
check_err $? "route insertion took too long"
log_info "inserted $num_rts routes in $diff seconds"
log_test "IPv6 routes insertion rate"
ip -batch $batch_dir/del.batch
for i in $(seq 1 $num_nhs); do
ip -6 address del 2001:db8:1::10:$i/128 dev $tor1_p1
done
rm -rf $batch_dir
}
setup_prepare()
{
spine_p1=${NETIFS[p1]}
tor1_p1=${NETIFS[p2]}
spine_p2=${NETIFS[p3]}
tor2_p1=${NETIFS[p4]}
vrf_prepare
forwarding_enable
tor1_create
tor2_create
spine_create
}
cleanup()
{
pre_cleanup
spine_destroy
tor2_destroy
tor1_destroy
forwarding_restore
vrf_cleanup
}
trap cleanup EXIT
setup_prepare
setup_wait
tests_run
exit $EXIT_STATUS
|