mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
6LoWPAN: Add configurable support for 6LoWPAN star topology. With this change, the endpoints which are the 'points' of the star will forward all traffic to the coordinator. The coordinator is assumed to be the 'hub' of the star. This function also implements IPv6 forwarding. That forwarding implementation is minimal, just enough to support the forwarding requirements of the star hub node.
This commit is contained in:
@@ -46,6 +46,9 @@ endif
|
||||
|
||||
ifeq ($(CONFIG_NET_IPv6),y)
|
||||
NET_CSRCS += ipv6_input.c
|
||||
ifeq ($(CONFIG_NET_IPFORWARD),y)
|
||||
NET_CSRCS += ipv6_forward.c
|
||||
endif
|
||||
endif
|
||||
|
||||
# I/O buffer chain support required?
|
||||
|
||||
@@ -425,6 +425,33 @@ uint16_t devif_conn_event(FAR struct net_driver_s *dev, FAR void *pvconn,
|
||||
uint16_t devif_dev_event(FAR struct net_driver_s *dev, void *pvconn,
|
||||
uint16_t flags);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv6_forward
|
||||
*
|
||||
* Description:
|
||||
* This function is called from ipv6_input when a packet is received that
|
||||
* is not destined for us. In this case, the packet may need to be
|
||||
* forwarded to another device (or sent back out the same device)
|
||||
* depending configuration, routing table information, and the IPv6
|
||||
* networks served by various network devices.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The device on which the packet was received and which contains
|
||||
* the IPv6 packet.
|
||||
* ipv6 - A convenience pointer to the IPv6 header in within the IPv6
|
||||
* packet
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned if the packet was successfully forward; A negated
|
||||
* errno value is returned if the packet is not forwardable. In that
|
||||
* latter case, the caller (ipv6_input()) should drop the packet.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6)
|
||||
int ipv6_forward(FAR struct net_driver_s *dev, FAR struct ipv6_hdr_s *ipv6);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Send data on the current connection.
|
||||
*
|
||||
|
||||
@@ -89,7 +89,8 @@ systime_t g_polltime;
|
||||
*
|
||||
* Description:
|
||||
* Generic output conversion hook. Only needed for IEEE802.15.4 for now
|
||||
* is a point where support for other conversions may be provided.
|
||||
* but this is a point where support for other conversions may be
|
||||
* provided.
|
||||
*
|
||||
* TCP output comes through three different mechansims. Either from:
|
||||
*
|
||||
@@ -136,7 +137,7 @@ static void devif_packet_conversion(FAR struct net_driver_s *dev,
|
||||
{
|
||||
/* Let 6LoWPAN convert IPv6 TCP output into IEEE802.15.4 frames. */
|
||||
|
||||
sixlowpan_tcp_send(dev);
|
||||
sixlowpan_tcp_send(dev, dev, ipv6);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
/****************************************************************************
|
||||
* net/devif/ipv6_forward.c
|
||||
*
|
||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "sixlowpan/sixlowpan.h"
|
||||
#include "devif/devif.h"
|
||||
|
||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv6_packet_conversion
|
||||
*
|
||||
* Description:
|
||||
* Generic output conversion hook. Only needed for IEEE802.15.4 for now
|
||||
* but this is a point where support for other conversions may be
|
||||
* provided.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN
|
||||
static int ipv6_packet_conversion(FAR struct net_driver_s *dev,
|
||||
FAR struct net_driver_s *fwddev,
|
||||
FAR struct ipv6_hdr_s *ipv6)
|
||||
{
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
/* Handle the case where multiple link layer protocols are supported */
|
||||
|
||||
if (dev->d_len > 0 && fwddev->d_lltype == NET_LL_IEEE802154)
|
||||
#else
|
||||
if (dev->d_len > 0)
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP
|
||||
if (ipv6->proto == IP_PROTO_TCP)
|
||||
{
|
||||
/* Let 6LoWPAN convert IPv6 TCP output into IEEE802.15.4 frames. */
|
||||
|
||||
sixlowpan_tcp_send(dev, fwddev, ipv6);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_NET_UDP
|
||||
if (ipv6->proto == IP_PROTO_UDP)
|
||||
{
|
||||
FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)dev->d_buf;
|
||||
|
||||
/* Let 6LoWPAN convert IPv6 UDP output into IEEE802.15.4 frames. */
|
||||
|
||||
sixlowpan_udp_send(dev, fwddev, ipv6);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Otherwise, we will have to drop the packet */
|
||||
|
||||
nwarn("WARNING: Dropping. Unsupported 6LoWPAN protocol: %d\n",
|
||||
ipv6->proto);
|
||||
|
||||
#ifdef CONFIG_NET_STATISTICS
|
||||
g_netstats.ipv6.drop++;
|
||||
#endif
|
||||
}
|
||||
|
||||
dev->d_len = 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
return -EPFNOSUPPORT;
|
||||
}
|
||||
#else
|
||||
# define ipv6_packet_conversion(dev, ipv6)
|
||||
#endif /* CONFIG_NET_6LOWPAN */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ipv6_forward
|
||||
*
|
||||
* Description:
|
||||
* This function is called from ipv6_input when a packet is received that
|
||||
* is not destined for us. In this case, the packet may need to be
|
||||
* forwarded to another device (or sent back out the same device)
|
||||
* depending configuration, routing table information, and the IPv6
|
||||
* networks served by various network devices.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The device on which the packet was received and which contains
|
||||
* the IPv6 packet.
|
||||
* ipv6 - A convenience pointer to the IPv6 header in within the IPv6
|
||||
* packet
|
||||
*
|
||||
* On input:
|
||||
* - dev->d_buf holds the received packet.
|
||||
* - dev->d_len holds the length of the received packet MINUS the
|
||||
* size of the L1 header. That was subtracted out by ipv6_input.
|
||||
* - ipv6 points to the IPv6 header with dev->d_buf.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero is returned if the packet was successfully forward; A negated
|
||||
* errno value is returned if the packet is not forwardable. In that
|
||||
* latter case, the caller (ipv6_input()) should drop the packet.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ipv6_forward(FAR struct net_driver_s *dev, FAR struct ipv6_hdr_s *ipv6)
|
||||
{
|
||||
/* Multiple network devices */
|
||||
|
||||
FAR struct net_driver_s *fwddev;
|
||||
int ret;
|
||||
|
||||
/* Search for a device that can forward this packet. This is a trivial
|
||||
* serch if there is only a single network device (CONFIG_NETDEV_MULTINIC
|
||||
* not defined). But netdev_findby_ipv6addr() will still assure
|
||||
* routability in that case.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
fwddev = netdev_findby_ipv6addr(ipv6->srcipaddr, ipv6->destipaddr);
|
||||
#else
|
||||
fwddev = netdev_findby_ipv6addr(ipv6->destipaddr);
|
||||
#endif
|
||||
if (fwddev == NULL)
|
||||
{
|
||||
nwarn("WARNING: Not routable\n");
|
||||
return (ssize_t)-ENETUNREACH;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NETDEV_MULTINIC)
|
||||
/* Check if we are forwarding on the same device that we received the
|
||||
* packet from.
|
||||
*/
|
||||
|
||||
if (fwddev != dev)
|
||||
{
|
||||
/* Perform any necessary packet conversions. */
|
||||
|
||||
ret = ipv6_packet_conversion(dev, fwddev, ipv6);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Extract the IPv6 + L3 header; Move the data payload to an IOB
|
||||
* chain.
|
||||
*/
|
||||
|
||||
/* Notify the forwarding device that TX data is available */
|
||||
|
||||
/* Set up to send the packet when the selected device polls for TX
|
||||
* data.
|
||||
*/
|
||||
|
||||
/* REVISIT: For Ethernet we may have to fix up the Ethernet header:
|
||||
* - source MAC, the MAC of the current device.
|
||||
* - dest MAC, the MAC associated with the destination IPv6 adress.
|
||||
* This will involve ICMPv6 and Neighbor Discovery.
|
||||
*/
|
||||
|
||||
/* Return success with dev->d_len = 0 */
|
||||
|
||||
# warning Missing logic
|
||||
nwarn("WARNING: Packet forwarding not yet supported "
|
||||
"across different devices\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* CONFIG_NETDEV_MULTINIC */
|
||||
|
||||
#if defined(CONFIG_NET_6LOWPAN) /* REVISIT: Currently only suport for
|
||||
* 6LoWPAN */
|
||||
{
|
||||
/* Single network device */
|
||||
|
||||
/* Perform any necessary packet conversions. If the packet was handled
|
||||
* via a backdoor path (or dropped), then dev->d_len will be zero. If
|
||||
* the packet needs to be forwarded in the normal manner then
|
||||
* dev->d_len will be unchanged.
|
||||
*/
|
||||
|
||||
ret = ipv6_packet_conversion(dev, dev, ipv6);
|
||||
if (ret < 0)
|
||||
{
|
||||
#ifdef CONFIG_NET_ETHERNET
|
||||
/* REVISIT: For Ethernet we may have to fix up the Ethernet header:
|
||||
* - source MAC, the MAC of the current device.
|
||||
* - dest MAC, the MAC associated with the destination IPv6 adress.
|
||||
* This will involve ICMPv6 and Neighbor Discovery.
|
||||
*/
|
||||
|
||||
/* Correct dev->d_buf by adding back the L1 header length */
|
||||
#endif
|
||||
|
||||
/* Nothing other 6LoWPAN forwarding is currently handled and that
|
||||
* case was dealt with in ipv6_packet_conversion().
|
||||
*/
|
||||
|
||||
# warning Missing logic
|
||||
nwarn("WARNING: Packet forwarding supported only for 6LoWPAN\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* CONFIG_NET_6LOWPAN */
|
||||
{
|
||||
nwarn("WARNING: Packet forwarding not supported in this configuration\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif /* CONFIG_NET_6LOWPAN */
|
||||
|
||||
/* Return success. ipv6_input will return to the network driver with
|
||||
* dev->d_len set to the packet size and the network driver will perform
|
||||
* the transfer.
|
||||
*/
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NET_IPv6 */
|
||||
+37
-8
@@ -87,6 +87,7 @@
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/netconfig.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
#include <nuttx/net/netstats.h>
|
||||
@@ -155,6 +156,12 @@ static int check_dev_destipaddr(FAR struct net_driver_s *dev, FAR void *arg)
|
||||
* is typically just a comparison the of the IPv6 destination address in
|
||||
* the IPv6 packet with the IPv6 address assigned to the receiving device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The device on which the packet was received and which contains
|
||||
* the IPv6 packet.
|
||||
* ipv6 - A convenience pointer to the IPv6 header in within the IPv6
|
||||
* packet
|
||||
*
|
||||
* Returned Value:
|
||||
* true - This packet is destined for us
|
||||
* false - This packet is NOT destined for us and may need to be forwarded.
|
||||
@@ -221,11 +228,14 @@ static bool check_destipaddr(FAR struct net_driver_s *dev,
|
||||
* Receive an IPv6 packet from the network device. Verify and forward to
|
||||
* L3 packet handling logic if the packet is destined for us.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The device on which the packet was received and which contains
|
||||
* the IPv6 packet.
|
||||
* Returned Value:
|
||||
* OK The packet was processed (or dropped) and can be discarded.
|
||||
* ERROR There is a matching connection, but could not dispatch the packet
|
||||
* yet. Currently useful for UDP when a packet arrives before a recv
|
||||
* call is in place.
|
||||
* OK - The packet was processed (or dropped) and can be discarded.
|
||||
* ERROR - There is a matching connection, but could not dispatch the
|
||||
* packet yet. Currently useful for UDP when a packet arrives
|
||||
* before a recv call is in place.
|
||||
*
|
||||
* If this function returns to the network driver with dev->d_len > 0,
|
||||
* that is an indication to the driver that there is an outgoing response
|
||||
@@ -337,12 +347,31 @@ int ipv6_input(FAR struct net_driver_s *dev)
|
||||
|
||||
if (!check_destipaddr(dev, ipv6))
|
||||
{
|
||||
/* No.. the packet is not destined for us.. drop it */
|
||||
#ifdef CONFIG_NET_IPFORWARD
|
||||
/* Not destined for us, try to forward the packet */
|
||||
|
||||
ret = ipv6forward(dev, ipv6);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* The packet was forwarded. Return success; d_len will
|
||||
* be set appropriately by the forwarding logic: Cleared
|
||||
* if the packet is forward via anoother device or non-
|
||||
* zero if it will be forwarded by the same device that
|
||||
* it was received on.
|
||||
*/
|
||||
|
||||
return OK;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Not destined for us and not forwardable... drop the packet. */
|
||||
|
||||
#ifdef CONFIG_NET_STATISTICS
|
||||
g_netstats.ipv6.drop++;
|
||||
g_netstats.ipv6.drop++;
|
||||
#endif
|
||||
goto drop;
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +417,7 @@ int ipv6_input(FAR struct net_driver_s *dev)
|
||||
{
|
||||
/* Let 6LoWPAN handle the TCP output */
|
||||
|
||||
sixlowpan_tcp_send(dev);
|
||||
sixlowpan_tcp_send(dev, dev, ipv6);
|
||||
|
||||
/* Drop the packet in the d_buf */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user