ICMPv6 Auto-configuration: If no router reponds to the Router Solicitation, claim the link local address by sending the Neighbor Advertisement and return success

This commit is contained in:
Gregory Nutt 2015-02-04 16:13:27 -06:00
parent c5ed77120f
commit 28b89b7a65
4 changed files with 48 additions and 26 deletions

View File

@ -263,15 +263,15 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev);
* buffer * buffer
* *
* Return: * Return:
* Zero (OK) on success; A negated errno value on return. * None.
* *
* Assumptions: * Assumptions:
* The network is locked * The network is locked
* *
****************************************************************************/ ****************************************************************************/
int icmpv6_advertise(FAR struct net_driver_s *dev, void icmpv6_advertise(FAR struct net_driver_s *dev,
const net_ipv6addr_t destipaddr); const net_ipv6addr_t destipaddr);
/**************************************************************************** /****************************************************************************
* Function: icmpv6_wait_setup * Function: icmpv6_wait_setup

View File

@ -83,15 +83,15 @@
* buffer * buffer
* *
* Return: * Return:
* Zero (OK) on success; A negated errno value on return. * None
* *
* Assumptions: * Assumptions:
* The network is locked * The network is locked
* *
****************************************************************************/ ****************************************************************************/
int icmpv6_advertise(FAR struct net_driver_s *dev, void icmpv6_advertise(FAR struct net_driver_s *dev,
const net_ipv6addr_t destipaddr) const net_ipv6addr_t destipaddr)
{ {
FAR struct icmpv6_iphdr_s *icmp = ICMPv6BUF; FAR struct icmpv6_iphdr_s *icmp = ICMPv6BUF;
FAR struct icmpv6_neighbor_advertise_s *adv; FAR struct icmpv6_neighbor_advertise_s *adv;
@ -186,7 +186,6 @@ int icmpv6_advertise(FAR struct net_driver_s *dev,
g_netstats.icmpv6.sent++; g_netstats.icmpv6.sent++;
g_netstats.ipv6.sent++; g_netstats.ipv6.sent++;
#endif #endif
return OK;
} }
#endif /* CONFIG_NET_ICMPv6 */ #endif /* CONFIG_NET_ICMPv6 */

View File

@ -78,6 +78,7 @@ struct icmpv6_router_s
FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */ FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */
sem_t snd_sem; /* Used to wake up the waiting thread */ sem_t snd_sem; /* Used to wake up the waiting thread */
volatile bool snd_sent; /* True: if request sent */ volatile bool snd_sent; /* True: if request sent */
bool snd_advertise; /* True: Send Neighbor Advertisement */
#ifdef CONFIG_NETDEV_MULTINIC #ifdef CONFIG_NETDEV_MULTINIC
uint8_t snd_ifname[IFNAMSIZ]; /* Interface name */ uint8_t snd_ifname[IFNAMSIZ]; /* Interface name */
#endif #endif
@ -135,7 +136,18 @@ static uint16_t icmpv6_router_interrupt(FAR struct net_driver_s *dev,
/* It looks like we are good to send the data */ /* It looks like we are good to send the data */
/* Copy the packet data into the device packet buffer and send it */ /* Copy the packet data into the device packet buffer and send it */
icmpv6_rsolicit(dev); if (state->snd_advertise)
{
/* Send the ICMPv6 Neighbor Advertisement message */
icmpv6_advertise(dev, g_ipv6_allnodes);
}
else
{
/* Send the ICMPv6 Router Solicitation message */
icmpv6_rsolicit(dev);
}
/* Make sure no additional Router Solicitation overwrites this one. /* Make sure no additional Router Solicitation overwrites this one.
* This flag will be cleared in icmpv6_out(). * This flag will be cleared in icmpv6_out().
@ -159,13 +171,14 @@ static uint16_t icmpv6_router_interrupt(FAR struct net_driver_s *dev,
} }
/**************************************************************************** /****************************************************************************
* Name: icmpv6_send_rsolicit * Name: icmpv6_send_message
* *
* Description: * Description:
* Send an ICMPv6 Router Solicitation to resolve an IPv6 address. * Send an ICMPv6 Router Solicitation to resolve an IPv6 address.
* *
* Parameters: * Parameters:
* dev - The device to use to send the solicitation * dev - The device to use to send the solicitation
* advertise - True: Send the Neighbor Advertisement message
* *
* Returned Value: * Returned Value:
* Zero (OK) is returned on success; On error a negated errno value is * Zero (OK) is returned on success; On error a negated errno value is
@ -176,7 +189,7 @@ static uint16_t icmpv6_router_interrupt(FAR struct net_driver_s *dev,
* *
****************************************************************************/ ****************************************************************************/
int icmpv6_send_rsolicit(FAR struct net_driver_s *dev) static int icmpv6_send_message(FAR struct net_driver_s *dev, bool advertise)
{ {
struct icmpv6_router_s state; struct icmpv6_router_s state;
int ret; int ret;
@ -210,6 +223,7 @@ int icmpv6_send_rsolicit(FAR struct net_driver_s *dev)
/* Arm the callback */ /* Arm the callback */
state.snd_sent = false; state.snd_sent = false;
state.snd_advertise = advertise;
state.snd_cb->flags = ICMPv6_POLL; state.snd_cb->flags = ICMPv6_POLL;
state.snd_cb->priv = (FAR void *)&state; state.snd_cb->priv = (FAR void *)&state;
state.snd_cb->event = icmpv6_router_interrupt; state.snd_cb->event = icmpv6_router_interrupt;
@ -242,7 +256,7 @@ errout_with_semaphore:
* Name: icmpv6_wait_radvertise * Name: icmpv6_wait_radvertise
* *
* Description: * Description:
* Wait for the receipt of the Router Advertisment matching the Router * Wait for the receipt of the Router Advertisement matching the Router
* Solicitation that we just sent. * Solicitation that we just sent.
* *
* Parameters: * Parameters:
@ -259,9 +273,9 @@ errout_with_semaphore:
* *
****************************************************************************/ ****************************************************************************/
int icmpv6_wait_radvertise(FAR struct net_driver_s *dev, static int icmpv6_wait_radvertise(FAR struct net_driver_s *dev,
FAR struct icmpv6_rnotify_s *notify, FAR struct icmpv6_rnotify_s *notify,
net_lock_t *save) net_lock_t *save)
{ {
struct timespec delay; struct timespec delay;
#ifdef CONFIG_NET_NOINTS #ifdef CONFIG_NET_NOINTS
@ -459,7 +473,7 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
/* Send the ICMPv6 Router solicitation message */ /* Send the ICMPv6 Router solicitation message */
ret = icmpv6_send_rsolicit(dev); ret = icmpv6_send_message(dev, false);
if (ret < 0) if (ret < 0)
{ {
ndbg("ERROR: Failed send router solicitation: %d\n", ret); ndbg("ERROR: Failed send router solicitation: %d\n", ret);
@ -490,11 +504,25 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
ndbg("ERROR: Failed to get the router advertisement: %d (retries=%d)\n", ndbg("ERROR: Failed to get the router advertisement: %d (retries=%d)\n",
ret, retries); ret, retries);
/* Take the network down and return the failure */ /* Claim the link local address as ours by sending the ICMPv6 Neighbor
* Advertisement message.
*/
ret = icmpv6_send_message(dev, true);
if (ret < 0)
{
ndbg("ERROR: Failed send neighbor advertisement: %d\n", ret);
netdev_ifdown(dev);
net_unlock(save);
return ret;
}
/* Leave the network up and return success (even though things did not
* work out quite the way we wanted.
*/
netdev_ifdown(dev);
net_unlock(save); net_unlock(save);
return ret; return OK;
} }
/* 5. Router Direction: The router provides direction to the node on how to /* 5. Router Direction: The router provides direction to the node on how to

View File

@ -109,7 +109,6 @@ struct icmpv6_conn_s g_icmpv6_conn;
void icmpv6_input(FAR struct net_driver_s *dev) void icmpv6_input(FAR struct net_driver_s *dev)
{ {
FAR struct icmpv6_iphdr_s *icmp = ICMPv6BUF; FAR struct icmpv6_iphdr_s *icmp = ICMPv6BUF;
int ret;
#ifdef CONFIG_NET_STATISTICS #ifdef CONFIG_NET_STATISTICS
g_netstats.icmpv6.recv++; g_netstats.icmpv6.recv++;
@ -136,13 +135,9 @@ void icmpv6_input(FAR struct net_driver_s *dev)
* solicitation came from. * solicitation came from.
*/ */
ret = icmpv6_advertise(dev, icmp->srcipaddr); icmpv6_advertise(dev, icmp->srcipaddr);
if (ret < 0)
{
goto icmpv6_drop_packet;
}
/* All statistics have been updated */ /* All statistics have been updated. Nothing to do but exit. */
return; return;
} }