From 64933246c34fef9b10d9930005e633227e889548 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 28 Mar 2017 14:08:54 -0600 Subject: [PATCH] 6loWPAN: Tie 6loWPAN send into common socket send logic. --- include/nuttx/net/net.h | 2 +- net/netdev/netdev_register.c | 2 +- net/sixlowpan/Make.defs | 2 +- net/sixlowpan/sixlowpan.h | 51 +++++ net/sixlowpan/sixlowpan_output.c | 77 -------- net/sixlowpan/sixlowpan_send.c | 309 +++++++++++++++++++++++++++++++ net/socket/send.c | 32 +++- net/tcp/tcp_send.c | 14 +- net/tcp/tcp_send_buffered.c | 2 +- net/tcp/tcp_send_unbuffered.c | 2 +- 10 files changed, 401 insertions(+), 92 deletions(-) delete mode 100644 net/sixlowpan/sixlowpan_output.c create mode 100644 net/sixlowpan/sixlowpan_send.c diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index 1c64351fe2e..337e0a63665 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -79,7 +79,7 @@ enum net_lltype_e NET_LL_SLIP, /* Serial Line Internet Protocol (SLIP) */ NET_LL_TUN, /* TUN Virtual Network Device */ NET_LL_IEEE80211, /* IEEE 802.11 */ - NET_LL_6LOWPAN /* IEEE 802.15.4 6LoWPAN */ + NET_LL_IEEE805154 /* IEEE 802.15.4 MAC */ }; /* This defines a bitmap big enough for one bit for each socket option */ diff --git a/net/netdev/netdev_register.c b/net/netdev/netdev_register.c index d275f6abfda..9a3a01c66d2 100644 --- a/net/netdev/netdev_register.c +++ b/net/netdev/netdev_register.c @@ -228,7 +228,7 @@ int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype) #endif #ifdef CONFIG_NET_6LOWPAN - case NET_LL_6LOWPAN: /* IEEE 802.15.4 */ + case NET_LL_IEEE802154: /* IEEE 802.15.4 MAC */ dev->d_llhdrlen = 0; /* REVISIT */ dev->d_mtu = SIXLOWPAN_MAC_MAXFRAME; #ifdef CONFIG_NET_TCP diff --git a/net/sixlowpan/Make.defs b/net/sixlowpan/Make.defs index 703f89cf52d..1e581517315 100644 --- a/net/sixlowpan/Make.defs +++ b/net/sixlowpan/Make.defs @@ -40,7 +40,7 @@ ifeq ($(CONFIG_NET_6LOWPAN),y) # Include IEEE 802.15.4 file in the build NET_CSRCS += sixlowpan_initialize.c sixlowpan_globals.c -NET_CSRCS += sixlowpan_input.c sixlowpan_output.c +NET_CSRCS += sixlowpan_input.c sixlowpan_send.c NET_CSRCS += sixlowpan_compressor.c sixlowpan_sniffer.c ifeq ($(CONFIG_NET_6LOWPAN_COMPRESSION_HC1),y) diff --git a/net/sixlowpan/sixlowpan.h b/net/sixlowpan/sixlowpan.h index ab36cf86d41..46a282b41da 100644 --- a/net/sixlowpan/sixlowpan.h +++ b/net/sixlowpan/sixlowpan.h @@ -77,6 +77,7 @@ extern FAR struct sixlowpan_rime_sniffer_s *g_sixlowpan_sniffer; ****************************************************************************/ struct net_driver_s; /* Forward reference */ +struct socket; /* Forward reference */ /**************************************************************************** * Name: sixlowpan_initialize @@ -99,6 +100,56 @@ struct net_driver_s; /* Forward reference */ void sixlowpan_initialize(void); +/**************************************************************************** + * Function: psock_6lowpan_tcp_send + * + * Description: + * psock_6lowpan_tcp_send() call may be used only when the TCP socket is in a + * connected state (so that the intended recipient is known). + * + * Parameters: + * psock - An instance of the internal socket structure. + * buf - Data to send + * len - Length of data to send + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -1 is returned, and errno is set appropriately. Returned error numbers + * must be consistent with definition of errors reported by send() or + * sendto(). + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, + size_t len); +#endif + +/**************************************************************************** + * Function: psock_6lowpan_udp_send + * + * Description: + * psock_6lowpan_udp_send() call may be used with connectionlesss UDP + * sockets. + * + * Parameters: + * psock - An instance of the internal socket structure. + * buf - Data to send + * len - Length of data to send + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -1 is returned, and errno is set appropriately. Returned error numbers + * must be consistent with definition of errors reported by send() or + * sendto(). + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP +ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf, + size_t len); +#endif + /**************************************************************************** * Name: sixlowpan_output * diff --git a/net/sixlowpan/sixlowpan_output.c b/net/sixlowpan/sixlowpan_output.c deleted file mode 100644 index af4b7c9d63a..00000000000 --- a/net/sixlowpan/sixlowpan_output.c +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** - * net/sixlowpan/sixlowpan_output.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 "nuttx/net/netdev.h" -#include "sixlowpan/sixlowpan.h" - -#ifdef CONFIG_NET_6LOWPAN - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: sixlowpan_output - * - * Description: - * Process an outgoing UDP or TCP packet. Called from UDP/TCP logic to - * determine if the the packet should be formatted for 6loWPAN output. - * - * Input Parameters: - * dev - The IEEE802.15.4 MAC network driver interface. - * - * Returned Value: - * Ok is returned on success; Othewise a negated errno value is returned. - * This function is expected to fail if the driver is not an IEEE802.15.4 - * MAC network driver. In that case, the UDP/TCP will fall back to normal - * IPv4/IPv6 formatting. - * - ****************************************************************************/ - -int sixlowpan_output(FAR struct net_driver_s *dev) -{ - /* REVISIT: To be provided */ - return -ENOSYS; -} - -#endif /* CONFIG_NET_6LOWPAN */ diff --git a/net/sixlowpan/sixlowpan_send.c b/net/sixlowpan/sixlowpan_send.c new file mode 100644 index 00000000000..de338945975 --- /dev/null +++ b/net/sixlowpan/sixlowpan_send.c @@ -0,0 +1,309 @@ +/**************************************************************************** + * net/sixlowpan/sixlowpan_send.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 +#include + +#include "nuttx/net/net.h" +#include "nuttx/net/netdev.h" + +#include "netdev/netdev.h" +#include "socket/socket.h" +#include "tcp/tcp.h" +#include "udp/udp.h" +#include "sixlowpan/sixlowpan.h" + +#ifdef CONFIG_NET_6LOWPAN + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sixlowpan_send + * + * Description: + * Process an outgoing UDP or TCP packet. Called from UDP/TCP logic to + * determine if the the packet should be formatted for 6loWPAN output. + * + * Input Parameters: + * dev - The IEEE802.15.4 MAC network driver interface. + * + * Returned Value: + * Ok is returned on success; Othewise a negated errno value is returned. + * This function is expected to fail if the driver is not an IEEE802.15.4 + * MAC network driver. In that case, the UDP/TCP will fall back to normal + * IPv4/IPv6 formatting. + * + * Assumptions: + * Called with the network locked. + * + ****************************************************************************/ + +int sixlowpan_send(FAR struct net_driver_s *dev) +{ + net_lock(); + /* REVISIT: To be provided */ + net_unlock(); + return -ENOSYS; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: psock_6lowpan_tcp_send + * + * Description: + * psock_6lowpan_tcp_send() call may be used only when the TCP socket is in a + * connected state (so that the intended recipient is known). + * + * Parameters: + * psock - An instance of the internal socket structure. + * buf - Data to send + * len - Length of data to send + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -1 is returned, and errno is set appropriately. Returned error numbers + * must be consistent with definition of errors reported by send() or + * sendto(). + * + ****************************************************************************/ + +#ifdef CONFIG_NET_TCP +ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, + size_t len) +{ + FAR struct tcp_conn_s *conn; + FAR struct net_driver_s *dev; + int ret; + + DEBUGASSERT(psock != NULL && psock->s_crefs > 0); + DEBUGASSERT(psock->s_type == SOCK_STREAM); + + /* Make sure that this is a valid socket */ + + if (psock != NULL || psock->s_crefs <= 0) + { + nerr("ERROR: Invalid socket\n"); + return (ssize_t)-EBADF; + } + + /* Make sure that this is a connected TCP socket */ + + if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags)) + { + nerr("ERROR: Not connected\n"); + return (ssize_t)-ENOTCONN; + } + + /* Get the underlying TCP connection structure */ + + conn = (FAR struct tcp_conn_s *)psock->s_conn; + DEBUGASSERT(conn != NULL); + + /* Ignore if not IPv6 domain */ + + if (conn->domain != PF_INET6) + { + nwarn("WARNING: Not IPv6\n"); + return (ssize_t)-EPROTOTYPE; + } + + /* Route outgoing message to the correct device */ + +#ifdef CONFIG_NETDEV_MULTINIC + dev = netdev_findby_ipv6addr(conn->u.ipv6.laddr, conn->u.ipv6.raddr); + if (dev == NULL || dev->d_lltype != NET_LL_IEEE805154) + { + nwarn("WARNING: Not routable or not IEEE802.15.4 MAC\n"); + return (ssize_t)-ENETUNREACH; + } +#else + dev = netdev_findby_ipv6addr(conn->u.ipv6.raddr); + if (dev == NULL) + { + nwarn("WARNING: Not routable\n"); + return (ssize_t)-ENETUNREACH; + } +#endif + +#ifdef CONFIG_NET_ICMPv6_NEIGHBOR + /* Make sure that the IP address mapping is in the Neighbor Table */ + + ret = icmpv6_neighbor(conn->u.ipv6.raddr); + if (ret < 0) + { + nerr("ERROR: Not reachable\n"); + return (ssize_t)-ENETUNREACH; + } +#endif + + /* Set the socket state to sending */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); + + /* If routable, then call sixlowpan_send() to format and send the 6loWPAN + * packet. + */ + + ret = sixlowpan_send(dev); + if (ret < 0) + { + nerr("ERROR: sixlowpan_send() failed: %d\n", ret); + } + + return ret; +} +#endif + +/**************************************************************************** + * Function: psock_6lowpan_udp_send + * + * Description: + * psock_6lowpan_udp_send() call may be used with connectionlesss UDP + * sockets. + * + * Parameters: + * psock - An instance of the internal socket structure. + * buf - Data to send + * len - Length of data to send + * + * Returned Value: + * On success, returns the number of characters sent. On error, + * -1 is returned, and errno is set appropriately. Returned error numbers + * must be consistent with definition of errors reported by send() or + * sendto(). + * + ****************************************************************************/ + +#ifdef CONFIG_NET_UDP +ssize_t psock_6lowpan_udp_send(FAR struct socket *psock, FAR const void *buf, + size_t len) +{ + FAR struct udp_conn_s *conn; + FAR struct net_driver_s *dev; + int ret; + + DEBUGASSERT(psock != NULL && psock->s_crefs > 0); + DEBUGASSERT(psock->s_type == SOCK_DGRAM); + + /* Make sure that this is a valid socket */ + + if (psock != NULL || psock->s_crefs <= 0) + { + nerr("ERROR: Invalid socket\n"); + return (ssize_t)-EBADF; + } + + /* Was the UDP socket connected via connect()? */ + + if (psock->s_type != SOCK_DGRAM || !_SS_ISCONNECTED(psock->s_flags)) + { + /* No, then it is not legal to call send() with this socket. */ + + return -ENOTCONN; + } + + /* Get the underlying UDP "connection" structure */ + + conn = (FAR struct udp_conn_s *)psock->s_conn; + DEBUGASSERT(conn != NULL); + + /* Ignore if not IPv6 domain */ + + if (conn->domain != PF_INET6) + { + nwarn("WARNING: Not IPv6\n"); + return (ssize_t)-EPROTOTYPE; + } + + /* Route outgoing message to the correct device */ + +#ifdef CONFIG_NETDEV_MULTINIC + dev = netdev_findby_ipv6addr(conn->u.ipv6.laddr, conn->u.ipv6.raddr); + if (dev == NULL || dev->d_lltype != NET_LL_IEEE805154) + { + nwarn("WARNING: Not routable or not IEEE802.15.4 MAC\n"); + return (ssize_t)-ENETUNREACH; + } +#else + dev = netdev_findby_ipv6addr(conn->u.ipv6.raddr); + if (dev == NULL) + { + nwarn("WARNING: Not routable\n"); + return (ssize_t)-ENETUNREACH; + } +#endif + +#ifdef CONFIG_NET_ICMPv6_NEIGHBOR + /* Make sure that the IP address mapping is in the Neighbor Table */ + + ret = icmpv6_neighbor(conn->u.ipv6.raddr); + if (ret < 0) + { + nerr("ERROR: Not reachable\n"); + return (ssize_t)-ENETUNREACH; + } +#endif + + /* Set the socket state to sending */ + + psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); + + /* If routable, then call sixlowpan_send() to format and send the 6loWPAN + * packet. + */ + + ret = sixlowpan_send(dev); + if (ret < 0) + { + nerr("ERROR: sixlowpan_send() failed: %d\n", ret); + } + + return ret; +} +#endif + +#endif /* CONFIG_NET_6LOWPAN */ diff --git a/net/socket/send.c b/net/socket/send.c index e90b27b116a..20252fcdaeb 100644 --- a/net/socket/send.c +++ b/net/socket/send.c @@ -45,9 +45,10 @@ #include +#include "pkt/pkt.h" #include "tcp/tcp.h" #include "udp/udp.h" -#include "pkt/pkt.h" +#include "sixlowpan/sixlowpan.h" #include "local/local.h" #include "socket/socket.h" @@ -133,6 +134,8 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len, #if defined(CONFIG_NET_PKT) case SOCK_RAW: { + /* Raw packet send */ + ret = psock_pkt_send(psock, buf, len); } break; @@ -146,6 +149,8 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len, if (psock->s_domain == PF_LOCAL) #endif { + /* Local TCP packet send */ + ret = psock_local_send(psock, buf, len, flags); } #endif /* CONFIG_NET_LOCAL_STREAM */ @@ -155,7 +160,17 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len, else #endif { - ret = psock_tcp_send(psock, buf, len); +#ifdef CONFIG_NET_6LOWPAN + /* Try 6loWPAN TCP packet send */ + + ret = psock_6lowpan_tcp_send(psock, buf, len); + if (ret < 0) +#endif + { + /* Try TCP/IP packet send */ + + ret = psock_tcp_send(psock, buf, len); + } } #endif /* CONFIG_NET_TCP */ } @@ -170,6 +185,7 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len, if (psock->s_domain == PF_LOCAL) #endif { + /* Local UDP packet send */ #warning Missing logic ret = -ENOSYS; } @@ -180,7 +196,17 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len, else #endif { - ret = psock_udp_send(psock, buf, len); +#ifdef CONFIG_NET_6LOWPAN + /* Try 6loWPAN UDP packet send */ + + ret = psock_6lowpan_udp_send(psock, buf, len); + if (ret < 0) +#endif + { + /* UDP/IP packet send */ + + ret = psock_udp_send(psock, buf, len); + } } #endif /* CONFIG_NET_UDP */ } diff --git a/net/tcp/tcp_send.c b/net/tcp/tcp_send.c index edce06a196f..a68394b24c1 100644 --- a/net/tcp/tcp_send.c +++ b/net/tcp/tcp_send.c @@ -121,7 +121,7 @@ static inline FAR struct tcp_hdr_s *tcp_header(FAR struct net_driver_s *dev) * None * * Assumptions: - * Called from the interrupt level or with interrupts disabled. + * Called with the network locked. * ****************************************************************************/ @@ -189,7 +189,7 @@ static inline void tcp_ipv4_sendcomplete(FAR struct net_driver_s *dev, * None * * Assumptions: - * Called from the interrupt level or with interrupts disabled. + * Called with the network locked. * ****************************************************************************/ @@ -252,7 +252,7 @@ static inline void tcp_ipv6_sendcomplete(FAR struct net_driver_s *dev, * None * * Assumptions: - * Called from the interrupt level or with interrupts disabled. + * Called with the network locked. * ****************************************************************************/ @@ -300,7 +300,7 @@ static void tcp_sendcomplete(FAR struct net_driver_s *dev, * None * * Assumptions: - * Called from the interrupt level or with interrupts disabled. + * Called with the network locked. * ****************************************************************************/ @@ -383,7 +383,7 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev, * None * * Assumptions: - * Called from the interrupt level or with interrupts disabled. + * Called with the network locked. * ****************************************************************************/ @@ -411,7 +411,7 @@ void tcp_send(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn, * None * * Assumptions: - * Called from the interrupt level or with interrupts disabled. + * Called with the network locked. * ****************************************************************************/ @@ -528,7 +528,7 @@ void tcp_reset(FAR struct net_driver_s *dev) * None * * Assumptions: - * Called from the interrupt level or with interrupts disabled. + * Called with the network locked. * ****************************************************************************/ diff --git a/net/tcp/tcp_send_buffered.c b/net/tcp/tcp_send_buffered.c index e3c12aed7e6..76941f3a999 100644 --- a/net/tcp/tcp_send_buffered.c +++ b/net/tcp/tcp_send_buffered.c @@ -952,7 +952,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, int errcode; int ret = OK; - if (!psock || psock->s_crefs <= 0) + if (psock == NULL || psock->s_crefs <= 0) { nerr("ERROR: Invalid socket\n"); errcode = EBADF; diff --git a/net/tcp/tcp_send_unbuffered.c b/net/tcp/tcp_send_unbuffered.c index d6422437c8c..6c3688d85ad 100644 --- a/net/tcp/tcp_send_unbuffered.c +++ b/net/tcp/tcp_send_unbuffered.c @@ -722,7 +722,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, /* Verify that the sockfd corresponds to valid, allocated socket */ - if (!psock || psock->s_crefs <= 0) + if (psock == NULL || psock->s_crefs <= 0) { nerr("ERROR: Invalid socket\n"); errcode = EBADF;