Skip to content

Commit ccb52a9

Browse files
committed
Merge branch 'gre-reapply-ipv6-link-local-address-generation-fix'
Guillaume Nault says: ==================== gre: Reapply IPv6 link-local address generation fix. Reintroduce the IPv6 link-local address generation fix for GRE and its kernel selftest. These patches were introduced by merge commit b3fc592 ("Merge branch 'gre-fix-regressions-in-ipv6-link-local-address-generation'") but have been reverted by commit 8417db0 ("Merge branch 'gre-revert-ipv6-link-local-address-fix'"), because it uncovered another bug in multipath routing. Now that this bug has been investigated and fixed, we can apply the GRE link-local address fix and its kernel selftest again. For convenience, here's the original cover letter: IPv6 link-local address generation has some special cases for GRE devices. This has led to several regressions in the past, and some of them are still not fixed. This series fixes the remaining problems, like the ipv6.conf.<dev>.addr_gen_mode sysctl being ignored and the router discovery process not being started (see details in patch 1). To avoid any further regressions, patch 2 adds selftests covering IPv4 and IPv6 gre/gretap devices with all combinations of currently supported addr_gen_mode values. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents c360eb0 + b6a6006 commit ccb52a9

File tree

3 files changed

+187
-6
lines changed

3 files changed

+187
-6
lines changed

net/ipv6/addrconf.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3214,16 +3214,13 @@ static void add_v4_addrs(struct inet6_dev *idev)
32143214
struct in6_addr addr;
32153215
struct net_device *dev;
32163216
struct net *net = dev_net(idev->dev);
3217-
int scope, plen, offset = 0;
3217+
int scope, plen;
32183218
u32 pflags = 0;
32193219

32203220
ASSERT_RTNL();
32213221

32223222
memset(&addr, 0, sizeof(struct in6_addr));
3223-
/* in case of IP6GRE the dev_addr is an IPv6 and therefore we use only the last 4 bytes */
3224-
if (idev->dev->addr_len == sizeof(struct in6_addr))
3225-
offset = sizeof(struct in6_addr) - 4;
3226-
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4);
3223+
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
32273224

32283225
if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) {
32293226
scope = IPV6_ADDR_COMPATv4;
@@ -3534,7 +3531,13 @@ static void addrconf_gre_config(struct net_device *dev)
35343531
return;
35353532
}
35363533

3537-
if (dev->type == ARPHRD_ETHER) {
3534+
/* Generate the IPv6 link-local address using addrconf_addr_gen(),
3535+
* unless we have an IPv4 GRE device not bound to an IP address and
3536+
* which is in EUI64 mode (as __ipv6_isatap_ifid() would fail in this
3537+
* case). Such devices fall back to add_v4_addrs() instead.
3538+
*/
3539+
if (!(dev->type == ARPHRD_IPGRE && *(__be32 *)dev->dev_addr == 0 &&
3540+
idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)) {
35383541
addrconf_addr_gen(idev, true);
35393542
return;
35403543
}

tools/testing/selftests/net/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ TEST_PROGS += veth.sh
3131
TEST_PROGS += ioam6.sh
3232
TEST_PROGS += gro.sh
3333
TEST_PROGS += gre_gso.sh
34+
TEST_PROGS += gre_ipv6_lladdr.sh
3435
TEST_PROGS += cmsg_so_mark.sh
3536
TEST_PROGS += cmsg_so_priority.sh
3637
TEST_PROGS += test_so_rcv.sh
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-2.0
3+
4+
source ./lib.sh
5+
6+
PAUSE_ON_FAIL="no"
7+
8+
# The trap function handler
9+
#
10+
exit_cleanup_all()
11+
{
12+
cleanup_all_ns
13+
14+
exit "${EXIT_STATUS}"
15+
}
16+
17+
# Add fake IPv4 and IPv6 networks on the loopback device, to be used as
18+
# underlay by future GRE devices.
19+
#
20+
setup_basenet()
21+
{
22+
ip -netns "${NS0}" link set dev lo up
23+
ip -netns "${NS0}" address add dev lo 192.0.2.10/24
24+
ip -netns "${NS0}" address add dev lo 2001:db8::10/64 nodad
25+
}
26+
27+
# Check if network device has an IPv6 link-local address assigned.
28+
#
29+
# Parameters:
30+
#
31+
# * $1: The network device to test
32+
# * $2: An extra regular expression that should be matched (to verify the
33+
# presence of extra attributes)
34+
# * $3: The expected return code from grep (to allow checking the absence of
35+
# a link-local address)
36+
# * $4: The user visible name for the scenario being tested
37+
#
38+
check_ipv6_ll_addr()
39+
{
40+
local DEV="$1"
41+
local EXTRA_MATCH="$2"
42+
local XRET="$3"
43+
local MSG="$4"
44+
45+
RET=0
46+
set +e
47+
ip -netns "${NS0}" -6 address show dev "${DEV}" scope link | grep "fe80::" | grep -q "${EXTRA_MATCH}"
48+
check_err_fail "${XRET}" $? ""
49+
log_test "${MSG}"
50+
set -e
51+
}
52+
53+
# Create a GRE device and verify that it gets an IPv6 link-local address as
54+
# expected.
55+
#
56+
# Parameters:
57+
#
58+
# * $1: The device type (gre, ip6gre, gretap or ip6gretap)
59+
# * $2: The local underlay IP address (can be an IPv4, an IPv6 or "any")
60+
# * $3: The remote underlay IP address (can be an IPv4, an IPv6 or "any")
61+
# * $4: The IPv6 interface identifier generation mode to use for the GRE
62+
# device (eui64, none, stable-privacy or random).
63+
#
64+
test_gre_device()
65+
{
66+
local GRE_TYPE="$1"
67+
local LOCAL_IP="$2"
68+
local REMOTE_IP="$3"
69+
local MODE="$4"
70+
local ADDR_GEN_MODE
71+
local MATCH_REGEXP
72+
local MSG
73+
74+
ip link add netns "${NS0}" name gretest type "${GRE_TYPE}" local "${LOCAL_IP}" remote "${REMOTE_IP}"
75+
76+
case "${MODE}" in
77+
"eui64")
78+
ADDR_GEN_MODE=0
79+
MATCH_REGEXP=""
80+
MSG="${GRE_TYPE}, mode: 0 (EUI64), ${LOCAL_IP} -> ${REMOTE_IP}"
81+
XRET=0
82+
;;
83+
"none")
84+
ADDR_GEN_MODE=1
85+
MATCH_REGEXP=""
86+
MSG="${GRE_TYPE}, mode: 1 (none), ${LOCAL_IP} -> ${REMOTE_IP}"
87+
XRET=1 # No link-local address should be generated
88+
;;
89+
"stable-privacy")
90+
ADDR_GEN_MODE=2
91+
MATCH_REGEXP="stable-privacy"
92+
MSG="${GRE_TYPE}, mode: 2 (stable privacy), ${LOCAL_IP} -> ${REMOTE_IP}"
93+
XRET=0
94+
# Initialise stable_secret (required for stable-privacy mode)
95+
ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.stable_secret="2001:db8::abcd"
96+
;;
97+
"random")
98+
ADDR_GEN_MODE=3
99+
MATCH_REGEXP="stable-privacy"
100+
MSG="${GRE_TYPE}, mode: 3 (random), ${LOCAL_IP} -> ${REMOTE_IP}"
101+
XRET=0
102+
;;
103+
esac
104+
105+
# Check that IPv6 link-local address is generated when device goes up
106+
ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode="${ADDR_GEN_MODE}"
107+
ip -netns "${NS0}" link set dev gretest up
108+
check_ipv6_ll_addr gretest "${MATCH_REGEXP}" "${XRET}" "config: ${MSG}"
109+
110+
# Now disable link-local address generation
111+
ip -netns "${NS0}" link set dev gretest down
112+
ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode=1
113+
ip -netns "${NS0}" link set dev gretest up
114+
115+
# Check that link-local address generation works when re-enabled while
116+
# the device is already up
117+
ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode="${ADDR_GEN_MODE}"
118+
check_ipv6_ll_addr gretest "${MATCH_REGEXP}" "${XRET}" "update: ${MSG}"
119+
120+
ip -netns "${NS0}" link del dev gretest
121+
}
122+
123+
test_gre4()
124+
{
125+
local GRE_TYPE
126+
local MODE
127+
128+
for GRE_TYPE in "gre" "gretap"; do
129+
printf "\n####\nTesting IPv6 link-local address generation on ${GRE_TYPE} devices\n####\n\n"
130+
131+
for MODE in "eui64" "none" "stable-privacy" "random"; do
132+
test_gre_device "${GRE_TYPE}" 192.0.2.10 192.0.2.11 "${MODE}"
133+
test_gre_device "${GRE_TYPE}" any 192.0.2.11 "${MODE}"
134+
test_gre_device "${GRE_TYPE}" 192.0.2.10 any "${MODE}"
135+
done
136+
done
137+
}
138+
139+
test_gre6()
140+
{
141+
local GRE_TYPE
142+
local MODE
143+
144+
for GRE_TYPE in "ip6gre" "ip6gretap"; do
145+
printf "\n####\nTesting IPv6 link-local address generation on ${GRE_TYPE} devices\n####\n\n"
146+
147+
for MODE in "eui64" "none" "stable-privacy" "random"; do
148+
test_gre_device "${GRE_TYPE}" 2001:db8::10 2001:db8::11 "${MODE}"
149+
test_gre_device "${GRE_TYPE}" any 2001:db8::11 "${MODE}"
150+
test_gre_device "${GRE_TYPE}" 2001:db8::10 any "${MODE}"
151+
done
152+
done
153+
}
154+
155+
usage()
156+
{
157+
echo "Usage: $0 [-p]"
158+
exit 1
159+
}
160+
161+
while getopts :p o
162+
do
163+
case $o in
164+
p) PAUSE_ON_FAIL="yes";;
165+
*) usage;;
166+
esac
167+
done
168+
169+
setup_ns NS0
170+
171+
set -e
172+
trap exit_cleanup_all EXIT
173+
174+
setup_basenet
175+
176+
test_gre4
177+
test_gre6

0 commit comments

Comments
 (0)