RFC 4391 (IP over InfiniBand), section 9.3, lays the ND source/target
link-layer address option out as type, length (3), two reserved zero
octets, then the 20-octet IPoIB link-layer address. The ND code
assumed the Ethernet layout (RFC 4861, section 4.6.1) everywhere and
read/wrote the address directly after the option header, i.e. two
octets early. The option-length sanity check computes 24 for both
layouts for a 20-octet address, so the mismatch was silent.
Against a conformant peer (e.g. Linux) this broke IPv6 over IPoIB in
both directions: the address parsed from a received NS/NA option was
shifted by two bytes, so the cached link-layer address embedded a GID
that does not exist on the fabric and replies were sent nowhere, and
the options we built carried our address at the wrong offset for the
peer. IPv4/ARP was unaffected. This blocked everything IPv6 over
IPoIB against Linux, including rdma_cm's IP-to-GID resolution and
therefore NFS-over-RDMA-over-InfiniBand with IPv6.
Add nd6_lladdr_opt_pad(), the analog of Linux's
ndisc_addr_option_pad(): the number of reserved octets between the
option header and the address (2 for IFT_INFINIBAND and
IFT_INFINIBANDLAG, 0 otherwise). Apply it at the option parse sites
(nd6_ns_input(), nd6_na_input(), nd6_rs_input(),
nd6_ra_opt_src_lladdr(), icmp6_redirect_input()) and the option build
sites (nd6_ns_output_fib(), nd6_na_output_fib(),
icmp6_redirect_output()). Zero the redirect target option before
filling it; previously its trailing pad bytes were left uninitialized
on links with 20-octet addresses. No functional change for link
types without reserved octets.
PR: 296585
Sponsored by: VersatusHPC