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
|
* 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
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user