ICMPv6: This completes coding of the ICMPv6 auto-configuration feature. It is not yet functional

This commit is contained in:
Gregory Nutt 2015-02-03 15:40:56 -06:00
parent 2c14d4ef93
commit 9791e829f5
5 changed files with 106 additions and 80 deletions

View File

@ -93,10 +93,6 @@ struct icmpv6_rnotify_s
{
#ifdef CONFIG_NET_MULTILINK
FAR struct icmpv6_notify_s *rn_flink; /* Supports singly linked list */
#endif
net_ipv6addr_t rn_prefix; /* Waited for router prefix */
uint8_t rn_preflen; /* Prefix length (# valid leading bits) */
#ifdef CONFIG_NET_MULTILINK
char rn_ifname[IFNAMSIZ]; /* Device name */
#endif
sem_t rn_sem; /* Will wake up the waiter */
@ -431,6 +427,9 @@ int icmpv6_rwait(FAR struct icmpv6_rnotify_s *notify,
* wake-up any threads that may be waiting for this particular Router
* Advertisement.
*
* NOTE: On success the network has the new address applied and is in
* the down state.
*
* Assumptions:
* This function is called from the MAC device driver indirectly through
* icmpv6_icmpv6in() will execute with the network locked.
@ -438,8 +437,8 @@ int icmpv6_rwait(FAR struct icmpv6_rnotify_s *notify,
****************************************************************************/
#ifdef CONFIG_NET_ICMPv6_AUTOCONF
void icmpv6_rnotify(FAR struct net_driver_s *dev, const net_ipv6addr_t prefix,
unsigned int preflen);
void icmpv6_rnotify(FAR struct net_driver_s *dev, const net_ipv6addr_t draddr,
const net_ipv6addr_t prefix, unsigned int preflen);
#else
# define icmpv6_rnotify(d,p,l)
#endif

View File

@ -52,6 +52,7 @@
#include <nuttx/net/netdev.h>
#include "devif/devif.h"
#include "netdev/netdev.h"
#include "icmpv6/icmpv6.h"
/****************************************************************************
@ -327,7 +328,7 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
ndbg("ERROR: Only Ethernet is supported\n");
return -ENOSYS;
#else
#else /* CONFIG_NET_ETHERNET */
struct icmpv6_rnotify_s notify;
net_ipv6addr_t lladdr;
net_lock_t save;
@ -348,6 +349,11 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
return -ENOSYS;
}
#endif
/* The interface should be in the down state */
save = net_lock();
netdev_ifdown(dev);
net_unlock(save);
/* IPv6 Stateless Autoconfiguration
* Reference: http://www.tcpipguide.com/free/t_IPv6AutoconfiguratinoandRenumbering.htm
@ -378,6 +384,10 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
memset(&lladdr[1], 0, 4* sizeof(uint16_t)); /* 64 more zeroes */
memcpy(&lladdr[5], dev->d_mac.ether_addr_octet, sizeof(struct ether_addr)); /* 48-bit Ethernet address */
nvdbg("lladdr=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
lladdr[0], lladdr[1], lladdr[2], lladdr[3],
lladdr[4], lladdr[6], lladdr[6], lladdr[7]);
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
/* 2. Link-Local Address Uniqueness Test: The node tests to ensure that
* the address it generated isn't for some reason already in use on the
@ -410,6 +420,11 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
net_ipv6addr_copy(dev->d_ipv6addr, lladdr);
/* Bring the interface up with the new, temporary IP address */
save = net_lock();
netdev_ifup(dev);
/* 4. Router Contact: The node next attempts to contact a local router for
* more information on continuing the configuration. This is done either
* by listening for Router Advertisement messages sent periodically by
@ -417,7 +432,6 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
* for information on what to do next.
*/
save = net_lock();
for (retries = 0; retries < CONFIG_ICMPv6_AUTOCONF_MAXTRIES; retries++)
{
/* Set up the Router Advertisement BEFORE we send the Router
@ -447,17 +461,22 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
break;
}
nvdbg("Timed out... retrying\n");
nvdbg("Timed out... retrying %d\n", retries + 1);
}
net_unlock(save);
/* Check for failures */
/* Check for failures. Note: On successful return, the network will be
* in the down state, but not in the event of failures.
*/
if (ret < 0)
{
ndbg("ERROR: Failed to get the router advertisement: %d (retries=%d)\n",
ret, retries);
/* Take the network down and return the failure */
netdev_ifdown(dev);
net_unlock(save);
return ret;
}
@ -466,20 +485,23 @@ int icmpv6_autoconfig(FAR struct net_driver_s *dev)
* network "stateful" auto-configuration is in use, and tell it the
* address of a DHCP server to use. Alternately, it will tell the host
* how to determine its global Internet address.
*/
#warning Missing logic
/* 6. Global Address Configuration: Assuming that stateless auto-
*
* 6. Global Address Configuration: Assuming that stateless auto-
* configuration is in use on the network, the host will configure
* itself with its globally-unique Internet address. This address is
* generally formed from a network prefix provided to the host by the
* router, combined with the device's identifier as generated in the
* first step.
*/
#warning Missing logic
return ret;
#endif
/* On success, the new address was already set (in icmpv_rnotify()). We
* need only to bring the network back to the up state and return success.
*/
netdev_ifup(dev);
net_unlock(save);
return OK;
#endif /* CONFIG_NET_ETHERNET */
}
#endif /* CONFIG_NET_ICMPv6_AUTOCONF */

View File

@ -321,7 +321,7 @@ void icmpv6_input(FAR struct net_driver_s *dev)
{
/* Yes.. Notify any waiting threads */
icmpv6_rnotify(dev, opt->prefix, opt->preflen);
icmpv6_rnotify(dev, icmp->srcipaddr, opt->prefix, opt->preflen);
goto icmpv_send_nothing;
}

View File

@ -85,6 +85,11 @@ void netdev_semtake(void);
void netdev_semgive(void);
#endif
/* netdev_ioctl.c ************************************************************/
void netdev_ifup(FAR struct net_driver_s *dev);
void netdev_ifdown(FAR struct net_driver_s *dev);
/* netdev_findbyname.c *******************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0

View File

@ -1,7 +1,7 @@
/****************************************************************************
* net/netdev/netdev_ioctl.c
*
* Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2012, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -315,58 +315,6 @@ static void ioctl_setipv6addr(FAR net_ipv6addr_t outaddr,
}
#endif
/****************************************************************************
* Name: ioctl_ifup / ioctl_ifdown
*
* Description:
* Bring the interface up/down
*
****************************************************************************/
static void ioctl_ifup(FAR struct net_driver_s *dev)
{
/* Make sure that the device supports the d_ifup() method */
if (dev->d_ifup)
{
/* Is the interface already up? */
if ((dev->d_flags & IFF_UP) == 0)
{
/* No, bring the interface up now */
if (dev->d_ifup(dev) == OK)
{
/* Mark the interface as up */
dev->d_flags |= IFF_UP;
}
}
}
}
static void ioctl_ifdown(FAR struct net_driver_s *dev)
{
/* Make sure that the device supports the d_ifdown() method */
if (dev->d_ifdown)
{
/* Is the interface already down? */
if ((dev->d_flags & IFF_UP) != 0)
{
/* No, take the interface down now */
if (dev->d_ifdown(dev) == OK)
{
/* Mark the interface as down */
dev->d_flags &= ~IFF_UP;
}
}
}
}
/****************************************************************************
* Name: netdev_ifrdev
*
@ -445,9 +393,9 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
dev = netdev_ifrdev(req);
if (dev)
{
ioctl_ifdown(dev);
netdev_ifdown(dev);
ioctl_setipv4addr(&dev->d_ipaddr, &req->ifr_addr);
ioctl_ifup(dev);
netdev_ifup(dev);
ret = OK;
}
}
@ -538,9 +486,9 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
{
FAR struct lifreq *lreq = (FAR struct lifreq *)req;
ioctl_ifdown(dev);
netdev_ifdown(dev);
ioctl_setipv6addr(dev->d_ipv6addr, &lreq->lifr_addr);
ioctl_ifup(dev);
netdev_ifup(dev);
ret = OK;
}
}
@ -650,7 +598,7 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
{
/* Yes.. bring the interface up */
ioctl_ifup(dev);
netdev_ifup(dev);
}
/* Is this a request to take the interface down? */
@ -659,7 +607,7 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
{
/* Yes.. take the interface down */
ioctl_ifdown(dev);
netdev_ifdown(dev);
}
}
@ -713,7 +661,7 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
dev = netdev_ifrdev(req);
if (dev)
{
ioctl_ifdown(dev);
netdev_ifdown(dev);
#ifdef CONFIG_NET_IPv4
dev->d_ipaddr = 0;
#endif
@ -1051,4 +999,56 @@ errout:
return ERROR;
}
/****************************************************************************
* Name: netdev_ifup / netdev_ifdown
*
* Description:
* Bring the interface up/down
*
****************************************************************************/
void netdev_ifup(FAR struct net_driver_s *dev)
{
/* Make sure that the device supports the d_ifup() method */
if (dev->d_ifup)
{
/* Is the interface already up? */
if ((dev->d_flags & IFF_UP) == 0)
{
/* No, bring the interface up now */
if (dev->d_ifup(dev) == OK)
{
/* Mark the interface as up */
dev->d_flags |= IFF_UP;
}
}
}
}
void netdev_ifdown(FAR struct net_driver_s *dev)
{
/* Make sure that the device supports the d_ifdown() method */
if (dev->d_ifdown)
{
/* Is the interface already down? */
if ((dev->d_flags & IFF_UP) != 0)
{
/* No, take the interface down now */
if (dev->d_ifdown(dev) == OK)
{
/* Mark the interface as down */
dev->d_flags &= ~IFF_UP;
}
}
}
}
#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */