Skip to content

Commit

Permalink
Merge pull request #2353 from pqarmitage/updates
Browse files Browse the repository at this point in the history
Handle failure to add IPv6 link-local addres to a VMAC
  • Loading branch information
pqarmitage authored Oct 15, 2023
2 parents fd03602 + e73702a commit 1646a2a
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 24 deletions.
8 changes: 8 additions & 0 deletions keepalived/core/keepalived_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1184,6 +1184,14 @@ netlink_if_address_filter(__attribute__((unused)) struct sockaddr_nl *snl, struc
IF_ISUP(ifp)) &&
#endif
(!__test_bit(VRRP_FLAG_SADDR_FROM_CONFIG, &vrrp->flags) || is_tracking_saddr)) {
/* Don't attempt to send an IPv6 advert if no address on the interface */
if (vrrp->saddr.ss_family == AF_INET6
#ifdef _HAVE_VRRP_VMAC_
&& !__test_bit(VRRP_VMAC_XMITBASE_BIT, &vrrp->flags)
#endif
)
vrrp->saddr.ss_family = AF_UNSPEC;

down_instance(vrrp);
vrrp->saddr.ss_family = AF_UNSPEC;
}
Expand Down
15 changes: 11 additions & 4 deletions keepalived/vrrp/vrrp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1814,7 +1814,10 @@ vrrp_state_leave_master(vrrp_t * vrrp, bool advF)
}
else if (vrrp->wantstate == VRRP_STATE_FAULT) {
log_message(LOG_INFO, "(%s) Entering FAULT STATE", vrrp->iname);
vrrp_send_adv(vrrp, VRRP_PRIO_STOP);

/* If there is no address on the interface we cannot sent an IPv6 advert */
if (vrrp->family == AF_INET || vrrp->saddr.ss_family != AF_UNSPEC)
vrrp_send_adv(vrrp, VRRP_PRIO_STOP);
}
else {
log_message(LOG_INFO, "(%s) vrrp_state_leave_master called with invalid wantstate %d", vrrp->iname, vrrp->wantstate);
Expand Down Expand Up @@ -4292,8 +4295,7 @@ set_vrrp_src_addr(void)
if (vrrp->family == AF_INET) {
if (!(VRRP_CONFIGURED_IFP(vrrp))->sin_addr.s_addr)
addr_missing = true;
}
else {
} else {
#ifdef _HAVE_VRRP_VMAC_
if (!__test_bit(VRRP_VMAC_BIT, &vrrp->flags))
#endif
Expand All @@ -4311,8 +4313,13 @@ set_vrrp_src_addr(void)
else if (vrrp->family == AF_INET)
inet_ip4tosockaddr(&VRRP_CONFIGURED_IFP(vrrp)->sin_addr, &vrrp->saddr);
else if (vrrp->family == AF_INET6) {
#ifdef _HAVE_VRRP_VMAC_
if (!__test_bit(VRRP_VMAC_XMITBASE_BIT, &vrrp->flags) &&
(
#ifdef _HAVE_VRRP_IPVLAN_
if (__test_bit(VRRP_IPVLAN_BIT, &vrrp->flags)) {
__test_bit(VRRP_IPVLAN_BIT, &vrrp->flags) ||
#endif
__test_bit(VRRP_VMAC_BIT, &vrrp->flags))) {
if (!IN6_IS_ADDR_UNSPECIFIED(&vrrp->ifp->sin6_addr))
inet_ip6tosockaddr(&vrrp->ifp->sin6_addr, &vrrp->saddr);
} else
Expand Down
7 changes: 5 additions & 2 deletions keepalived/vrrp/vrrp_vmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ netlink_link_add_vmac(vrrp_t *vrrp, const interface_t *old_interface)
} req;
u_char if_ll_addr[ETH_ALEN];
bool update_interface = false;
bool ret = true;

if (!vrrp->ifp || __test_bit(VRRP_VMAC_UP_BIT, &vrrp->flags) || !vrrp->vrid)
return false;
Expand Down Expand Up @@ -495,8 +496,10 @@ netlink_link_add_vmac(vrrp_t *vrrp, const interface_t *old_interface)

if (vrrp->family == AF_INET6 &&
!__test_bit(VRRP_VMAC_XMITBASE_BIT, &vrrp->flags)) {
if (!set_link_local_address(vrrp) && create_interface)
if (!set_link_local_address(vrrp) && create_interface) {
log_message(LOG_INFO, "(%s) adding link-local address to %s failed", vrrp->iname, vrrp->ifp->ifname);
ret = false;
}
}

/* If the base interface does not implement IFF_UNICAST_FLT, for example
Expand Down Expand Up @@ -543,7 +546,7 @@ netlink_link_add_vmac(vrrp_t *vrrp, const interface_t *old_interface)
* as we progress */
kernel_netlink_poll();

return true;
return ret;
}

#ifdef _INCLUDE_UNUSED_CODE_
Expand Down
65 changes: 47 additions & 18 deletions test/mk_if
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ BR_NAME=br
CHAINS=
DEFAULT_CHAINS="TESTIN TESTOUT"
SCRIPT=
FIXED_LEN=0
NUM_LEN=

CMD=add
LOW=0
Expand All @@ -33,6 +35,7 @@ $0 - Usage: $0 CMD [OPTIONS]
-h Show this!
-f NUM First interface number
-l NUM Last interface number
-p fixed interface name lenths
-n "NS NS .." List of namespaces (default: high medium low default)
-b NS Specify namespace for bridge (default: medium)
-r NS Specify root namespace (default: default)
Expand All @@ -50,7 +53,7 @@ $0 - Usage: $0 CMD [OPTIONS]
EOF
}

while getopts ":hf:l:n:b:r:N:eb:r:Rc:i:4:6:q:Q:I:s:" opt; do
while getopts ":hf:l:n:pb:r:N:eb:r:Rc:i:4:6:q:Q:I:s:" opt; do
case $opt in
h)
show_help
Expand All @@ -65,6 +68,9 @@ while getopts ":hf:l:n:b:r:N:eb:r:Rc:i:4:6:q:Q:I:s:" opt; do
l)
HIGH=$OPTARG
;;
p)
FIXED_LEN=1
;;
n)
NS_LIST=$OPTARG
;;
Expand Down Expand Up @@ -120,6 +126,17 @@ done

CMD=${!OPTIND}

# Work out number length of interface names
if [[ $FIXED_LEN -eq 1 ]]; then
NUM_LEN=1
LAST=$HIGH
while [[ $(( LAST /= 10 )) -gt 0 ]]; do
: $((NUM_LEN++))
done
fi

[[ $IF_NAME != eth ]] && BR_NAME=br${IF_NAME:2}

# Check if system is using iptables or nftables
USE_IPTABLES=1
type -f iptables >/dev/null
Expand Down Expand Up @@ -156,9 +173,13 @@ fi
if [[ $CMD = add ]]; then
for n in $NS_LIST; do
[[ .$n = .$ROOT_NS ]] && continue
ip netns | grep $n >/dev/null 2>/dev/null
[[ $? -eq 0 ]] && continue

$ECHO unshare -n ip netns add $n
$ECHO ip netns exec $n ip link set up lo

NEW_NS+=" $n"
done
fi

Expand All @@ -176,12 +197,20 @@ if [[ $USE_IPTABLES -eq 1 ]]; then
fi

for n in $(seq $LOW $HIGH); do
if [[ -n $NUM_LEN ]]; then
IF=${IF_NAME}$(printf "%${NUM_LEN}.${NUM_LEN}d" $n)
BR=${BR_NAME}$(printf "%${NUM_LEN}.${NUM_LEN}d" $n)
else
IF=${IF_NAME}$n
BR=${BR_NAME}$n
fi

if [[ $CMD = add || $CMD = remake ]]; then
if [[ $CMD = add ]]; then
$ECHO ip netns exec $BRIDGE_NS ip link add ${BR_NAME}${n} type bridge
$ECHO ip netns exec $BRIDGE_NS ip link set ${BR_NAME}${n} up
$ECHO ip netns exec $BRIDGE_NS ip addr add ${IP_BASE_ADDR}.${n}.${ip[medium]}/24 broadcast + dev ${BR_NAME}${n}
$ECHO ip netns exec $BRIDGE_NS ip addr add ${IP6_BASE_ADDR}:$((100 + $n))::${ip[medium]}/64 dev ${BR_NAME}${n}
$ECHO ip netns exec $BRIDGE_NS ip link add ${BR} type bridge
$ECHO ip netns exec $BRIDGE_NS ip link set ${BR} up
$ECHO ip netns exec $BRIDGE_NS ip addr add ${IP_BASE_ADDR}.${n}.${ip[medium]}/24 broadcast + dev ${BR}
$ECHO ip netns exec $BRIDGE_NS ip addr add ${IP6_BASE_ADDR}:$((100 + $n))::${ip[medium]}/64 dev ${BR}
NS=$NS_LIST
else
NS=$SIDE
Expand All @@ -190,29 +219,29 @@ for n in $(seq $LOW $HIGH); do
for p in $NS; do
[[ $p = $BRIDGE_NS ]] && continue

$ECHO ip netns exec $BRIDGE_NS ip link add ${IF_NAME}${n}.$p type veth peer name ${IF_NAME}${n}
$ECHO ip netns exec $BRIDGE_NS ip link set ${IF_NAME}${n}.$p master ${BR_NAME}${n}
$ECHO ip netns exec $BRIDGE_NS ip link set ${IF_NAME}${n}.$p up
$ECHO ip netns exec $BRIDGE_NS ip link add ${IF}.$p type veth peer name ${IF}
$ECHO ip netns exec $BRIDGE_NS ip link set ${IF}.$p master ${BR}
$ECHO ip netns exec $BRIDGE_NS ip link set ${IF}.$p up

$ECHO ip netns exec $BRIDGE_NS ip link set ${IF_NAME}${n} netns ${p/$ROOT_NS/1}
$ECHO ip netns exec $BRIDGE_NS ip link set ${IF} netns ${p/$ROOT_NS/1}

[[ $p = $ROOT_NS ]] && NETNS_CMD= || NETNS_CMD="ip netns exec $p"
$ECHO $NETNS_CMD ip link set ${IF_NAME}${n} up
$ECHO $NETNS_CMD ip addr add ${IP_BASE_ADDR}.${n}.${ip[$p]}/24 broadcast + dev ${IF_NAME}${n}
$ECHO $NETNS_CMD ip addr add ${IP6_BASE_ADDR}:$((100 + $n))::${ip[$p]}/64 dev ${IF_NAME}${n}
$ECHO $NETNS_CMD ip link set ${IF} up
$ECHO $NETNS_CMD ip addr add ${IP_BASE_ADDR}.${n}.${ip[$p]}/24 broadcast + dev ${IF}
$ECHO $NETNS_CMD ip addr add ${IP6_BASE_ADDR}:$((100 + $n))::${ip[$p]}/64 dev ${IF}
done

$ECHO ip netns exec $BRIDGE_NS ip link add ${IF_NAME}${n} type dummy
$ECHO ip netns exec $BRIDGE_NS ip link set ${IF_NAME}${n} master ${BR_NAME}${n}
$ECHO ip netns exec $BRIDGE_NS ip link set up ${IF_NAME}${n}
$ECHO ip netns exec $BRIDGE_NS ip link add ${IF} type dummy
$ECHO ip netns exec $BRIDGE_NS ip link set ${IF} master ${BR}
$ECHO ip netns exec $BRIDGE_NS ip link set up ${IF}
elif [[ $CMD = del ]]; then
for p in $NS_LIST; do
[[ $p = $BRIDGE_NS ]] && continue

$ECHO ip netns exec $BRIDGE_NS ip link del ${IF_NAME}${n}.$p
$ECHO ip netns exec $BRIDGE_NS ip link del ${IF}.$p
done
$ECHO ip netns exec $BRIDGE_NS ip link del ${IF_NAME}${n}
$ECHO ip netns exec $BRIDGE_NS ip link del ${BR_NAME}${n}
$ECHO ip netns exec $BRIDGE_NS ip link del ${IF}
$ECHO ip netns exec $BRIDGE_NS ip link del ${BR}
else
echo Unknown command $CMD
fi
Expand Down

0 comments on commit 1646a2a

Please sign in to comment.