diff --git a/net/Kconfig b/net/Kconfig index 62b5e5ae391..559360052ab 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -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" diff --git a/net/devif/Make.defs b/net/devif/Make.defs index f46aa5c26a0..714f4356e1d 100644 --- a/net/devif/Make.defs +++ b/net/devif/Make.defs @@ -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? diff --git a/net/devif/devif.h b/net/devif/devif.h index e90377dd585..78fcce32e59 100644 --- a/net/devif/devif.h +++ b/net/devif/devif.h @@ -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. * diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c index 41475cb9b58..08d6c99e8ae 100644 --- a/net/devif/devif_poll.c +++ b/net/devif/devif_poll.c @@ -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 { diff --git a/net/devif/ipv6_forward.c b/net/devif/ipv6_forward.c new file mode 100644 index 00000000000..e8b688c6aba --- /dev/null +++ b/net/devif/ipv6_forward.c @@ -0,0 +1,262 @@ +/**************************************************************************** + * net/devif/ipv6_forward.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#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 */ diff --git a/net/devif/ipv6_input.c b/net/devif/ipv6_input.c index b6889a4f352..0dedcd0b3e2 100644 --- a/net/devif/ipv6_input.c +++ b/net/devif/ipv6_input.c @@ -87,6 +87,7 @@ #include +#include #include #include #include @@ -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 */ diff --git a/net/sixlowpan/sixlowpan.h b/net/sixlowpan/sixlowpan.h index a175a3d3f52..aad911597a0 100644 --- a/net/sixlowpan/sixlowpan.h +++ b/net/sixlowpan/sixlowpan.h @@ -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 */ diff --git a/net/sixlowpan/sixlowpan_framelist.c b/net/sixlowpan/sixlowpan_framelist.c index 53921963acc..2f7b1398178 100644 --- a/net/sixlowpan/sixlowpan_framelist.c +++ b/net/sixlowpan/sixlowpan_framelist.c @@ -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. * diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index 0c94d05dbaf..221d3ad2ef3 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -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 * diff --git a/net/sixlowpan/sixlowpan_tcpsend.c b/net/sixlowpan/sixlowpan_tcpsend.c index 4e3701e6fed..eac31b90261 100644 --- a/net/sixlowpan/sixlowpan_tcpsend.c +++ b/net/sixlowpan/sixlowpan_tcpsend.c @@ -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); } } } diff --git a/net/sixlowpan/sixlowpan_udpsend.c b/net/sixlowpan/sixlowpan_udpsend.c index 75b4b2ba431..a0f6ee370c2 100644 --- a/net/sixlowpan/sixlowpan_udpsend.c +++ b/net/sixlowpan/sixlowpan_udpsend.c @@ -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 */ diff --git a/net/sixlowpan/sixlowpan_utils.c b/net/sixlowpan/sixlowpan_utils.c index 6f2948479bf..b404d37fa69 100644 --- a/net/sixlowpan/sixlowpan_utils.c +++ b/net/sixlowpan/sixlowpan_utils.c @@ -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 *