HomeFreeBSD

Simplify the way of attaching IPv6 link-layer header.

Description

Simplify the way of attaching IPv6 link-layer header.

Problem description:
How do we currently perform layer 2 resolution and header imposition:

For IPv4 we have the following chain:

ip_output() -> (ether|atm|whatever)_output() -> arpresolve()

Lookup is done in proper place (link-layer output routine) and it is possible

to provide cached lle data.

For IPv6 situation is more complex:

ip6_output() -> nd6_output() -> nd6_output_ifp() -> (whatever)_output() ->
  nd6_storelladdr()

We have ip6_ouput() which calls nd6_output() instead of link output routine.
nd6_output() does the following:

  • checks if lle exists, creates it if needed (similar to arpresolve())
  • performes lle state transitions (similar to arpresolve())
  • calls nd6_output_ifp() which pushes packets to link output routine along with running SeND/MAC hooks regardless of lle state (e.g. works as run-hooks placeholder).

After that, iface output routine like ether_output() calls nd6_storelladdr()

which performs lle lookup once again.

As a result, we perform lookup twice for each outgoing packet for most types

of interfaces. We also need to maintain runtime-checked table of 'nd6-free'
interfaces (see nd6_need_cache()).

Fix this behavior by eliminating first ND lookup. To be more specific:

  • make all nd6_output() consumers use nd6_output_ifp() instead
  • rename nd6_output[_slow]() to nd6_resolve_[slow]()
  • convert nd6_resolve() and nd6_resolve_slow() to arpresolve() semantics, e.g. copy L2 address to buffer instead of pushing packet towards lower layers
  • Make all nd6_storelladdr() users use nd6_resolve()
  • eliminate nd6_storelladdr()

The resulting callchain is the following:

ip6_output() -> nd6_output_ifp() -> (whatever)_output() -> nd6_resolve()

Error handling:
Currently sending packet to non-existing la results in ip6_<output|forward>

-> nd6_output() -> nd6_output _lle() which returns 0.

In new scenario packet is propagated to <ether|whatever>_output() ->

nd6_resolve() which will return EWOULDBLOCK, and that result
will be converted to 0.

(And EWOULDBLOCK is actually used by IB/TOE code).

Sponsored by: Yandex LLC
Differential Revision: https://reviews.freebsd.org/D1469

Details

Provenance
melifaroAuthored on
Differential Revision
D1469: Change the way of attaching IPv6 link-layer header.
Parents
rS287860: Frontends don't need to set errors themselves.
Branches
Unknown
Tags
Unknown