Skip to content

Commit b3fc592

Browse files
author
Paolo Abeni
committed
Merge branch 'gre-fix-regressions-in-ipv6-link-local-address-generation'
Guillaume Nault says: ==================== gre: Fix regressions in IPv6 link-local address generation. 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/cover.1741375285.git.gnault@redhat.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2 parents 83d2fe6 + 6f50175 commit b3fc592

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
@@ -3209,16 +3209,13 @@ static void add_v4_addrs(struct inet6_dev *idev)
32093209
struct in6_addr addr;
32103210
struct net_device *dev;
32113211
struct net *net = dev_net(idev->dev);
3212-
int scope, plen, offset = 0;
3212+
int scope, plen;
32133213
u32 pflags = 0;
32143214

32153215
ASSERT_RTNL();
32163216

32173217
memset(&addr, 0, sizeof(struct in6_addr));
3218-
/* in case of IP6GRE the dev_addr is an IPv6 and therefore we use only the last 4 bytes */
3219-
if (idev->dev->addr_len == sizeof(struct in6_addr))
3220-
offset = sizeof(struct in6_addr) - 4;
3221-
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4);
3218+
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
32223219

32233220
if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) {
32243221
scope = IPV6_ADDR_COMPATv4;
@@ -3529,7 +3526,13 @@ static void addrconf_gre_config(struct net_device *dev)
35293526
return;
35303527
}
35313528

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

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 += cmsg_time.sh cmsg_ipv6.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)