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:
Gregory Nutt 2017-06-28 15:39:21 -06:00
parent ca97725e55
commit a93f130002
12 changed files with 677 additions and 23 deletions

View File

@ -137,6 +137,7 @@ config NET_6LOWPAN
select NETDEV_MULTINIC if NET_ETHERNET || NET_LOOPBACK || NET_SLIP || NET_TUN
select NET_MULTILINK if NET_ETHERNET || NET_LOOPBACK || NET_SLIP || NET_TUN
select NETDEV_IOCTL
select NET_HAVE_STAR
depends on NET_IPv6
---help---
Enable support for IEEE 802.15.4 Low power Wireless Personal Area
@ -286,6 +287,60 @@ source "net/sixlowpan/Kconfig"
endmenu # Internet Protocol Selection
config NET_HAVE_STAR
bool
default n
---help---
Automatically enabled if at least one selected L2 protocol supports
a STAR topology.
config NET_IPFORWARD
bool "Enable L2 forwarding"
default n
depends on NET_IPv6
---help---
Enable forwarding of IPv6 packets. Packets received with IPv6
addresses which are not supported by this platform will be forwarded
to the appropriate network device. Routing table support may be
required.
NOTE: L2 forwarding only supported for IPv6. There is no technical
reason why IPv4 forwarding has not been implemented, it just has
not yet been done.
config NET_STAR
bool "Enable star topology"
default n
depends on NET_HAVE_STAR && NET_IPv6
---help---
Enable support for a star network topology.
NOTE: Currently only supported by 6LoWPAN.
NOTE: L2 forwarding only supported for IPv6.
choice
prompt "Node role"
depends on NET_STARTOPOLOGY
default NET_STARTPOINT
---help---
Specifies the role of this not in the star configuration.
config NET_STARPOINT
bool "Point node in star"
---help---
The node is a "point" in the star configuration and must send all
packets to the star hub node.
config NET_STARHUB
bool "Hub node of star"
select NET_IPFORWARD
---help---
This is the "hub" node in the star configurations. It will receive
packets packets from all "point" nodes and perform L2 forwarding of
the packets that are not destined for this node.
endchoice # Node role
source "net/socket/Kconfig"
source "net/pkt/Kconfig"
source "net/local/Kconfig"

View File

@ -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?

View File

@ -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.
*

View File

@ -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
{

262
net/devif/ipv6_forward.c Normal file
View File

@ -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 */

View File

@ -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 */

View File

@ -54,6 +54,7 @@
****************************************************************************/
struct net_driver_s; /* Forward reference */
struct ipv6_hdr_s; /* Forward reference */
struct socket; /* Forward reference */
struct sockaddr; /* Forward reference */
@ -126,7 +127,13 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
* the IEEE80215.4 frames.
*
* Parameters:
* dev - An instance of nework device state structure
* dev - The network device containing the packet to be sent.
* fwddev - The network device used to send the data. This will be the
* same device except for the IP forwarding case where packets
* are sent across devices.
* ipv6 - A pointer to the IPv6 header in dev->d_buf which lies AFTER
* the L1 header. NOTE: dev->d_len must have been decremented
* by the size of any preceding MAC header.
*
* Returned Value:
* None
@ -136,7 +143,9 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
*
****************************************************************************/
void sixlowpan_tcp_send(FAR struct net_driver_s *dev);
void sixlowpan_tcp_send(FAR struct net_driver_s *dev,
FAR struct net_driver_s *fwddev,
FAR struct ipv6_hdr_s *ipv6);
/****************************************************************************
* Name: psock_6lowpan_udp_send
@ -200,5 +209,35 @@ ssize_t psock_6lowpan_udp_sendto(FAR struct socket *psock,
FAR const struct sockaddr *to,
socklen_t tolen);
/****************************************************************************
* Name: sixlowpan_udp_send
*
* Description:
* Handles forwarding a UDP packet via 6LoWPAN. This is currently only
* used by the IPv6 forwarding logic.
*
* Parameters:
* dev - An instance of nework device state structure
* fwddev - The network device used to send the data. This will be the
* same device except for the IP forwarding case where packets
* are sent across devices.
* ipv6 - A pointer to the IPv6 header in dev->d_buf which lies AFTER
* the L1 header. NOTE: dev->d_len must have been decremented
* by the size of any preceding MAC header.
*
* Returned Value:
* None
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/
#ifdef CONFIG_NET_IPFORWARD
void sixlowpan_udp_send(FAR struct net_driver_s *dev,
FAR struct net_driver_s *fwddev,
FAR struct ipv6_hdr_s *ipv6);
#endif
#endif /* CONFIG_NET_6LOWPAN */
#endif /* _NET_SIXLOWPAN_SIXLOWPAN_H */

View File

@ -324,6 +324,23 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
&ieee->i_dev.d_mac.ieee802154);
#endif
#ifdef CONFIG_NET_STARPOINT
/* If this node is a "point" in a star topology, then the destination
* MAC address is the address of the hub/PAN coordinator.
*/
if (destmac->extended)
{
pktmeta.dextended = TRUE;
ret = sixlowpan_coord_eaddr(ieee, pktmeta.dest.eaddr.u8);
}
else
{
ret = sixlowpan_coord_saddr(ieee, pktmeta.dest.saddr.u8);
}
#else
/* Otherwise, it is the actual destination node address */
if (destmac->extended)
{
pktmeta.dextended = TRUE;
@ -333,6 +350,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee,
{
sixlowpan_saddrcopy(pktmeta.dest.saddr.u8, destmac->u.saddr.u8);
}
#endif
/* Get the destination PAN ID.
*

View File

@ -593,6 +593,46 @@ bool sixlowpan_iseaddrbased(const net_ipv6addr_t ipaddr,
bool sixlowpan_ismacbased(const net_ipv6addr_t ipaddr,
FAR const struct sixlowpan_tagaddr_s *addr);
/****************************************************************************
* Name: sixlowpan_coord_eaddr
*
* Description:
* Get the extended address of the PAN coordinator.
*
* Input parameters:
* ieee - A reference IEEE802.15.4 MAC network device structure.
* eaddr - The location in which to return the extended address.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_NET_STARPOINT
int sixlowpan_coord_eaddr(FAR struct ieee802154_driver_s *ieee,
FAR uint8_t *eaddr);
#endif
/****************************************************************************
* Name: sixlowpan_coord_saddr
*
* Description:
* Get the short address of the PAN coordinator.
*
* Input parameters:
* ieee - A reference IEEE802.15.4 MAC network device structure.
* saddr - The location in which to return the short address.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_NET_STARPOINT
int sixlowpan_coord_saddr(FAR struct ieee802154_driver_s *ieee,
FAR uint8_t *saddr);
#endif
/****************************************************************************
* Name: sixlowpan_src_panid
*

View File

@ -63,7 +63,6 @@
/* Buffer access helpers */
#define IPv6BUF(dev) ((FAR struct ipv6_hdr_s *)((dev)->d_buf))
#define TCPBUF(dev) ((FAR struct tcp_hdr_s *)(&(dev)->d_buf[IPv6_HDRLEN]))
/****************************************************************************
@ -540,7 +539,7 @@ static uint16_t tcp_send_interrupt(FAR struct net_driver_s *dev,
*
* NOTE: tcp_appsend() normally increments conn->unacked based on
* the value of dev->d_sndlen. However, dev->d_len is always
* zero for 6LoWPAN since it does no send via the dev->d_bufuse
* zero for 6LoWPAN since it does not send via the dev->d_buf
* but, rather, uses a backdoor frame interface with the IEEE
* 802.15.4 MAC.
*/
@ -876,7 +875,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
* TCP output comes through three different mechansims. Either from:
*
* 1. TCP socket output. For the case of TCP output to an
* IEEE802.15.4 device, the TCP output is caught in the socket
* IEEE802.15.4, the TCP output is caught in the socket
* send()/sendto() logic and and redirected to psock_6lowpan_tcp_send().
* 2. TCP output from the TCP state machine. That will occur
* during TCP packet processing by the TCP state meachine.
@ -889,7 +888,13 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
* the IEEE80215.4 frames.
*
* Parameters:
* dev - An instance of nework device state structure
* dev - The network device containing the packet to be sent.
* fwddev - The network device used to send the data. This will be the
* same device except for the IP forwarding case where packets
* are sent across devices.
* ipv6 - A pointer to the IPv6 header in dev->d_buf which lies AFTER
* the L1 header. NOTE: dev->d_len must have been decremented
* by the size of any preceding MAC header.
*
* Returned Value:
* None
@ -899,15 +904,17 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf,
*
****************************************************************************/
void sixlowpan_tcp_send(FAR struct net_driver_s *dev)
void sixlowpan_tcp_send(FAR struct net_driver_s *dev,
FAR struct net_driver_s *fwddev,
FAR struct ipv6_hdr_s *ipv6)
{
DEBUGASSERT(dev != NULL && dev->d_len > 0);
DEBUGASSERT(dev != NULL && dev->d_len > 0 && fwddev != NULL);
/* Double check */
ninfo("d_len %u\n", dev->d_len);
sixlowpan_dumpbuffer("Outgoing TCP packet",
(FAR const uint8_t *)IPv6BUF(dev), dev->d_len);
(FAR const uint8_t *)ipv6, dev->d_len);
if (dev != NULL && dev->d_len > 0)
{
@ -918,7 +925,7 @@ void sixlowpan_tcp_send(FAR struct net_driver_s *dev)
* and the TCP state machine should only response with TCP packets.
*/
ipv6hdr = (FAR struct ipv6tcp_hdr_s *)(dev->d_buf);
ipv6hdr = (FAR struct ipv6tcp_hdr_s *)ipv6;
/* The TCP data payload should follow the IPv6 header plus the
* protocol header.
@ -960,12 +967,12 @@ void sixlowpan_tcp_send(FAR struct net_driver_s *dev)
{
/* Convert the outgoing packet into a frame list. */
buf = dev->d_buf + hdrlen;
buf = (FAR uint8_t *)ipv6 + hdrlen;
buflen = dev->d_len - hdrlen;
(void)sixlowpan_queue_frames(
(FAR struct ieee802154_driver_s *)dev, &ipv6hdr->ipv6,
buf, buflen, &destmac);
(FAR struct ieee802154_driver_s *)fwddev,
&ipv6hdr->ipv6, buf, buflen, &destmac);
}
}
}

View File

@ -407,4 +407,101 @@ ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf,
sizeof(struct sockaddr_in6));
}
/****************************************************************************
* Name: sixlowpan_udp_send
*
* Description:
* Handles forwarding a UDP packet via 6LoWPAN. This is currently only
* used by the IPv6 forwarding logic.
*
* Parameters:
* dev - An instance of nework device state structure
* fwddev - The network device used to send the data. This will be the
* same device except for the IP forwarding case where packets
* are sent across devices.
* ipv6 - A pointer to the IPv6 header in dev->d_buf which lies AFTER
* the L1 header. NOTE: dev->d_len must have been decremented
* by the size of any preceding MAC header.
*
* Returned Value:
* None
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/
#ifdef CONFIG_NET_IPFORWARD
void sixlowpan_udp_send(FAR struct net_driver_s *dev,
FAR struct net_driver_s *fwddev,
FAR struct ipv6_hdr_s *ipv6)
{
FAR struct ipv6udp_hdr_s *ipv6udp = (FAR struct ipv6udp_hdr_s *)ipv6;
/* Double check */
DEBUGASSERT(dev != NULL && dev->d_len > 0);
ninfo("d_len %u\n", dev->d_len);
if (dev != NULL && dev->d_len > 0)
{
sixlowpan_dumpbuffer("Outgoing UDP packet",
(FAR const uint8_t *)ipv6udp, dev->d_len);
/* The UDP data payload should follow the IPv6 header plus the
* protocol header.
*/
if (ipv6udp->ipv6.proto != IP_PROTO_UDP)
{
nwarn("WARNING: Expected UDP protoype: %u vs %s\n",
ipv6udp->ipv6.proto, IP_PROTO_UDP);
}
else
{
struct sixlowpan_tagaddr_s destmac;
FAR uint8_t *buf;
uint16_t hdrlen;
uint16_t buflen;
/* Get the IEEE 802.15.4 MAC address of the destination. This
* assumes an encoding of the MAC address in the IPv6 address.
*/
sixlowpan_addrfromip(ipv6udp->ipv6.destipaddr, &destmac);
/* Get the IPv6 + UDP combined header length. The size of the UDP
* header is encoded in the top 4 bits of the udpoffset field (in
* units of 32-bit words).
*/
hdrlen = IPv6_HDRLEN + (((uint16_t)ipv6udp->udp.udpoffset >> 4) << 2);
/* Drop the packet if the buffer length is less than this. */
if (hdrlen > dev->d_len)
{
nwarn("WARNING: Dropping small UDP packet: %u < %u\n",
buflen, hdrlen);
}
else
{
/* Convert the outgoing packet into a frame list. */
buf = (FAR uint8_t *)ipv6 + hdrlen;
buflen = dev->d_len - hdrlen;
(void)sixlowpan_queue_frames(
(FAR struct ieee802154_driver_s *)fwddev,
&ipv6udp->ipv6, buf, buflen, &destmac);
}
}
}
dev->d_len = 0;
}
#endif
#endif /* CONFIG_NET_6LOWPAN && CONFIG_NET_UDP */

View File

@ -227,6 +227,82 @@ bool sixlowpan_ismacbased(const net_ipv6addr_t ipaddr,
}
}
/****************************************************************************
* Name: sixlowpan_coord_eaddr
*
* Description:
* Get the extended address of the PAN coordinator.
*
* Input parameters:
* ieee - A reference IEEE802.15.4 MAC network device structure.
* eaddr - The location in which to return the extended address.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_NET_STARPOINT
int sixlowpan_coord_eaddr(FAR struct ieee802154_driver_s *ieee,
FAR uint8_t *eaddr)
{
FAR struct net_driver_s *dev = &ieee->i_dev;
struct ieee802154_netmac_s arg;
int ret;
memcpy(arg.ifr_name, ieee->i_dev.d_ifname, IFNAMSIZ);
arg.u.getreq.attr = IEEE802154_ATTR_MAC_COORD_EADDR ;
ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST,
(unsigned long)((uintptr_t)&arg));
if (ret < 0)
{
nerr("ERROR: MAC802154IOC_MLME_GET_REQUEST failed: %d\n", ret);
return ret;
}
IEEE802154_EADDRCOPY(eaddr, arg.u.getreq.attrval.mac.eaddr);
return OK;
}
#endif
/****************************************************************************
* Name: sixlowpan_coord_saddr
*
* Description:
* Get the short address of the PAN coordinator.
*
* Input parameters:
* ieee - A reference IEEE802.15.4 MAC network device structure.
* saddr - The location in which to return the short address.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
#ifdef CONFIG_NET_STARPOINT
int sixlowpan_coord_saddr(FAR struct ieee802154_driver_s *ieee,
FAR uint8_t *saddr)
{
FAR struct net_driver_s *dev = &ieee->i_dev;
struct ieee802154_netmac_s arg;
int ret;
memcpy(arg.ifr_name, ieee->i_dev.d_ifname, IFNAMSIZ);
arg.u.getreq.attr = IEEE802154_ATTR_MAC_COORD_SADDR ;
ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST,
(unsigned long)((uintptr_t)&arg));
if (ret < 0)
{
nerr("ERROR: MAC802154IOC_MLME_GET_REQUEST failed: %d\n", ret);
return ret;
}
IEEE802154_SADDRCOPY(saddr, arg.u.getreq.attrval.mac.saddr);
return OK;
}
#endif
/****************************************************************************
* Name: sixlowpan_src_panid
*