mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ipv6: update NUD_FAILED neighbors from NA messages
Transition a FAILED neighbor entry to STALE upon receipt of an NA message on routers when accept_untracked_na is enabled. This extends the RFC 9131 accept_untracked_na behavior so that FAILED entries are treated the same as non-existent entries. RFC 4861 section 7.3.3 says that an entry should be deleted when address resolution fails. Linux instead retains the entry in NUD_FAILED, so treating it as untracked is consistent with the protocol model. Trying to resolve FAILED neighbors via periodic probing (e.g. using NTF_EXT_MANAGED) is more work compared to this approach which uses information in NAs that the kernel may already be receiving. Note that because this behavior in IPv6 is dependent on the accept_untracked_na sysctl setting, this approach is more conservative than IPv4 which transitions FAILED neighbors to STALE by default upon receiving GARPs. Link: https://lore.kernel.org/r/20260813233344.445265-1-lfqlee314@gmail.com Signed-off-by: Lawrence Lee <lfqlee314@gmail.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/6be400e601f4ffa59e47ddb5daa33ecdd85dd88b.1790127207.git.lfqlee314@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
7ab4bbdca9
commit
24717a02ae
|
|
@ -3225,18 +3225,19 @@ drop_unsolicited_na - BOOLEAN
|
|||
Default: 0 (disabled).
|
||||
|
||||
accept_untracked_na - INTEGER
|
||||
Define behavior for accepting neighbor advertisements from devices that
|
||||
are absent in the neighbor cache:
|
||||
Define behavior for accepting neighbor advertisements for IPv6 addresses
|
||||
that are absent from the neighbor cache or whose entries are in FAILED
|
||||
state:
|
||||
|
||||
- 0 - (default) Do not accept unsolicited and untracked neighbor
|
||||
advertisements.
|
||||
- 0 - (default) Do not create new neighbor cache entries or update
|
||||
FAILED entries from neighbor advertisements.
|
||||
|
||||
- 1 - Add a new neighbor cache entry in STALE state for routers on
|
||||
receiving a neighbor advertisement (either solicited or unsolicited)
|
||||
with target link-layer address option specified if no neighbor entry
|
||||
is already present for the advertised IPv6 address. Without this knob,
|
||||
NAs received for untracked addresses (absent in neighbor cache) are
|
||||
silently ignored.
|
||||
- 1 - For routers, add a new neighbor cache entry or update an existing
|
||||
FAILED entry to STALE upon receiving a neighbor advertisement (either
|
||||
solicited or unsolicited) with the target link-layer address option
|
||||
specified. Without this knob, NAs received for untracked addresses
|
||||
(absent from the neighbor cache or in FAILED state) are silently
|
||||
ignored.
|
||||
|
||||
This is as per router-side behavior documented in RFC9131.
|
||||
|
||||
|
|
@ -3251,9 +3252,10 @@ accept_untracked_na - INTEGER
|
|||
used in conjunction with the ndisc_notify setting on the host to
|
||||
satisfy this prerequisite.
|
||||
|
||||
- 2 - Extend option (1) to add a new neighbor cache entry only if the
|
||||
source IP address is in the same subnet as an address configured on
|
||||
the interface that received the neighbor advertisement.
|
||||
- 2 - Extend option (1) to add a new neighbor cache entry or update a
|
||||
FAILED entry only if the source IP address is in the same subnet as
|
||||
an address configured on the interface that received the neighbor
|
||||
advertisement.
|
||||
|
||||
enhanced_dad - BOOLEAN
|
||||
Include a nonce option in the IPv6 neighbor solicitation messages used for
|
||||
|
|
|
|||
|
|
@ -973,13 +973,13 @@ static enum skb_drop_reason ndisc_recv_ns(struct sk_buff *skb)
|
|||
static int accept_untracked_na(struct inet6_dev *idev, struct in6_addr *saddr)
|
||||
{
|
||||
switch (READ_ONCE(idev->cnf.accept_untracked_na)) {
|
||||
case 0: /* Don't accept untracked na (absent in neighbor cache) */
|
||||
case 0: /* Don't accept untracked NA (absent or FAILED) */
|
||||
return 0;
|
||||
case 1: /* Create new entries from na if currently untracked */
|
||||
case 1: /* Create new or update FAILED entries from NA */
|
||||
return 1;
|
||||
case 2: /* Create new entries from untracked na only if saddr is in the
|
||||
case 2: /* Create new or update FAILED entries only if saddr is in the
|
||||
* same subnet as an address configured on the interface that
|
||||
* received the na
|
||||
* received the NA
|
||||
*/
|
||||
return !!ipv6_chk_prefix(saddr, idev->dev);
|
||||
default:
|
||||
|
|
@ -1067,34 +1067,39 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb)
|
|||
neigh = neigh_lookup(tbl, &msg->target, dev);
|
||||
|
||||
/* RFC 9131 updates original Neighbour Discovery RFC 4861.
|
||||
* NAs with Target LL Address option without a corresponding
|
||||
* entry in the neighbour cache can now create a STALE neighbour
|
||||
* cache entry on routers.
|
||||
* NAs with Target LL Address option can now create a STALE neighbor
|
||||
* cache entry on routers if the NA does not have a corresponding entry
|
||||
* in the neighbour cache or has a corresponding FAILED entry.
|
||||
*
|
||||
* entry accept fwding solicited behaviour
|
||||
* ------- ------ ------ --------- ----------------------
|
||||
* present X X 0 Set state to STALE
|
||||
* present X X 1 Set state to REACHABLE
|
||||
* absent 0 X X Do nothing
|
||||
* absent 1 0 X Do nothing
|
||||
* absent 1 1 X Add a new STALE entry
|
||||
* entry accept fwding solicited behaviour
|
||||
* ----------- ------ ------ --------- ----------------------
|
||||
* non-FAILED X X 0 Set state to STALE
|
||||
* non-FAILED X X 1 Set state to REACHABLE
|
||||
* FAILED 0 X X Do nothing
|
||||
* FAILED 1 0 X Do nothing
|
||||
* FAILED 1 1 X Set state to STALE
|
||||
* absent 0 X X Do nothing
|
||||
* absent 1 0 X Do nothing
|
||||
* absent 1 1 X Add a new STALE entry
|
||||
*
|
||||
* Note that we don't do a (daddr == all-routers-mcast) check.
|
||||
*/
|
||||
new_state = msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE;
|
||||
if (!neigh && lladdr && idev && READ_ONCE(idev->cnf.forwarding)) {
|
||||
if (accept_untracked_na(idev, saddr)) {
|
||||
neigh = neigh_create(tbl, &msg->target, dev);
|
||||
new_state = NUD_STALE;
|
||||
if (!neigh || (READ_ONCE(neigh->nud_state) & NUD_FAILED)) {
|
||||
if (!lladdr || !idev || !READ_ONCE(idev->cnf.forwarding) ||
|
||||
!accept_untracked_na(idev, saddr)) {
|
||||
if (neigh)
|
||||
neigh_release(neigh);
|
||||
return reason;
|
||||
}
|
||||
if (!neigh)
|
||||
neigh = neigh_create(tbl, &msg->target, dev);
|
||||
new_state = NUD_STALE;
|
||||
}
|
||||
|
||||
if (neigh && !IS_ERR(neigh)) {
|
||||
u8 old_flags = neigh->flags;
|
||||
|
||||
if (READ_ONCE(neigh->nud_state) & NUD_FAILED)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Don't update the neighbor cache entry on a proxy NA from
|
||||
* ourselves because either the proxied node is off link or it
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user