[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
(usagi-users 02706) IPv6 state transition error
- To: usagi-users@xxxxxxxxxxxxxx
- Subject: (usagi-users 02706) IPv6 state transition error
- From: Hiroaki Kago <kago@xxxxxxxxxxxxxx>
- Date: Thu, 18 Dec 2003 18:52:21 +0900
- Reply-to: kago@xxxxxxxxxxxxxx
- User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)
Hello,
I faced some errors in state transition and the processing,
when the IPv6 packet below is received in the USAGI snap
kernel-2.6-s20031208.
------------------------------------------------------------------------
1. Neighbor Advertisement
===========================+=========+===================
Neighbor Advertisement |Current |New State
-----------+-+-+-+---------+ State+--------+----------
Destination|r|s|o|TLLA | |expected|result(NG)
===========+=+=+=+=========+=========+========+==========
Unicast 0 0 0 different REACHABLE STALE REACHABLE
-----------+-+-+-+---------+---------+--------+----------
Unicast 0 1 0 different REACHABLE STALE REACHABLE
-----------+-+-+-+---------+---------+--------+----------
Multicast 0 0 0 different REACHABLE STALE REACHABLE
===========+=+=+=+=========+=========+========+==========
Unicast 0 0 0 none PROBE PROBE STALE
-----------+-+-+-+---------+---------+--------+----------
Unicast 0 0 1 none PROBE PROBE STALE
-----------+-+-+-+---------+---------+--------+----------
Unicast 0 0 0 same PROBE PROBE STALE
-----------+-+-+-+---------+---------+--------+----------
Unicast 0 0 1 same PROBE PROBE STALE
-----------+-+-+-+---------+---------+--------+----------
Multicast 0 0 0 same PROBE PROBE STALE
-----------+-+-+-+---------+---------+--------+----------
Multicast 0 0 1 same PROBE PROBE STALE
===========+=+=+=+=========+=========+========+==========
Abbreviations
r : Router flag s : Solicited flag o : Override flag
TLLA : Target Link-Layer Address option
Meanings of the column descriptions
exist/none : presence of Target Link-Layer Address option
same/different : the link-layer address included in Target
Link-Layer Address option differs from that
in the target's Neighbor Cache entry
According to RFC2461:
7.2.5. Receipt of Neighbor Advertisements
.....
If the target's Neighbor Cache entry is in any state other than
INCOMPLETE when the advertisement is received, processing becomes
quite a bit more complex. If the Override flag is clear and the
supplied link-layer address differs from that in the cache, then one
of two actions takes place: if the state of the entry is REACHABLE,
set it to STALE, but do not update the entry in any other way;
otherwise, the received advertisement should be ignored and MUST NOT
update the cache. If the Override flag is set, both the Override
flag is clear and the supplied link-layer address is the same as that
in the cache, or no Target Link-layer address option was supplied,
the received advertisement MUST update the Neighbor Cache entry as
follows:
.....
- If the Solicited flag is set, the state of the entry MUST be set
to REACHABLE. If the Solicited flag is zero and the link-layer
address was updated with a different address the state MUST be set
to STALE. Otherwise, the entry's state remains unchanged.
------------------------------------------------------------------------
------------------------------------------------------------------------
2. Neighbor Solicitation
=====================+=======+===================
Neighbor Solicitation|Current|New State
------------+--------+ State+--------+----------
Destination |SLLA | |expected|result(NG)
============+========+=======+========+==========
Unicast none PROBE PROBE STALE
------------+--------+-------+--------+----------
Unicast same PROBE PROBE STALE
------------+--------+-------+--------+----------
Multicast same PROBE PROBE STALE
============+========+=======+========+==========
Abbreviations
SLLA : Source Link-Layer Address option
Meanings of the column descriptions
exist/none : presence of Source Link-Layer Address option
same/different : the link-layer address included in Source
Link-Layer Address option differs from that
in the target's Neighbor Cache entry
According to RFC2461:
7.2.3. Receipt of Neighbor Solicitations
.....
If the Target Address is tentative, the Neighbor Solicitation should
be processed as described in [ADDRCONF]. Otherwise, the following
description applies. If the Source Address is not the unspecified
address and, on link layers that have addresses, the solicitation
includes a Source Link-Layer Address option, then the recipient
SHOULD create or update the Neighbor Cache entry for the IP Source
Address of the solicitation. If an entry does not already exist, the
node SHOULD create a new one and set its reachability state to STALE
as specified in Section 7.3.3. If an entry already exists, and the
cached link-layer address differs from the one in the received Source
Link-Layer option, the cached address should be replaced by the
received address and the entry's reachability state MUST be set to
STALE.
------------------------------------------------------------------------
------------------------------------------------------------------------
3. Router Advertisement
====================+=======+===================
Router Advertisement|Current|New State
--------------------+ State|
Source Link-Layer | +--------+----------
Address option | |expected|result(NG)
====================+=======+========+==========
none PROBE PROBE STALE
--------------------+-------+--------+----------
same PROBE PROBE STALE
====================+=======+========+==========
Meanings of the column descriptions
exist/none : presence of Source Link-Layer Address option
same/different : the link-layer address included in Source
Link-Layer Address option differs from that
in the target's Neighbor Cache entry
According to RFC2461:
6.3.4. Processing Received Router Advertisements
.....
After extracting information from the fixed part of the Router
Advertisement message, the advertisement is scanned for valid
options. If the advertisement contains a Source Link-Layer Address
option the link-layer address SHOULD be recorded in the Neighbor
Cache entry for the router (creating an entry if necessary) and the
IsRouter flag in the Neighbor Cache entry MUST be set to TRUE. If no
Source Link-Layer Address is included, but a corresponding Neighbor
Cache entry exists, its IsRouter flag MUST be set to TRUE. The
IsRouter flag is used by Neighbor Unreachability Detection to
determine when a router changes to being a host (i.e., no longer
capable of forwarding packets). If a Neighbor Cache entry is created
for the router its reachability state MUST be set to STALE as
specified in Section 7.3.3. If a cache entry already exists and is
updated with a different link-layer address the reachability state
MUST also be set to STALE.
------------------------------------------------------------------------
------------------------------------------------------------------------
4. Router Solicitation
===================+==========+===================+====================
Router Solicitation|Current |New State |link-layer address
-------------------+ State| | in the cache
Source Link-Layer | +--------+----------+---------+----------
Address option | |expected|result(NG)|expected |result(NG)
===================+==========+========+==========+=========+==========
exist NONCE STALE NONCE unchanged unchanged
===================+==========+========+==========+=========+==========
exist INCOMPLETE STALE INCOMPLETE unchanged unchanged
===================+==========+========+==========+=========+==========
different REACHABLE STALE REACHABLE updated unchanged
===================+==========+========+==========+=========+==========
different STALE STALE STALE updated unchanged
===================+==========+========+==========+=========+==========
different PROBE STALE PROBE updated unchanged
===================+==========+========+==========+=========+==========
Meanings of the column descriptions
exist/none : presence of Source Link-Layer Address option
same/different : the link-layer address included in Source
Link-Layer Address option differs from that
in the target's Neighbor Cache entry
According to RFC2461:
6.2.6. Processing Router Solicitations
.....
Router Solicitations in which the Source Address is the unspecified
address MUST NOT update the router's Neighbor Cache; solicitations
with a proper source address update the Neighbor Cache as follows. If
the router already has a Neighbor Cache entry for the solicitation's
sender, the solicitation contains a Source Link-Layer Address option,
and the received link-layer address differs from that already in the
cache, the link-layer address SHOULD be updated in the appropriate
Neighbor Cache entry, and its reachability state MUST also be set to
STALE. If there is no existing Neighbor Cache entry for the
solicitation's sender, the router creates one, installs the link-
layer address and sets its reachability state to STALE as specified
in Section 7.3.3. Whether or not a Source Link-Layer Address option
is provided, if a Neighbor Cache entry for the solicitation's sender
exists (or is created) the entry's IsRouter flag MUST be set to
FALSE.
------------------------------------------------------------------------
------------------------------------------------------------------------
5. Redirect
================================+=======+===================
Redirect Option |Current|New state
------+-------------------------+ State+--------+----------
TLLA |Redirected header option | |expected|result(NG)
======+=========================+=======+========+==========
none none PROBE PROBE STALE
------+-------------------------+-------+--------+----------
same none PROBE PROBE STALE
======+=========================+=======+========+==========
Abbreviations
TLLA : Target Link-Layer Address option
Meanings of the column descriptions
exist/none : presence of Target Link-Layer Address option
same/different : the link-layer address included in Target
Link-Layer Address option differs from that
in the target's Neighbor Cache entry
According to RFC2461:
8.3. Host Specification
.....
If the redirect contains a Target Link-Layer Address option the host
either creates or updates the Neighbor Cache entry for the target.
In both cases the cached link-layer address is copied from the Target
Link-Layer Address option. If a Neighbor Cache entry is created for
the target its reachability state MUST be set to STALE as specified
in Section 7.3.3. If a cache entry already existed and it is updated
with a different link-layer address, its reachability state MUST also
be set to STALE. If the link-layer address is the same as that
already in the cache, the cache entry's state remains unchanged.
------------------------------------------------------------------------
I made a patch and fixed the problem.
------------------------------------------------------------------------
diff -Nuar linux26.orig/include/net/neighbour.h linux26/include/net/neighbour.h
--- linux26.orig/include/net/neighbour.h 2003-08-23 17:02:16.000000000 +0900
+++ linux26/include/net/neighbour.h 2003-12-18 15:46:39.000000000 +0900
@@ -170,6 +170,14 @@
struct pneigh_entry *phash_buckets[PNEIGH_HASHMASK+1];
};
+#define NEIGH_UPDATE_TYPE_ADMIN 0
+#define NEIGH_UPDATE_TYPE_ARP 1
+#define NEIGH_UPDATE_TYPE_IP6NS 2
+#define NEIGH_UPDATE_TYPE_IP6NA 3
+#define NEIGH_UPDATE_TYPE_IP6RS 4
+#define NEIGH_UPDATE_TYPE_IP6RA 5
+#define NEIGH_UPDATE_TYPE_IP6REDIRECT 6
+
extern void neigh_table_init(struct neigh_table *tbl);
extern int neigh_table_clear(struct neigh_table *tbl);
extern struct neighbour * neigh_lookup(struct neigh_table *tbl,
diff -Nuar linux26.orig/net/core/neighbour.c linux26/net/core/neighbour.c
--- linux26.orig/net/core/neighbour.c 2003-11-11 05:07:19.000000000 +0900
+++ linux26/net/core/neighbour.c 2003-12-18 15:46:39.000000000 +0900
@@ -848,8 +848,6 @@
if (old & NUD_VALID) {
if (!memcmp(lladdr, neigh->ha, dev->addr_len))
lladdr = neigh->ha;
- else if (!override)
- goto out;
}
} else {
/* No address is supplied; if we know something,
@@ -861,28 +859,86 @@
lladdr = neigh->ha;
}
- neigh_sync(neigh);
- old = neigh->nud_state;
- if (new & NUD_CONNECTED)
- neigh->confirmed = jiffies;
- neigh->updated = jiffies;
-
/* If entry was valid and address is not changed,
do not change entry state, if new one is STALE.
*/
err = 0;
- if ((old & NUD_VALID) && lladdr == neigh->ha &&
- (new == old || (new == NUD_STALE && (old & NUD_CONNECTED))))
- goto out;
+ if (old&NUD_VALID) {
+ if (lladdr != neigh->ha && !override) {
+ switch(arp) {
+ case NEIGH_UPDATE_TYPE_IP6NA:
+ if (old&NUD_CONNECTED) {
+ new = NUD_STALE;
+ lladdr = neigh->ha;
+ break;
+ }
+ /*NOBREAK*/
+ case NEIGH_UPDATE_TYPE_ADMIN:
+ case NEIGH_UPDATE_TYPE_ARP:
+ default:
+ goto out;
+ }
+ } else {
+ switch(arp) {
+ case NEIGH_UPDATE_TYPE_IP6NS:
+ case NEIGH_UPDATE_TYPE_IP6NA:
+ case NEIGH_UPDATE_TYPE_IP6RS:
+ case NEIGH_UPDATE_TYPE_IP6RA:
+ case NEIGH_UPDATE_TYPE_IP6REDIRECT:
+ if (new == NUD_STALE) {
+ if (lladdr == neigh->ha) {
+ new = old;
+ }
+ }
+ break;
+ case NEIGH_UPDATE_TYPE_ADMIN:
+ case NEIGH_UPDATE_TYPE_ARP:
+ default:
+ if (new == old) {
+ lladdr = neigh->ha;
+ } else if (lladdr == neigh->ha &&
+ new == NUD_STALE &&
+ (old&NUD_CONNECTED)) {
+ new = old;
+ }
+ }
+ }
+ }
+
+ if (new != old) {
+ if (new&NUD_IN_TIMER) {
+ unsigned long next = jiffies;
+ switch(new) {
+ case NUD_REACHABLE:
+ next += neigh->parms->reachable_time;
+ break;
+ default:
+ /*XXX*/
+ }
+ if (old&NUD_IN_TIMER) {
+ mod_timer(&neigh->timer, next);
+ } else {
+ neigh_hold(neigh);
+ neigh->timer.expires = next;
+ add_timer(&neigh->timer);
+ }
+ } else {
+ neigh_del_timer(neigh);
+ }
+ neigh->nud_state = new;
+ }
+
+ if (new != old || lladdr != neigh->ha) {
+ if (new&NUD_CONNECTED)
+ neigh->confirmed = jiffies;
+ else
+ neigh->confirmed = jiffies - (neigh->parms->base_reachable_time<<1);
+ }
- neigh_del_timer(neigh);
- neigh->nud_state = new;
if (lladdr != neigh->ha) {
+ neigh->updated = jiffies;
memcpy(&neigh->ha, lladdr, dev->addr_len);
neigh_update_hhs(neigh);
- if (!(new & NUD_CONNECTED))
- neigh->confirmed = jiffies -
- (neigh->parms->base_reachable_time << 1);
#ifdef CONFIG_ARPD
notify = 1;
#endif
diff -Nuar linux26.orig/net/ipv6/ndisc.c linux26/net/ipv6/ndisc.c
--- linux26.orig/net/ipv6/ndisc.c 2003-10-30 14:49:30.000000000 +0900
+++ linux26/net/ipv6/ndisc.c 2003-12-18 15:46:39.000000000 +0900
@@ -813,7 +813,12 @@
* for the source address
*/
- neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
+ neigh = __neigh_lookup(&nd_tbl, saddr, dev,
+ lladdr || !dev->addr_len);
+ if (neigh) {
+ neigh_update(neigh, lladdr, NUD_STALE,
+ 1, NEIGH_UPDATE_TYPE_IP6NS);
+ }
if (neigh || !dev->hard_header) {
ndisc_send_na(dev, neigh, saddr, &ifp->addr,
@@ -856,7 +861,12 @@
* for the source address
*/
- neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, skb->dev);
+ neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev,
+ lladdr || !dev->addr_len);
+ if (neigh) {
+ neigh_update(neigh, lladdr, NUD_STALE,
+ 1, NEIGH_UPDATE_TYPE_IP6NS);
+ }
if (neigh || !dev->hard_header) {
ndisc_send_na(dev, neigh, saddr,
@@ -886,7 +896,12 @@
nd_tbl.stats.rcv_probes_ucast++;
if (addr_type & IPV6_ADDR_UNICAST) {
- neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
+ neigh = __neigh_lookup(&nd_tbl, saddr, dev,
+ lladdr || !dev->addr_len);
+ if (neigh) {
+ neigh_update(neigh, lladdr, NUD_STALE,
+ 1, NEIGH_UPDATE_TYPE_IP6NS);
+ }
if (neigh) {
ndisc_send_na(dev, neigh, saddr, &msg->target,
@@ -994,7 +1009,7 @@
neigh_update(neigh, lladdr,
msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
- msg->icmph.icmp6_override, 1);
+ msg->icmph.icmp6_override, NEIGH_UPDATE_TYPE_IP6NA);
neigh_release(neigh);
}
}
@@ -1164,7 +1179,8 @@
goto out;
}
}
- neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
+ neigh_update(neigh, lladdr, NUD_STALE, 1,
+ NEIGH_UPDATE_TYPE_IP6RA);
}
if (ndopts.nd_opts_pi) {
@@ -1297,7 +1313,8 @@
if (neigh) {
if (neigh->nud_state&NUD_VALID) {
if (!rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, on_link))
- neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
+ neigh_update(neigh, lladdr, NUD_STALE, 1,
+ NEIGH_UPDATE_TYPE_IP6REDIRECT);
} else
__neigh_event_send(neigh, NULL);
neigh_release(neigh);
------------------------------------------------------------------------
Regards,
Hiroaki Kago