Fix quick-register broadcast detection on Proxmox bridges
CI / Lint + build + test (push) Failing after 5m17s
CI / Lint + build + test (push) Failing after 5m17s
Two bugs compounded on Proxmox hosts: primary_iface walked `ip link show` and picked the physical NIC (e.g. enp1s0), which has no IPv4 on Proxmox because the address lives on vmbr0. Even if vmbr0 had been picked, the kernel reports its broadcast as 0.0.0.0, so the script fell all the way back to 255.255.255.255. Now we prefer the default-route interface (vmbr0 on Proxmox, eno1 on bare metal) and, when `ip` doesn't surface a usable `brd`, compute the broadcast from the inet CIDR instead of giving up.
This commit is contained in:
@@ -26,16 +26,40 @@ if [[ -z "${ORCH_URL}" ]]; then
|
||||
fi
|
||||
|
||||
primary_iface() {
|
||||
# Pick the first physical ethernet-style interface that isn't a loopback,
|
||||
# bridge, veth, docker, virbr, bond, tun, or tap.
|
||||
ip -o link show 2>/dev/null \
|
||||
| awk '$0 ~ /link\/ether/ {
|
||||
name=$2; sub(":","",name)
|
||||
if (name ~ /^(lo|docker|br-|veth|virbr|bond|tun|tap|wlan|wlp)/) next
|
||||
# Prefer the interface carrying the default route — that's the
|
||||
# canonical "primary" iface (e.g. vmbr0 on Proxmox, eno1 on bare
|
||||
# metal). `ip link show` order picks the physical NIC on Proxmox,
|
||||
# but that NIC has no IPv4, so we'd miss the broadcast address.
|
||||
local iface
|
||||
iface="$(ip -o -4 route show default 2>/dev/null \
|
||||
| awk '{for(i=1;i<=NF;i++) if($i=="dev") {print $(i+1); exit}}')"
|
||||
if [[ -n "${iface}" ]]; then
|
||||
echo "${iface}"
|
||||
return
|
||||
fi
|
||||
# Fallback: first non-virtual interface that has an IPv4 address.
|
||||
ip -o -4 addr show 2>/dev/null \
|
||||
| awk '{
|
||||
name=$2
|
||||
if (name ~ /^(lo|docker|br-|veth|virbr|bond|tun|tap|fwbr|fwpr|fwln|wlan|wlp)/) next
|
||||
print name; exit
|
||||
}'
|
||||
}
|
||||
|
||||
# compute_broadcast "192.168.1.250/24" → "192.168.1.255"
|
||||
compute_broadcast() {
|
||||
local cidr="$1" ip prefix a b c d host mask inv bc
|
||||
ip="${cidr%/*}"
|
||||
prefix="${cidr#*/}"
|
||||
[[ "${ip}" == *.*.*.* && "${prefix}" =~ ^[0-9]+$ ]] || return 1
|
||||
IFS=. read -r a b c d <<<"${ip}"
|
||||
host=$(( (a<<24) | (b<<16) | (c<<8) | d ))
|
||||
mask=$(( (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF ))
|
||||
inv=$(( (~mask) & 0xFFFFFFFF ))
|
||||
bc=$(( host | inv ))
|
||||
printf '%d.%d.%d.%d' $(( (bc>>24)&0xFF )) $(( (bc>>16)&0xFF )) $(( (bc>>8)&0xFF )) $(( bc&0xFF ))
|
||||
}
|
||||
|
||||
IFACE="$(primary_iface || true)"
|
||||
if [[ -z "${IFACE}" ]]; then
|
||||
echo "ERROR: could not pick a primary network interface." >&2
|
||||
@@ -50,8 +74,17 @@ if [[ -z "${MAC}" ]]; then
|
||||
fi
|
||||
|
||||
if [[ -z "${WOL_BROADCAST:-}" ]]; then
|
||||
WOL_BROADCAST="$(ip -o -4 addr show dev "${IFACE}" 2>/dev/null \
|
||||
| awk '{for(i=1;i<=NF;i++) if($i=="brd") {print $(i+1); exit}}')"
|
||||
ipinfo="$(ip -o -4 addr show dev "${IFACE}" 2>/dev/null || true)"
|
||||
WOL_BROADCAST="$(awk '{for(i=1;i<=NF;i++) if($i=="brd") {print $(i+1); exit}}' <<<"${ipinfo}")"
|
||||
# Bridges (vmbr0 on Proxmox, br0 on Linux bridges) often report
|
||||
# brd 0.0.0.0 or omit it entirely. Compute from the inet CIDR
|
||||
# before giving up on 255.255.255.255.
|
||||
if [[ -z "${WOL_BROADCAST}" || "${WOL_BROADCAST}" == "0.0.0.0" ]]; then
|
||||
cidr="$(awk '{for(i=1;i<=NF;i++) if($i=="inet") {print $(i+1); exit}}' <<<"${ipinfo}")"
|
||||
if [[ "${cidr}" == */* ]]; then
|
||||
WOL_BROADCAST="$(compute_broadcast "${cidr}" || true)"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
WOL_BROADCAST="${WOL_BROADCAST:-255.255.255.255}"
|
||||
WOL_PORT="${WOL_PORT:-9}"
|
||||
|
||||
Reference in New Issue
Block a user