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:
parent
c5ed77120f
commit
28b89b7a65
@ -263,15 +263,15 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev);
|
||||
* buffer
|
||||
*
|
||||
* Return:
|
||||
* Zero (OK) on success; A negated errno value on return.
|
||||
* None.
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int icmpv6_advertise(FAR struct net_driver_s *dev,
|
||||
const net_ipv6addr_t destipaddr);
|
||||
void icmpv6_advertise(FAR struct net_driver_s *dev,
|
||||
const net_ipv6addr_t destipaddr);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: icmpv6_wait_setup
|
||||
|
@ -83,15 +83,15 @@
|
||||
* buffer
|
||||
*
|
||||
* Return:
|
||||
* Zero (OK) on success; A negated errno value on return.
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int icmpv6_advertise(FAR struct net_driver_s *dev,
|
||||
const net_ipv6addr_t destipaddr)
|
||||
void icmpv6_advertise(FAR struct net_driver_s *dev,
|
||||
const net_ipv6addr_t destipaddr)
|
||||
{
|
||||
FAR struct icmpv6_iphdr_s *icmp = ICMPv6BUF;
|
||||
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.ipv6.sent++;
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_ICMPv6 */
|
||||
|
@ -78,6 +78,7 @@ struct icmpv6_router_s
|
||||
FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */
|
||||
sem_t snd_sem; /* Used to wake up the waiting thread */
|
||||
volatile bool snd_sent; /* True: if request sent */
|
||||
bool snd_advertise; /* True: Send Neighbor Advertisement */
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
uint8_t snd_ifname[IFNAMSIZ]; /* Interface name */
|
||||
#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 */
|
||||
/* 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.
|
||||
* 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:
|
||||
* Send an ICMPv6 Router Solicitation to resolve an IPv6 address.
|
||||
*
|
||||
* 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:
|
||||
* 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;
|
||||
int ret;
|
||||
@ -210,6 +223,7 @@ int icmpv6_send_rsolicit(FAR struct net_driver_s *dev)
|
||||
/* Arm the callback */
|
||||
|
||||
state.snd_sent = false;
|
||||
state.snd_advertise = advertise;
|
||||
state.snd_cb->flags = ICMPv6_POLL;
|
||||
state.snd_cb->priv = (FAR void *)&state;
|
||||
state.snd_cb->event = icmpv6_router_interrupt;
|
||||
@ -242,7 +256,7 @@ errout_with_semaphore:
|
||||
* Name: icmpv6_wait_radvertise
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Parameters:
|
||||
@ -259,9 +273,9 @@ errout_with_semaphore:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int icmpv6_wait_radvertise(FAR struct net_driver_s *dev,
|
||||
FAR struct icmpv6_rnotify_s *notify,
|
||||
net_lock_t *save)
|
||||
static int icmpv6_wait_radvertise(FAR struct net_driver_s *dev,
|
||||
FAR struct icmpv6_rnotify_s *notify,
|
||||
net_lock_t *save)
|
||||
{
|
||||
struct timespec delay;
|
||||
#ifdef CONFIG_NET_NOINTS
|
||||
@ -459,7 +473,7 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
|
||||
|
||||
/* Send the ICMPv6 Router solicitation message */
|
||||
|
||||
ret = icmpv6_send_rsolicit(dev);
|
||||
ret = icmpv6_send_message(dev, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
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",
|
||||
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);
|
||||
return ret;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* 5. Router Direction: The router provides direction to the node on how to
|
||||
|
@ -109,7 +109,6 @@ struct icmpv6_conn_s g_icmpv6_conn;
|
||||
void icmpv6_input(FAR struct net_driver_s *dev)
|
||||
{
|
||||
FAR struct icmpv6_iphdr_s *icmp = ICMPv6BUF;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_NET_STATISTICS
|
||||
g_netstats.icmpv6.recv++;
|
||||
@ -136,13 +135,9 @@ void icmpv6_input(FAR struct net_driver_s *dev)
|
||||
* solicitation came from.
|
||||
*/
|
||||
|
||||
ret = icmpv6_advertise(dev, icmp->srcipaddr);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto icmpv6_drop_packet;
|
||||
}
|
||||
icmpv6_advertise(dev, icmp->srcipaddr);
|
||||
|
||||
/* All statistics have been updated */
|
||||
/* All statistics have been updated. Nothing to do but exit. */
|
||||
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user