summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/examples/Kconfig1
-rw-r--r--apps/examples/Make.defs4
-rw-r--r--apps/examples/Makefile17
-rw-r--r--apps/examples/README.txt5
-rw-r--r--apps/examples/netpkt/Kconfig14
-rw-r--r--apps/examples/netpkt/Makefile109
-rw-r--r--apps/examples/netpkt/netpkt_main.c258
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_eth.c9
-rw-r--r--nuttx/include/netpacket/packet.h61
-rw-r--r--nuttx/include/nuttx/net/uip/uip-pkt.h106
-rw-r--r--nuttx/include/nuttx/net/uip/uip.h3
-rw-r--r--nuttx/net/Kconfig19
-rw-r--r--nuttx/net/bind.c74
-rw-r--r--nuttx/net/net_send_unbuffered.c377
-rw-r--r--nuttx/net/recvfrom.c263
-rw-r--r--nuttx/net/socket.c118
-rw-r--r--nuttx/net/uip/Make.defs9
-rw-r--r--nuttx/net/uip/uip_initialize.c6
-rw-r--r--nuttx/net/uip/uip_internal.h23
-rw-r--r--nuttx/net/uip/uip_pktcallback.c95
-rw-r--r--nuttx/net/uip/uip_pktconn.c290
-rw-r--r--nuttx/net/uip/uip_pktinput.c140
-rw-r--r--nuttx/net/uip/uip_pktpoll.c129
-rw-r--r--nuttx/net/uip/uip_poll.c116
24 files changed, 2076 insertions, 170 deletions
diff --git a/apps/examples/Kconfig b/apps/examples/Kconfig
index 968ef8fd4..47b11b1e3 100644
--- a/apps/examples/Kconfig
+++ b/apps/examples/Kconfig
@@ -26,6 +26,7 @@ source "$APPSDIR/examples/mm/Kconfig"
source "$APPSDIR/examples/modbus/Kconfig"
source "$APPSDIR/examples/mount/Kconfig"
source "$APPSDIR/examples/mtdpart/Kconfig"
+source "$APPSDIR/examples/netpkt/Kconfig"
source "$APPSDIR/examples/nettest/Kconfig"
source "$APPSDIR/examples/nrf24l01_term/Kconfig"
source "$APPSDIR/examples/nsh/Kconfig"
diff --git a/apps/examples/Make.defs b/apps/examples/Make.defs
index e5dfbb355..219c8df71 100644
--- a/apps/examples/Make.defs
+++ b/apps/examples/Make.defs
@@ -130,6 +130,10 @@ ifeq ($(CONFIG_EXAMPLES_MTDPART),y)
CONFIGURED_APPS += examples/mtdpart
endif
+ifeq ($(CONFIG_EXAMPLES_NETPKT),y)
+CONFIGURED_APPS += examples/netpkt
+endif
+
ifeq ($(CONFIG_EXAMPLES_NETTEST),y)
CONFIGURED_APPS += examples/nettest
endif
diff --git a/apps/examples/Makefile b/apps/examples/Makefile
index 83153157b..547e3004a 100644
--- a/apps/examples/Makefile
+++ b/apps/examples/Makefile
@@ -1,7 +1,7 @@
############################################################################
# apps/examples/Makefile
#
-# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2011-2014 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -39,13 +39,12 @@
SUBDIRS = adc buttons can cc3000 cpuhog cxxtest dhcpd discover elf
SUBDIRS += flash_test ftpc ftpd hello helloxx hidkbd igmp i2schar json
-SUBDIRS += keypadtest lcdrw mm modbus mount mtdpart nettest nrf24l01_term
-SUBDIRS += nsh null nx nxconsole nxffs nxflat nxhello nximage nxlines
-SUBDIRS += nxtext ostest pashello pipe poll posix_spawn pwm qencoder random
-SUBDIRS += relays rgmp romfs sendmail serialblaster serloop serialrx slcd
-SUBDIRS += smart smart_test tcpecho telnetd thttpd tiff touchscreen udp uip
-SUBDIRS += usbserial usbterm watchdog wget wgetjson xmlrpc
-
+SUBDIRS += keypadtest lcdrw mm modbus mount mtdpart netpkt nettest
+SUBDIRS += nrf24l01_term nsh null nx nxconsole nxffs nxflat nxhello nximage
+SUBDIRS += nxlines nxtext ostest pashello pipe poll posix_spawn pwm qencoder
+SUBDIRS += random relays rgmp romfs sendmail serialblaster serloop serialrx
+SUBDIRS += slcd smart smart_test tcpecho telnetd thttpd tiff touchscreen udp
+SUBDIRS += uip usbserial usbterm watchdog wget wgetjson xmlrpc
# Sub-directories that might need context setup. Directories may need
# context setup for a variety of reasons, but the most common is because
@@ -56,7 +55,7 @@ CNTXTDIRS = pwm
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
CNTXTDIRS += adc can cc3000 cpuhog cxxtest dhcpd discover flash_test ftpd
CNTXTDIRS += hello helloxx i2schar json keypadtestmodbus lcdrw mtdpart
-CNTXTDIRS += nettest nx nxhello nximage nxlines nxtext nrf24l01_term
+CNTXTDIRS += netpkt nettest nx nxhello nximage nxlines nxtext nrf24l01_term
CNTXTDIRS += ostest random relays qencoder serialblasterslcd serialrx
CNTXTDIRS += smart_test tcpecho telnetd tiff touchscreen usbterm watchdog
CNTXTDIRS += wgetjson
diff --git a/apps/examples/README.txt b/apps/examples/README.txt
index 137802220..1352d4455 100644
--- a/apps/examples/README.txt
+++ b/apps/examples/README.txt
@@ -658,6 +658,11 @@ examples/mtdpart
* CONFIG_EXAMPLES_MTDPART_NEBLOCKS - This value gives the nubmer of erase
blocks in MTD RAM device.
+examples/netpkt
+^^^^^^^^^^^^^^^
+
+ A test of AF_PACKET, "raw" sockets. Contributed by Lazlo Sitzer.
+
examples/nettest
^^^^^^^^^^^^^^^^
diff --git a/apps/examples/netpkt/Kconfig b/apps/examples/netpkt/Kconfig
new file mode 100644
index 000000000..4fbcd9ac9
--- /dev/null
+++ b/apps/examples/netpkt/Kconfig
@@ -0,0 +1,14 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt
+#
+
+config EXAMPLES_NETPKT
+ bool "Network packet socket example"
+ default n
+ depends on NET_PKT
+ ---help---
+ Enable the network packet socket example
+
+if EXAMPLES_NETPKT
+endif
diff --git a/apps/examples/netpkt/Makefile b/apps/examples/netpkt/Makefile
new file mode 100644
index 000000000..503bd7e69
--- /dev/null
+++ b/apps/examples/netpkt/Makefile
@@ -0,0 +1,109 @@
+############################################################################
+# apps/examples/netpkt/Makefile
+#
+# Copyright (C) 2014 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.
+#
+############################################################################
+
+-include $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# Network packet socket example
+
+APPNAME = netpkt
+PRIORITY = SCHED_PRIORITY_DEFAULT
+STACKSIZE = 2048
+
+# MDIO tool
+
+ASRCS =
+CSRCS = netpkt_main.c
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+ BIN = ..\..\libapps$(LIBEXT)
+else
+ifeq ($(WINTOOL),y)
+ BIN = ..\\..\\libapps$(LIBEXT)
+else
+ BIN = ../../libapps$(LIBEXT)
+endif
+endif
+
+ROOTDEPPATH = --dep-path .
+
+# Common build
+
+VPATH =
+
+all: .built
+.PHONY: clean depend distclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+.built: $(OBJS)
+ $(call ARCHIVE, $(BIN), $(OBJS))
+ @touch .built
+
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
+ $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
+
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
+
+.depend: Makefile $(SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+depend: .depend
+
+clean:
+ $(call DELFILE, .built)
+ $(call CLEAN)
+
+distclean: clean
+ $(call DELFILE, Make.dep)
+ $(call DELFILE, .depend)
+
+-include Make.dep
diff --git a/apps/examples/netpkt/netpkt_main.c b/apps/examples/netpkt/netpkt_main.c
new file mode 100644
index 000000000..b833a4a14
--- /dev/null
+++ b/apps/examples/netpkt/netpkt_main.c
@@ -0,0 +1,258 @@
+/****************************************************************************
+ * net/recvfrom.c
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Lazlo <dlsitzer@gmail.comg>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <netpacket/packet.h>
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: psock_create
+ ****************************************************************************/
+
+static int psock_create(void)
+{
+ int sd;
+ struct sockaddr_ll addr;
+ int addrlen = sizeof(addr);
+
+ sd = socket(AF_PACKET, SOCK_RAW, 0);
+ if (sd < 0)
+ {
+ perror("ERROR: failed to create packet socket");
+ return -1;
+ }
+
+ /* Prepare sockaddr struct */
+
+ addr.sll_family = AF_PACKET;
+ addr.sll_ifindex = 0;
+ if (bind(sd, (const struct sockaddr *)&addr, addrlen) < 0)
+ {
+ perror("ERROR: binding socket failed");
+ close(sd);
+ return -1;
+ }
+
+ return sd;
+}
+
+/****************************************************************************
+ * Name: print_buf
+ ****************************************************************************/
+
+static void print_buf(const uint8_t *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ printf("%02X", buf[i]);
+
+ if ((i+1) % 16 == 0 || (i+1) == len)
+ {
+ printf("\n");
+ }
+ else if ((i+1) % 8 == 0)
+ {
+ printf(" ");
+ }
+ else
+ {
+ printf(" ");
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: netpkt_usage
+ ****************************************************************************/
+
+static void netpkt_usage(void)
+{
+ printf("usage: netpkt options\n");
+ printf("\n");
+ printf(" -a transmit and receive\n");
+ printf(" -r receive\n");
+ printf(" -t transmit\n");
+ printf(" -v verbose\n");
+ printf("\n");
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: netpkt_main
+ ****************************************************************************/
+
+int netpkt_main(int argc, char **argv)
+{
+ int sd;
+ int i;
+ int txc;
+ int rxc;
+ uint8_t *buf;
+ const int buflen = 128;
+ const char da[6] = {0xf0, 0xde, 0xf1, 0x02, 0x43, 0x01};
+ const char sa[6] = {0x00, 0xe0, 0xde, 0xad, 0xbe, 0xef};
+
+ int opt;
+ int verbose = 0;
+ int do_rx = 0;
+ int do_rxtimes = 3;
+ int do_tx = 0;
+ int do_txtimes = 3;
+
+ if (argc == 1)
+ {
+ netpkt_usage();
+ return -1;
+ }
+
+ /* Parse arguments */
+
+ while ((opt = getopt(argc, argv, "artv")) != -1)
+ {
+ switch(opt)
+ {
+ case 'a':
+ do_rx = 1;
+ do_tx = 1;
+ break;
+
+ case 'r':
+ do_rx = 1;
+ break;
+
+ case 't':
+ do_tx = 1;
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ default:
+ netpkt_usage();
+ return -1;
+ }
+ }
+
+ sd = psock_create();
+
+ if (do_tx)
+ {
+ if (verbose)
+ {
+ printf("Testing write() (%d times)\n", do_txtimes);
+ }
+
+ buf = malloc(buflen);
+ memset(buf, 0, buflen);
+ memcpy(buf, da, 6);
+ memcpy(buf+6, sa, 6);
+ for (i = 0; i < do_txtimes; i++)
+ {
+ if ((txc = write(sd, buf, buflen)) < 0)
+ {
+ perror("ERROR: write failed");
+ free(buf);
+ close(sd);
+ return -1;
+ }
+ else
+ {
+ if (verbose)
+ {
+ printf("transmited %d octets\n", txc);
+ print_buf(buf, txc);
+ }
+ }
+ }
+
+ free(buf);
+ }
+
+ if (do_rx)
+ {
+ if (verbose)
+ {
+ printf("Testing read() (%d times)\n", do_rxtimes);
+ }
+
+ buf = malloc(buflen);
+ memset(buf, 0, buflen);
+ for (i = 0; i < do_rxtimes; i++)
+ {
+ rxc = read(sd, buf, buflen);
+ if (rxc < 0)
+ {
+ perror("ERROR: read failed");
+ free(buf);
+ close(sd);
+ return -1;
+ }
+ else if (rxc == 0)
+ {
+ /* ignore silently */
+ }
+ else
+ {
+ if (verbose)
+ {
+ printf("received %d octets\n", rxc);
+ print_buf(buf, rxc);
+ }
+ }
+ }
+
+ free(buf);
+ }
+
+ close(sd);
+ return 0;
+}
diff --git a/nuttx/arch/arm/src/stm32/stm32_eth.c b/nuttx/arch/arm/src/stm32/stm32_eth.c
index 60187bcff..cded4edb3 100644
--- a/nuttx/arch/arm/src/stm32/stm32_eth.c
+++ b/nuttx/arch/arm/src/stm32/stm32_eth.c
@@ -56,6 +56,9 @@
#include <nuttx/net/uip/uip.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/uip/uip-arch.h>
+#if defined(CONFIG_NET_PKT)
+# include <nuttx/net/uip/uip-pkt.h>
+#endif
#include "up_internal.h"
@@ -1589,6 +1592,12 @@ static void stm32_receive(FAR struct stm32_ethmac_s *priv)
while (stm32_recvframe(priv) == OK)
{
+#ifdef CONFIG_NET_PKT
+ /* When packet sockets are enabled, feed the frame into the packet tap */
+
+ uip_pktinput(&priv->dev);
+#endif
+
/* Check if the packet is a valid size for the uIP buffer configuration
* (this should not happen)
*/
diff --git a/nuttx/include/netpacket/packet.h b/nuttx/include/netpacket/packet.h
new file mode 100644
index 000000000..be9076e65
--- /dev/null
+++ b/nuttx/include/netpacket/packet.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+ * include/netpacket/netpacket.h
+ * Definitions for use with AF_PACKET sockets
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Lazlo <dlsitzer@gmail.comg>
+ *
+ * Includes some definitions that a compatible with the LGPL GNU C Library
+ * header file of the same name.
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NETPACKET_PACKET_H
+#define __INCLUDE_NETPACKET_PACKET_H 1
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct sockaddr_ll
+{
+ uint16_t sll_family;
+ uint16_t sll_protocol;
+ sint16_t sll_ifindex;
+};
+
+#endif /* __INCLUDE_NETPACKET_PACKET_H */
diff --git a/nuttx/include/nuttx/net/uip/uip-pkt.h b/nuttx/include/nuttx/net/uip/uip-pkt.h
new file mode 100644
index 000000000..03502eb38
--- /dev/null
+++ b/nuttx/include/nuttx/net/uip/uip-pkt.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+ * include/netpacket/netpacket.h
+ * Definitions for use with AF_PACKET sockets
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Lazlo <dlsitzer@gmail.comg>
+ *
+ * Includes some definitions that a compatible with the LGPL GNU C Library
+ * header file of the same name.
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_NET_UIP_UIP_PKT_H
+#define __INCLUDE_NUTTX_NET_UIP_UIP_PKT_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <nuttx/net/uip/uipopt.h>
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* Representation of a uIP packet socket connection */
+
+struct uip_pkt_conn
+{
+ dq_entry_t node; /* Supports a double linked list */
+ uint8_t lmac[6]; /* The local Ethernet address in network byte order */
+ uint8_t ifindex;
+ uint16_t proto;
+ uint8_t crefs; /* Reference counts on this instance */
+
+ /* Defines the list of packet callbacks */
+
+ struct uip_callback_s *list;
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/* uIP application functions
+ *
+ * Functions used by an application running of top of uIP. This includes
+ * functions for opening and closing connections, sending and receiving
+ * data, etc.
+ *
+ * Find a free connection structure and allocate it for use. This is
+ * normally something done by the implementation of the socket() API
+ */
+
+struct uip_pkt_conn *uip_pktalloc(void);
+
+/* Allocate a new packet socket data callback */
+
+#define uip_pktcallbackalloc(conn) uip_callbackalloc(&conn->list)
+#define uip_pktcallbackfree(conn,cb) uip_callbackfree(cb, &conn->list)
+
+/* Free a connection structure that is no longer in use. This should
+ * be done by the implementation of close()
+ */
+
+void uip_pktfree(struct uip_pkt_conn *conn);
+
+void uip_pktpoll(struct uip_driver_s *dev, struct uip_pkt_conn *conn);
+
+int uip_pktinput(struct uip_driver_s *dev);
+
+#endif /* __INCLUDE_NUTTX_NET_UIP_UIP_PKT_H */
diff --git a/nuttx/include/nuttx/net/uip/uip.h b/nuttx/include/nuttx/net/uip/uip.h
index c9078fd9e..798b905ac 100644
--- a/nuttx/include/nuttx/net/uip/uip.h
+++ b/nuttx/include/nuttx/net/uip/uip.h
@@ -227,6 +227,9 @@ struct uip_callback_s
/* Protocol-specific support */
+#ifdef CONFIG_NET_PKT
+# include <nuttx/net/uip/uip-pkt.h>
+#endif
#ifdef CONFIG_NET_TCP
# include <nuttx/net/uip/uip-tcp.h>
#endif
diff --git a/nuttx/net/Kconfig b/nuttx/net/Kconfig
index be415289b..0a5944b7f 100644
--- a/nuttx/net/Kconfig
+++ b/nuttx/net/Kconfig
@@ -83,6 +83,25 @@ config NET_SOLINGER
endif # NET_SOCKOPTS
+config NET_PKT
+ bool "Socket packet socket support"
+ default n
+ ---help---
+ Enable or disbale support for packet sockets.
+ Packet sockets allow receiving and transmitting frames without
+ a transport protocol in between. Frames received are copied into
+ a packet socket tap before they enter uIP. Data written into a
+ packet socket will bypass uIP altogether and be placed in the
+ transmission buffer of the network interface driver.
+
+if NET_PKT
+
+config NET_PKT_CONNS
+ int "Max packet sockets"
+ default 1
+
+endif # NET_PKT
+
config NET_BUFSIZE
int "Network packet buffer size (MTU)"
default 1294 if !NET_SLIP && NET_IPv6
diff --git a/nuttx/net/bind.c b/nuttx/net/bind.c
index cbb0a1dea..6de8443f8 100644
--- a/nuttx/net/bind.c
+++ b/nuttx/net/bind.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/bind.c
*
- * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2012, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -43,11 +43,64 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
+#include <string.h>
+
+#ifdef CONFIG_NET_PKT
+# include <netpacket/packet.h>
+#endif
#include "net_internal.h"
/****************************************************************************
- * Global Functions
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: pkt_rawbind
+ *
+ * Description:
+ * Bind a raw socket to an network device.
+ *
+ * Parameters:
+ * conn AF_PACKET connection structure
+ * addr Peer address information
+ *
+ * Returned Value:
+ * 0 on success; -1 on error with errno set appropriately
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_PKT
+static int pkt_rawbind(FAR struct uip_pkt_conn *conn,
+ FAR const struct sockaddr_ll *addr)
+{
+ int ifindex;
+#if 0
+ char hwaddr[6] = {0x00, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1}; /* our MAC for debugging */
+#endif
+ char hwaddr[6] = {0x00, 0xe0, 0xde, 0xad, 0xbe, 0xef}; /* MAC from ifconfig */
+
+ /* Look at the addr and identify network interface */
+
+ ifindex = addr->sll_ifindex;
+
+#if 0
+ /* Get the MAC address of that interface */
+
+ memcpy(hwaddr, g_netdevices->d_mac, 6);
+#endif
+
+ /* Put ifindex and mac address into connection */
+
+ conn->ifindex = ifindex;
+ memcpy(conn->lmac, hwaddr, 6);
+
+ return OK;
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
+ * Public Functions
****************************************************************************/
/****************************************************************************
@@ -83,6 +136,9 @@
int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
socklen_t addrlen)
{
+#ifdef CONFIG_NET_PKT
+ FAR const struct sockaddr_ll *lladdr = (const struct sockaddr_ll *)addr;
+#endif
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
#ifdef CONFIG_NET_IPv6
FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr;
@@ -105,9 +161,13 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
/* Verify that a valid address has been provided */
#ifdef CONFIG_NET_IPv6
- if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6))
+ if ((addr->sa_family != AF_PACKET && addr->sa_family != AF_INET6) ||
+ (addr->sa_family == AF_PACKET && addrlen < sizeof(struct sockaddr_ll)) ||
+ (addr->sa_family == AF_INET6 && addrlen < sizeof(struct sockaddr_in6)))
#else
- if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in))
+ if ((addr->sa_family != AF_PACKET && addr->sa_family != AF_INET) ||
+ (addr->sa_family == AF_PACKET && addrlen < sizeof(struct sockaddr_ll)) ||
+ (addr->sa_family == AF_INET && addrlen < sizeof(struct sockaddr_in)))
#endif
{
err = EBADF;
@@ -118,6 +178,12 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
switch (psock->s_type)
{
+#ifdef CONFIG_NET_PKT
+ case SOCK_RAW:
+ ret = pkt_rawbind(psock->s_conn, lladdr);
+ break;
+#endif
+
#ifdef CONFIG_NET_TCP
case SOCK_STREAM:
ret = uip_tcpbind(psock->s_conn, inaddr);
diff --git a/nuttx/net/net_send_unbuffered.c b/nuttx/net/net_send_unbuffered.c
index db192d48f..bcf40b72e 100644
--- a/nuttx/net/net_send_unbuffered.c
+++ b/nuttx/net/net_send_unbuffered.c
@@ -55,6 +55,10 @@
#include <nuttx/net/arp.h>
#include <nuttx/net/uip/uip-arch.h>
+#ifdef CONFIG_NET_PKT
+# include <nuttx/net/uip/uip-pkt.h>
+#endif
+
#include "net_internal.h"
#include "uip/uip_internal.h"
@@ -115,7 +119,9 @@ struct send_s
*
****************************************************************************/
-#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
+#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_SOCKOPTS) && \
+ !defined(CONFIG_DISABLE_CLOCK)
+
static inline int send_timeout(FAR struct send_s *pstate)
{
FAR struct socket *psock = 0;
@@ -139,7 +145,191 @@ static inline int send_timeout(FAR struct send_s *pstate)
#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */
/****************************************************************************
- * Function: send_interrupt
+ * Function: pktsend_interrupt
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_PKT)
+static uint16_t pktsend_interrupt(FAR struct uip_driver_s *dev,
+ FAR void *pvconn,
+ FAR void *pvpriv, uint16_t flags)
+{
+ FAR struct send_s *pstate = (FAR struct send_s *)pvpriv;
+
+ nllvdbg("flags: %04x sent: %d\n", flags, pstate->snd_sent);
+
+ if (pstate)
+ {
+ /* Check if the outgoing packet is available. If my have been claimed
+ * by a send interrupt serving a different thread -OR- if the output
+ * buffer currently contains unprocessed incoming data. In these cases
+ * we will just have to wait for the next polling cycle.
+ */
+
+ if (dev->d_sndlen > 0 || (flags & UIP_NEWDATA) != 0)
+ {
+ /* Another thread has beat us sending data or the buffer is busy,
+ * Check for a timeout. If not timed out, wait for the next
+ * polling cycle and check again.
+ */
+
+ /* No timeout. Just wait for the next polling cycle */
+
+ return flags;
+ }
+
+ /* It looks like we are good to send the data */
+
+ else
+ {
+ /* Copy the user data into d_snddata and send it */
+
+#if 0
+ uip_send(dev, pstate->snd_buffer, pstate->snd_buflen);
+ pstate->snd_sent = pstate->snd_buflen;
+#else
+ /* NOTE: This is almost identical to calling uip_send() while
+ * the data from the sent operation buffer is copied into dev->d_buf
+ * instead of dev->d_snddata
+ */
+
+ if (pstate->snd_buflen > 0 && pstate->snd_buflen < CONFIG_NET_BUFSIZE)
+ {
+ memcpy(dev->d_buf, pstate->snd_buffer, pstate->snd_buflen);
+ dev->d_sndlen = pstate->snd_buflen;
+ }
+
+ pstate->snd_sent = pstate->snd_buflen;
+#endif
+ }
+
+ /* Don't allow any further call backs. */
+
+ pstate->snd_cb->flags = 0;
+ pstate->snd_cb->priv = NULL;
+ pstate->snd_cb->event = NULL;
+
+ /* Wake up the waiting thread */
+
+ sem_post(&pstate->snd_sem);
+ }
+
+ return flags;
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
+ * Function: pktsend
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_PKT)
+static ssize_t pktsend(FAR struct socket *psock, FAR const void *buf,
+ size_t len, int flags)
+{
+ struct send_s state;
+ uip_lock_t save;
+ int err;
+ int ret;
+
+ /* Verify that the sockfd corresponds to valid, allocated socket */
+
+ if (!psock || psock->s_crefs <= 0)
+ {
+ err = EBADF;
+ goto errout;
+ }
+
+ /* Set the socket state to sending */
+
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
+
+ /* Perform the send operation */
+
+ /* Initialize the state structure. This is done with interrupts
+ * disabled because we don't want anything to happen until we
+ * are ready.
+ */
+
+ save = uip_lock();
+ memset(&state, 0, sizeof(struct send_s));
+ (void)sem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
+ state.snd_sock = psock; /* Socket descriptor to use */
+ state.snd_buflen = len; /* Number of bytes to send */
+ state.snd_buffer = buf; /* Buffer to send from */
+
+ if (len > 0)
+ {
+ struct uip_pkt_conn *conn = (struct uip_pkt_conn*)psock->s_conn;
+
+ /* Allocate resource to receive a callback */
+
+ state.snd_cb = uip_pktcallbackalloc(conn);
+ if (state.snd_cb)
+ {
+ /* Set the initial time for calculating timeouts */
+
+#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
+ state.snd_time = clock_systimer();
+#endif
+
+ /* Set up the callback in the connection */
+
+ state.snd_cb->flags = UIP_POLL;
+ state.snd_cb->priv = (void*)&state;
+ state.snd_cb->event = pktsend_interrupt;
+
+ /* Wait for the send to complete or an error to occure: NOTES: (1)
+ * uip_lockedwait will also terminate if a signal is received, (2)
+ * interrupts may be disabled! They will be re-enabled while the
+ * task sleeps and automatically re-enabled when the task restarts.
+ */
+
+ ret = uip_lockedwait(&state.snd_sem);
+
+ /* Make sure that no further interrupts are processed */
+
+ uip_pktcallbackfree(conn, state.snd_cb);
+ }
+ }
+
+ sem_destroy(&state.snd_sem);
+ uip_unlock(save);
+
+ /* Set the socket state to idle */
+
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
+
+ /* Check for a errors, Errors are signalled by negative errno values
+ * for the send length
+ */
+
+ if (state.snd_sent < 0)
+ {
+ err = state.snd_sent;
+ goto errout;
+ }
+
+ /* If uip_lockedwait failed, then we were probably reawakened by a signal. In
+ * this case, uip_lockedwait will have set errno appropriately.
+ */
+
+ if (ret < 0)
+ {
+ err = -ret;
+ goto errout;
+ }
+
+ /* Return the number of bytes actually sent */
+
+ return state.snd_sent;
+
+errout:
+ set_errno(err);
+ return ERROR;
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
+ * Function: tcpsend_interrupt
*
* Description:
* This function is called from the interrupt level to perform the actual
@@ -158,8 +348,10 @@ static inline int send_timeout(FAR struct send_s *pstate)
*
****************************************************************************/
-static uint16_t send_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn,
- FAR void *pvpriv, uint16_t flags)
+#if defined(CONFIG_NET_TCP)
+static uint16_t tcpsend_interrupt(FAR struct uip_driver_s *dev,
+ FAR void *pvconn,
+ FAR void *pvpriv, uint16_t flags)
{
FAR struct uip_conn *conn = (FAR struct uip_conn*)pvconn;
FAR struct send_s *pstate = (FAR struct send_s *)pvpriv;
@@ -358,7 +550,7 @@ static uint16_t send_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn,
if ((pstate->snd_sent - pstate->snd_acked + sndlen) < conn->winsize)
{
/* Set the sequence number for this packet. NOTE: uIP updates
- * sndseq on recept of ACK *before* this function is called. In that
+ * sndseq on receipt of ACK *before* this function is called. In that
* case sndseq will point to the next unacknowledged byte (which might
* have already been sent). We will overwrite the value of sndseq
* here before the packet is sent.
@@ -436,77 +628,15 @@ end_wait:
sem_post(&pstate->snd_sem);
return flags;
}
+#endif
/****************************************************************************
- * Public Functions
+ * Function: tcpsend
****************************************************************************/
-/****************************************************************************
- * Function: psock_send
- *
- * Description:
- * The send() call may be used only when the socket is in a connected state
- * (so that the intended recipient is known). The only difference between
- * send() and write() is the presence of flags. With zero flags parameter,
- * send() is equivalent to write(). Also, send(sockfd,buf,len,flags) is
- * equivalent to sendto(sockfd,buf,len,flags,NULL,0).
- *
- * Parameters:
- * psock An instance of the internal socket structure.
- * buf Data to send
- * len Length of data to send
- * flags Send flags
- *
- * Returned Value:
- * On success, returns the number of characters sent. On error,
- * -1 is returned, and errno is set appropriately:
- *
- * EAGAIN or EWOULDBLOCK
- * The socket is marked non-blocking and the requested operation
- * would block.
- * EBADF
- * An invalid descriptor was specified.
- * ECONNRESET
- * Connection reset by peer.
- * EDESTADDRREQ
- * The socket is not connection-mode, and no peer address is set.
- * EFAULT
- * An invalid user space address was specified for a parameter.
- * EINTR
- * A signal occurred before any data was transmitted.
- * EINVAL
- * Invalid argument passed.
- * EISCONN
- * The connection-mode socket was connected already but a recipient
- * was specified. (Now either this error is returned, or the recipient
- * specification is ignored.)
- * EMSGSIZE
- * The socket type requires that message be sent atomically, and the
- * size of the message to be sent made this impossible.
- * ENOBUFS
- * The output queue for a network interface was full. This generally
- * indicates that the interface has stopped sending, but may be
- * caused by transient congestion.
- * ENOMEM
- * No memory available.
- * ENOTCONN
- * The socket is not connected, and no target has been given.
- * ENOTSOCK
- * The argument s is not a socket.
- * EOPNOTSUPP
- * Some bit in the flags argument is inappropriate for the socket
- * type.
- * EPIPE
- * The local end has been shut down on a connection oriented socket.
- * In this case the process will also receive a SIGPIPE unless
- * MSG_NOSIGNAL is set.
- *
- * Assumptions:
- *
- ****************************************************************************/
-
-ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
- int flags)
+#if defined(CONFIG_NET_TCP)
+ssize_t tcpsend(FAR struct socket *psock, FAR const void *buf, size_t len,
+ int flags)
{
struct send_s state;
uip_lock_t save;
@@ -575,7 +705,7 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
state.snd_cb->flags = UIP_ACKDATA|UIP_REXMIT|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
state.snd_cb->priv = (void*)&state;
- state.snd_cb->event = send_interrupt;
+ state.snd_cb->event = tcpsend_interrupt;
/* Notify the device driver of the availability of TX data */
@@ -630,5 +760,106 @@ errout:
set_errno(err);
return ERROR;
}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: psock_send
+ *
+ * Description:
+ * The send() call may be used only when the socket is in a connected state
+ * (so that the intended recipient is known). The only difference between
+ * send() and write() is the presence of flags. With zero flags parameter,
+ * send() is equivalent to write(). Also, send(sockfd,buf,len,flags) is
+ * equivalent to sendto(sockfd,buf,len,flags,NULL,0).
+ *
+ * Parameters:
+ * psock An instance of the internal socket structure.
+ * buf Data to send
+ * len Length of data to send
+ * flags Send flags
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error,
+ * -1 is returned, and errno is set appropriately:
+ *
+ * EAGAIN or EWOULDBLOCK
+ * The socket is marked non-blocking and the requested operation
+ * would block.
+ * EBADF
+ * An invalid descriptor was specified.
+ * ECONNRESET
+ * Connection reset by peer.
+ * EDESTADDRREQ
+ * The socket is not connection-mode, and no peer address is set.
+ * EFAULT
+ * An invalid user space address was specified for a parameter.
+ * EINTR
+ * A signal occurred before any data was transmitted.
+ * EINVAL
+ * Invalid argument passed.
+ * EISCONN
+ * The connection-mode socket was connected already but a recipient
+ * was specified. (Now either this error is returned, or the recipient
+ * specification is ignored.)
+ * EMSGSIZE
+ * The socket type requires that message be sent atomically, and the
+ * size of the message to be sent made this impossible.
+ * ENOBUFS
+ * The output queue for a network interface was full. This generally
+ * indicates that the interface has stopped sending, but may be
+ * caused by transient congestion.
+ * ENOMEM
+ * No memory available.
+ * ENOTCONN
+ * The socket is not connected, and no target has been given.
+ * ENOTSOCK
+ * The argument s is not a socket.
+ * EOPNOTSUPP
+ * Some bit in the flags argument is inappropriate for the socket
+ * type.
+ * EPIPE
+ * The local end has been shut down on a connection oriented socket.
+ * In this case the process will also receive a SIGPIPE unless
+ * MSG_NOSIGNAL is set.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
+ int flags)
+{
+ int ret;
+
+ switch (psock->s_type)
+ {
+#if defined(CONFIG_NET_PKT)
+ case SOCK_RAW:
+ {
+ ret = pktsend(psock, buf, len, flags);
+ break;
+ }
+#endif
+
+#if defined(CONFIG_NET_TCP)
+ case SOCK_STREAM:
+ {
+ ret = tcpsend(psock, buf, len, flags);
+ break;
+ }
+#endif
+
+ default:
+ {
+ ret = ERROR;
+ }
+ }
+
+ return ret;
+}
#endif /* CONFIG_NET && CONFIG_NET_TCP && !CONFIG_NET_TCP_WRITE_BUFFERS */
diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c
index cba01c64e..aaf6b9236 100644
--- a/nuttx/net/recvfrom.c
+++ b/nuttx/net/recvfrom.c
@@ -48,6 +48,10 @@
#include <errno.h>
#include <debug.h>
+#ifdef CONFIG_NET_PKT
+# include <netpacket/packet.h>
+#endif
+
#include <arch/irq.h>
#include <nuttx/clock.h>
#include <nuttx/net/uip/uip-arch.h>
@@ -142,6 +146,52 @@ static size_t recvfrom_newdata(FAR struct uip_driver_s *dev,
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
/****************************************************************************
+ * Function: recvfrom_newpktdata
+ *
+ * Description:
+ * Copy the read data from the packet
+ *
+ * Parameters:
+ * dev The structure of the network driver that caused the interrupt
+ * pstate recvfrom state structure
+ *
+ * Returned Value:
+ * None.
+ *
+ * Assumptions:
+ * Running at the interrupt level
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_PKT
+static void recvfrom_newpktdata(FAR struct uip_driver_s *dev,
+ FAR struct recvfrom_s *pstate)
+{
+ size_t recvlen;
+
+ if (dev->d_len > pstate->rf_buflen)
+ {
+ recvlen = pstate->rf_buflen;
+ }
+ else
+ {
+ recvlen = dev->d_len;
+ }
+
+ /* Copy the new packet data into the user buffer */
+
+ memcpy(pstate->rf_buffer, dev->d_buf, recvlen);
+ nllvdbg("Received %d bytes (of %d)\n", (int)recvlen, (int)dev->d_len);
+
+ /* Update the accumulated size of the data read */
+
+ pstate->rf_recvlen += recvlen;
+ pstate->rf_buffer += recvlen;
+ pstate->rf_buffer -= recvlen;
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
* Function: recvfrom_newtcpdata
*
* Description:
@@ -252,7 +302,7 @@ static inline void recvfrom_newudpdata(FAR struct uip_driver_s *dev,
* Copy the read data from the packet
*
* Parameters:
- * dev The sructure of the network driver that caused the interrupt
+ * dev The structure of the network driver that caused the interrupt
* pstate recvfrom state structure
*
* Returned Value:
@@ -407,6 +457,89 @@ static int recvfrom_timeout(struct recvfrom_s *pstate)
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
/****************************************************************************
+ * Function: recvfrom_pktsender
+ *
+ * Description:
+ *
+ * Parameters:
+ *
+ * Returned Values:
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_PKT
+static inline void recvfrom_pktsender(FAR struct uip_driver_s *dev,
+ FAR struct recvfrom_s *pstate)
+{
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
+ * Function: recvfrom_pktinterrupt
+ *
+ * Description:
+ *
+ * Parameters:
+ *
+ * Returned Values:
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_PKT
+static uint16_t recvfrom_pktinterrupt(FAR struct uip_driver_s *dev,
+ FAR void *conn, FAR void *pvpriv,
+ uint16_t flags)
+{
+ struct recvfrom_s *pstate = (struct recvfrom_s *)pvpriv;
+
+ nllvdbg("flags: %04x\n", flags);
+
+ /* 'priv' might be null in some race conditions (?) */
+
+ if (pstate)
+ {
+ /* If a new packet is available, then complete the read action. */
+
+ if ((flags & UIP_NEWDATA) != 0)
+ {
+ /* Copy the packet */
+ recvfrom_newpktdata(dev, pstate);
+
+ /* We are finished. */
+
+ nllvdbg("PKT done\n");
+
+ /* Don't allow any further call backs. */
+
+ pstate->rf_cb->flags = 0;
+ pstate->rf_cb->priv = NULL;
+ pstate->rf_cb->event = NULL;
+#if 0
+ /* Save the sender's address in the caller's 'from' location */
+
+ recvfrom_pktsender(dev, pstate);
+#endif
+ /* indicate that the data has been consumed */
+
+ flags &= ~UIP_NEWDATA;
+
+ /* Wake up the waiting thread, returning the number of bytes
+ * actually read.
+ */
+
+ sem_post(&pstate->rf_sem);
+ }
+ }
+
+ return flags;
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
* Function: recvfrom_tcpsender
*
* Description:
@@ -647,6 +780,7 @@ static uint16_t recvfrom_tcpinterrupt(FAR struct uip_driver_s *dev,
}
#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */
}
+
return flags;
}
#endif /* CONFIG_NET_TCP */
@@ -700,7 +834,7 @@ static inline void recvfrom_udpsender(struct uip_driver_s *dev, struct recvfrom_
* UDP receive operation via by the uIP layer.
*
* Parameters:
- * dev The sructure of the network driver that caused the interrupt
+ * dev The structure of the network driver that caused the interrupt
* conn The connection structure associated with the socket
* flags Set of events describing why the callback was invoked
*
@@ -746,11 +880,11 @@ static uint16_t recvfrom_udpinterrupt(struct uip_driver_s *dev, void *pvconn,
recvfrom_udpsender(dev, pstate);
- /* Indicate that the data has been consumed */
+ /* Indicate that the data has been consumed */
flags &= ~UIP_NEWDATA;
- /* Wake up the waiting thread, returning the number of bytes
+ /* Wake up the waiting thread, returning the number of bytes
* actually read.
*/
@@ -786,6 +920,7 @@ static uint16_t recvfrom_udpinterrupt(struct uip_driver_s *dev, void *pvconn,
}
#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */
}
+
return flags;
}
#endif /* CONFIG_NET_UDP */
@@ -891,6 +1026,89 @@ static ssize_t recvfrom_result(int result, struct recvfrom_s *pstate)
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
/****************************************************************************
+ * Function: pkt_recvfrom
+ *
+ * Description:
+ * Perform the recvfrom operation for packet socket
+ *
+ * Parameters:
+ *
+ * Returned Value:
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_PKT
+static ssize_t pkt_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
+ FAR struct sockaddr_ll *from)
+{
+ struct uip_pkt_conn *conn = (struct uip_pkt_conn *)psock->s_conn;
+ struct recvfrom_s state;
+ uip_lock_t save;
+ int ret;
+
+ /* Perform the packet recvfrom() operation */
+
+ /* Initialize the state structure. This is done with interrupts
+ * disabled because we don't want anything to happen until we
+ * are ready.
+ */
+
+ save = uip_lock();
+ recvfrom_init(psock, buf, len, (struct sockaddr_in *)from, &state);
+
+ /* TODO recvfrom_init() expects from to be of type sockaddr_in, but
+ * in our case is sockaddr_ll
+ */
+
+#if 0
+ ret = uip_pktconnect(conn, NULL);
+ if (ret < 0)
+ {
+ goto errout_with_state;
+ }
+#endif
+
+ /* Set up the callback in the connection */
+
+ state.rf_cb = uip_pktcallbackalloc(conn);
+ if (state.rf_cb)
+ {
+ state.rf_cb->flags = UIP_NEWDATA|UIP_POLL;
+ state.rf_cb->priv = (void*)&state;
+ state.rf_cb->event = recvfrom_pktinterrupt;
+
+ /* Notify the device driver of the receive call */
+
+ /* netdev_rxnotify(conn->ripaddr); */
+
+ /* Wait for either the receive to complete or for an error/timeout to occur.
+ * NOTES: (1) uip_lockedwait will also terminate if a signal is received, (2)
+ * interrupts are disabled! They will be re-enabled while the task sleeps
+ * and automatically re-enabled when the task restarts.
+ */
+
+ ret = uip_lockedwait(&state.rf_sem);
+
+ /* Make sure that no further interrupts are processed */
+
+ uip_pktcallbackfree(conn, state.rf_cb);
+ ret = recvfrom_result(ret, &state);
+ }
+ else
+ {
+ ret = -EBUSY;
+ }
+
+errout_with_state:
+ uip_unlock(save);
+ recvfrom_uninit(&state);
+ return ret;
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
* Function: udp_recvfrom
*
* Description:
@@ -900,7 +1118,7 @@ static ssize_t recvfrom_result(int result, struct recvfrom_s *pstate)
* psock Pointer to the socket structure for the SOCK_DRAM socket
* buf Buffer to receive data
* len Length of buffer
- * infrom INET ddress of source (may be NULL)
+ * infrom INET address of source (may be NULL)
*
* Returned Value:
* On success, returns the number of characters sent. On error,
@@ -992,7 +1210,7 @@ errout_with_state:
* psock Pointer to the socket structure for the SOCK_DRAM socket
* buf Buffer to receive data
* len Length of buffer
- * infrom INET ddress of source (may be NULL)
+ * infrom INET address of source (may be NULL)
*
* Returned Value:
* On success, returns the number of characters sent. On error,
@@ -1113,7 +1331,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
* 1) Make sure thet there is buffer space to receive additional data
* (state.rf_buflen > 0). This could be zero, for example, if read-ahead
* buffering was enabled and we filled the user buffer with data from
- * the read-ahead buffers. Aand
+ * the read-ahead buffers. And
* 2) if read-ahead buffering is enabled (CONFIG_NET_TCP_READAHEAD)
* and delay logic is disabled (CONFIG_NET_TCP_RECVDELAY == 0), then we
* not want to wait if we already obtained some data from the read-ahead
@@ -1190,7 +1408,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
* Returned Value:
* On success, returns the number of characters sent. If no data is
* available to be received and the peer has performed an orderly shutdown,
- * recv() will return 0. Othwerwise, on errors, -1 is returned, and errno
+ * recv() will return 0. Otherwise, on errors, -1 is returned, and errno
* is set appropriately:
*
* EAGAIN
@@ -1225,6 +1443,9 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
int flags,FAR struct sockaddr *from,
FAR socklen_t *fromlen)
{
+#if defined(CONFIG_NET_PKT)
+ FAR struct sockaddr_ll *llfrom = (struct sockaddr_ll *)from;
+#endif
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
#ifdef CONFIG_NET_IPv6
FAR struct sockaddr_in6 *infrom = (struct sockaddr_in6 *)from;
@@ -1275,24 +1496,34 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV);
- /* Perform the TCP/IP or UDP recv() operation */
+ /* Read from the network interface driver buffer */
+ /* Or perform the TCP/IP or UDP recv() operation */
-#if defined(CONFIG_NET_UDP) && defined(CONFIG_NET_TCP)
+#if defined(CONFIG_NET_PKT)
+ if (psock->s_type == SOCK_RAW)
+ {
+ ret = pkt_recvfrom(psock, buf, len, llfrom);
+ }
+ else
+#endif
+#if defined(CONFIG_NET_TCP)
if (psock->s_type == SOCK_STREAM)
{
ret = tcp_recvfrom(psock, buf, len, infrom);
}
else
+#endif
+#if defined(CONFIG_NET_UDP)
+ if (psock->s_type == SOCK_DGRAM)
{
ret = udp_recvfrom(psock, buf, len, infrom);
}
-#elif defined(CONFIG_NET_TCP)
- ret = tcp_recvfrom(psock, buf, len, infrom);
-#elif defined(CONFIG_NET_UDP)
- ret = udp_recvfrom(psock, buf, len, infrom);
-#else
- ret = -ENOSYS;
+ else
#endif
+ {
+ ndbg("ERROR: Unsupported socket type: %d\n", psock->s_type
+ ret = -ENOSYS;
+ }
/* Set the socket state to idle */
diff --git a/nuttx/net/socket.c b/nuttx/net/socket.c
index 7b8db0c05..532e70ad8 100644
--- a/nuttx/net/socket.c
+++ b/nuttx/net/socket.c
@@ -91,33 +91,54 @@
int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
{
- int err = ENFILE;
+ int err;
- /* Only PF_INET or PF_INET6 domains supported */
+ /* Only PF_INET, PF_INET6 or PF_PACKET domains supported */
-#ifdef CONFIG_NET_IPv6
- if ( domain != PF_INET6)
+ if (
+#if defined(CONFIG_NET_IPv6)
+ domain != PF_INET6
#else
- if ( domain != PF_INET)
+ domain != PF_INET
#endif
+#if defined(CONFIG_NET_PKT)
+ && domain != PF_PACKET
+#endif
+ )
{
err = EAFNOSUPPORT;
goto errout;
}
- /* Only SOCK_STREAM and possible SOCK_DRAM are supported */
-
-#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_UDP)
- if ((type == SOCK_STREAM && protocol != 0 && protocol != IPPROTO_TCP) ||
- (type == SOCK_DGRAM && protocol != 0 && protocol != IPPROTO_UDP) ||
- (type != SOCK_STREAM && type != SOCK_DGRAM))
-#elif defined(CONFIG_NET_TCP)
- if ((type == SOCK_STREAM && protocol != 0 && protocol != IPPROTO_TCP) ||
- (type != SOCK_STREAM))
-#elif defined(CONFIG_NET_UDP)
- if ((type == SOCK_DGRAM && protocol != 0 && protocol != IPPROTO_UDP) ||
- (type != SOCK_DGRAM))
+ /* Only SOCK_STREAM, SOCK_DGRAM and possible SOCK_RAW are supported */
+
+ if (
+#if defined(CONFIG_NET_TCP)
+ (type == SOCK_STREAM && protocol != 0 && protocol != IPPROTO_TCP) ||
+#endif
+#if defined(CONFIG_NET_UDP)
+ (type == SOCK_DGRAM && protocol != 0 && protocol != IPPROTO_UDP) ||
+#endif
+ (
+#if defined(CONFIG_NET_TCP)
+#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_PKT)
+ type != SOCK_STREAM &&
+#else
+ type != SOCK_STREAM
+#endif
+#endif
+#if defined(CONFIG_NET_UDP)
+#if defined(CONFIG_NET_PKT)
+ type != SOCK_DGRAM &&
+#else
+ type != SOCK_DGRAM
+#endif
+#endif
+#if defined(CONFIG_NET_PKT)
+ type != SOCK_RAW
#endif
+ )
+ )
{
err = EPROTONOSUPPORT;
goto errout;
@@ -140,6 +161,20 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
err = ENOMEM; /* Assume failure to allocate connection instance */
switch (type)
{
+#ifdef CONFIG_NET_PKT
+ case SOCK_RAW:
+ {
+ struct uip_pkt_conn *conn = uip_pktalloc();
+ if (conn)
+ {
+ DEBUGASSERT(conn->crefs == 0);
+ psock->s_conn = conn;
+ conn->crefs = 1;
+ }
+ }
+ break;
+#endif
+
#ifdef CONFIG_NET_TCP
case SOCK_STREAM:
{
@@ -148,17 +183,21 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
*/
struct uip_conn *conn = uip_tcpalloc();
- if (conn)
+ if (!conn)
{
- /* Set the reference count on the connection structure. This
- * reference count will be increment only if the socket is
- * dup'ed
- */
+ /* Failed to reserve a connection structure */
- DEBUGASSERT(conn->crefs == 0);
- psock->s_conn = conn;
- conn->crefs = 1;
+ goto errout; /* With err == ENFILE or ENOMEM */
}
+
+ /* Set the reference count on the connection structure. This
+ * reference count will be increment only if the socket is
+ * dup'ed
+ */
+
+ DEBUGASSERT(conn->crefs == 0);
+ psock->s_conn = conn;
+ conn->crefs = 1;
}
break;
#endif
@@ -171,17 +210,21 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
*/
struct uip_udp_conn *conn = uip_udpalloc();
- if (conn)
+ if (!conn)
{
- /* Set the reference count on the connection structure. This
- * reference count will be increment only if the socket is
- * dup'ed
- */
+ /* Failed to reserve a connection structure */
- DEBUGASSERT(conn->crefs == 0);
- psock->s_conn = conn;
- conn->crefs = 1;
+ goto errout; /* With err == ENFILE or ENOMEM */
}
+
+ /* Set the reference count on the connection structure. This
+ * reference count will be increment only if the socket is
+ * dup'ed
+ */
+
+ DEBUGASSERT(conn->crefs == 0);
+ psock->s_conn = conn;
+ conn->crefs = 1;
}
break;
#endif
@@ -190,15 +233,6 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
break;
}
- /* Did we successfully allocate some kind of connection structure? */
-
- if (!psock->s_conn)
- {
- /* Failed to reserve a connection structure */
-
- goto errout; /* With err == ENFILE or ENOMEM */
- }
-
return OK;
errout:
diff --git a/nuttx/net/uip/Make.defs b/nuttx/net/uip/Make.defs
index df31f7eae..7cd15b569 100644
--- a/nuttx/net/uip/Make.defs
+++ b/nuttx/net/uip/Make.defs
@@ -46,6 +46,15 @@ ifeq ($(CONFIG_NET_NOINTS),y)
NET_CSRCS += uip_lock.c
endif
+# Packet socket support
+
+ifeq ($(CONFIG_NET_PKT),y)
+NET_CSRCS += uip_pktconn.c
+NET_CSRCS += uip_pktinput.c
+NET_CSRCS += uip_pktcallback.c
+NET_CSRCS += uip_pktpoll.c
+endif
+
# IPv6-specific logic
ifeq ($(CONFIG_NET_IPv6),y)
diff --git a/nuttx/net/uip/uip_initialize.c b/nuttx/net/uip/uip_initialize.c
index 6fc4d706b..eac765407 100644
--- a/nuttx/net/uip/uip_initialize.c
+++ b/nuttx/net/uip/uip_initialize.c
@@ -123,6 +123,12 @@ void uip_initialize(void)
uip_callbackinit();
+ /* Initialize packet socket suport */
+
+#ifdef CONFIG_NET_PKT
+ uip_pktinit();
+#endif
+
/* Initialize the listening port structures */
#ifdef CONFIG_NET_TCP
diff --git a/nuttx/net/uip/uip_internal.h b/nuttx/net/uip/uip_internal.h
index 4905c94a3..9dd8f0b56 100644
--- a/nuttx/net/uip/uip_internal.h
+++ b/nuttx/net/uip/uip_internal.h
@@ -51,6 +51,7 @@
#include <errno.h>
#include <arch/irq.h>
#include <nuttx/net/uip/uip.h>
+#include <nuttx/net/arp.h>
/****************************************************************************
* Pre-processor Definitions
@@ -102,6 +103,28 @@ void uip_callbackfree(FAR struct uip_callback_s *cb, struct uip_callback_s **lis
uint16_t uip_callbackexecute(FAR struct uip_driver_s *dev, void *pvconn,
uint16_t flags, FAR struct uip_callback_s *list);
+#ifdef CONFIG_NET_PKT
+/* Defined in uip_pktconn.c *************************************************/
+
+void uip_pktinit(void);
+struct uip_pkt_conn *uip_pktalloc(void);
+void uip_pktfree(struct uip_pkt_conn *conn);
+struct uip_pkt_conn *uip_pktactive(struct uip_eth_hdr *buf);
+struct uip_pkt_conn *uip_nextpktconn(struct uip_pkt_conn *conn);
+
+/* Defined in uip_pktcallback.c *********************************************/
+
+uint16_t uip_pktcallback(struct uip_driver_s *dev, struct uip_pkt_conn *conn,
+ uint16_t flags);
+
+/* Defined in uip_pktinput.c ************************************************/
+
+/* Defined in uip_pktpoll.c *************************************************/
+
+void uip_pktpoll(struct uip_driver_s *dev, struct uip_pkt_conn *conn);
+
+#endif /* CONFIG_NET_PKT */
+
#ifdef CONFIG_NET_TCP
/* Defined in uip_tcpconn.c *************************************************/
diff --git a/nuttx/net/uip/uip_pktcallback.c b/nuttx/net/uip/uip_pktcallback.c
new file mode 100644
index 000000000..34e111768
--- /dev/null
+++ b/nuttx/net/uip/uip_pktcallback.c
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * net/uip/uip_pktcallback.c
+ *
+ * Copyright (C) 2014 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>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_PKT)
+
+#include <stdint.h>
+#include <debug.h>
+
+#include <nuttx/net/uip/uipopt.h>
+#include <nuttx/net/uip/uip.h>
+#include <nuttx/net/uip/uip-arch.h>
+
+#include "uip_internal.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: uip_pktcallback
+ *
+ * Description:
+ * Inform the application holding the packet socket of a change in state.
+ *
+ * Returned Value:
+ * OK if packet has been processed, otherwise ERROR.
+ *
+ * Assumptions:
+ * This function is called at the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+uint16_t uip_pktcallback(FAR struct uip_driver_s *dev,
+ FAR struct uip_pkt_conn *conn, uint16_t flags)
+{
+ nllvdbg("flags: %04x\n", flags);
+
+ /* Some sanity checking */
+
+ if (conn)
+ {
+ /* Perform the callback */
+
+ flags = uip_callbackexecute(dev, conn, flags, conn->list);
+ }
+
+ return flags;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_PKT */
diff --git a/nuttx/net/uip/uip_pktconn.c b/nuttx/net/uip/uip_pktconn.c
new file mode 100644
index 000000000..2bca680a1
--- /dev/null
+++ b/nuttx/net/uip/uip_pktconn.c
@@ -0,0 +1,290 @@
+/****************************************************************************
+ * net/uip/uip_pktconn.c
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Large parts of this file were leveraged from uIP logic:
+ *
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_PKT)
+
+#include <semaphore.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include <nuttx/net/uip/uipopt.h>
+#include <nuttx/net/uip/uip.h>
+#include <nuttx/net/uip/uip-arch.h>
+#include <nuttx/net/arp.h>
+
+#include "uip_internal.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* The array containing all packet socket connections */
+
+static struct uip_pkt_conn g_pkt_connections[CONFIG_NET_PKT_CONNS];
+
+/* A list of all free packet socket connections */
+
+static dq_queue_t g_free_pkt_connections;
+static sem_t g_free_sem;
+
+/* A list of all allocated packet scoket connections */
+
+static dq_queue_t g_active_pkt_connections;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: _uip_semtake() and _uip_semgive()
+ *
+ * Description:
+ * Take/give semaphore
+ *
+ ****************************************************************************/
+
+static inline void _uip_semtake(sem_t *sem)
+{
+ /* Take the semaphore (perhaps waiting) */
+
+ while (uip_lockedwait(sem) != 0)
+ {
+ /* The only case that an error should occur here is if
+ * the wait was awakened by a signal.
+ */
+
+ ASSERT(*get_errno_ptr() == EINTR);
+ }
+}
+
+#define _uip_semgive(sem) sem_post(sem)
+
+/****************************************************************************
+ * Name: uip_find_conn()
+ *
+ * Description:
+ * Find the packet socket connection that uses this interface index
+ * number. Called only from user user level code, but with interrupts
+ * disabled.
+ *
+ ****************************************************************************/
+
+static struct uip_pkt_conn *uip_find_conn(uint8_t ifindex)
+{
+ int i;
+
+ /* Now search each connection structure. */
+
+ for (i = 0; i < CONFIG_NET_PKT_CONNS; i++)
+ {
+ if (g_pkt_connections[ i ].ifindex == ifindex)
+ {
+ return &g_pkt_connections[ i ];
+ }
+ }
+
+ return NULL;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: uip_pktinit()
+ *
+ * Description:
+ * Initialize the packet socket connection structures. Called once and
+ * only from the UIP layer.
+ *
+ ****************************************************************************/
+
+void uip_pktinit(void)
+{
+ int i;
+
+ /* Initialize the queues */
+
+ dq_init(&g_free_pkt_connections);
+ dq_init(&g_active_pkt_connections);
+ sem_init(&g_free_sem, 0, 1);
+
+ for (i = 0; i < CONFIG_NET_PKT_CONNS; i++)
+ {
+ /* Mark the connection closed and move it to the free list */
+ g_pkt_connections[i].ifindex = 0;
+ dq_addlast(&g_pkt_connections[i].node, &g_free_pkt_connections);
+ }
+}
+
+/****************************************************************************
+ * Name: uip_pktpalloc()
+ *
+ * Description:
+ * Alloc a new, uninitialized packet socket connection structure.
+ *
+ ****************************************************************************/
+
+struct uip_pkt_conn *uip_pktalloc(void)
+{
+ struct uip_pkt_conn *conn;
+
+ /* The free list is only accessed from user, non-interrupt level and
+ * is protected by a semaphore (that behaves like a mutex).
+ */
+
+ _uip_semtake(&g_free_sem);
+ conn = (struct uip_pkt_conn *)dq_remfirst(&g_free_pkt_connections);
+ if (conn)
+ {
+ /* Make sure that the connection is marked as uninitialized */
+
+ conn->ifindex = 0;
+
+ /* Enqueue the connection into the active list */
+
+ dq_addlast(&conn->node, &g_active_pkt_connections);
+ }
+
+ _uip_semgive(&g_free_sem);
+ return conn;
+}
+
+/****************************************************************************
+ * Name: uip_pktfree()
+ *
+ * Description:
+ * Free a packet socket connection structure that is no longer in use.
+ * This should be done by the implementation of close().
+ *
+ ****************************************************************************/
+
+void uip_pktfree(struct uip_pkt_conn *conn)
+{
+ /* The free list is only accessed from user, non-interrupt level and
+ * is protected by a semaphore (that behaves like a mutex).
+ */
+
+ DEBUGASSERT(conn->crefs == 0);
+
+ _uip_semtake(&g_free_sem);
+
+ /* Remove the connection from the active list */
+
+ dq_rem(&conn->node, &g_active_pkt_connections);
+
+ /* Free the connection */
+
+ dq_addlast(&conn->node, &g_free_pkt_connections);
+ _uip_semgive(&g_free_sem);
+}
+
+/****************************************************************************
+ * Name: uip_pktactive()
+ *
+ * Description:
+ * Find a connection structure that is the appropriate
+ * connection to be used with the provided Ethernet header
+ *
+ * Assumptions:
+ * This function is called from UIP logic at interrupt level
+ *
+ ****************************************************************************/
+
+struct uip_pkt_conn *uip_pktactive(struct uip_eth_hdr *buf)
+{
+ #define uip_ethaddr_cmp(addr1, addr2) \
+ ((addr1[0] == addr2[0]) && (addr1[1] == addr2[1]) && \
+ (addr1[2] == addr2[2]) && (addr1[3] == addr2[3]) && \
+ (addr1[4] == addr2[4]) && (addr1[5] == addr2[5]))
+
+ FAR struct uip_pkt_conn *conn =
+ (struct uip_pkt_conn *)g_active_pkt_connections.head;
+
+ while (conn)
+ {
+ /* FIXME lmac in conn should have been set by pkt_rawbind() */
+
+ if (uip_ethaddr_cmp(buf->dest, conn->lmac))
+ {
+ /* Matching connection found.. return a reference to it */
+
+ break;
+ }
+
+ /* Look at the next active connection */
+
+ conn = (struct uip_pkt_conn *)conn->node.flink;
+ }
+
+ return conn;
+}
+
+/****************************************************************************
+ * Name: uip_nextpktconn()
+ *
+ * Description:
+ * Traverse the list of allocated packet connections
+ *
+ * Assumptions:
+ * This function is called from UIP logic at interrupt level (or with
+ * interrupts disabled).
+ *
+ ****************************************************************************/
+
+struct uip_pkt_conn *uip_nextpktconn(struct uip_pkt_conn *conn)
+{
+ if (!conn)
+ {
+ return (struct uip_pkt_conn *)g_active_pkt_connections.head;
+ }
+ else
+ {
+ return (struct uip_pkt_conn *)conn->node.flink;
+ }
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_PKT */
diff --git a/nuttx/net/uip/uip_pktinput.c b/nuttx/net/uip/uip_pktinput.c
new file mode 100644
index 000000000..9d7714788
--- /dev/null
+++ b/nuttx/net/uip/uip_pktinput.c
@@ -0,0 +1,140 @@
+/****************************************************************************
+ * net/uip/uip_pktinput.c
+ * Handling incoming packet input
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Adapted for NuttX from logic in uIP which also has a BSD-like license:
+ *
+ * Original author Adam Dunkels <adam@dunkels.com>
+ * Copyright () 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_PKT)
+
+#include <debug.h>
+
+#include <nuttx/net/uip/uip.h>
+#include <nuttx/net/uip/uip-arch.h>
+#include <nuttx/net/uip/uip-pkt.h>
+#include <nuttx/net/arp.h>
+
+#include "uip_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define PKTBUF ((struct uip_eth_hdr *)&dev->d_buf)
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: uip_pktinput
+ *
+ * Description:
+ * Handle incoming packet input
+ *
+ * Parameters:
+ * dev - The device driver structure containing the received packet
+ *
+ * Return:
+ * OK The packet has been processed and can be deleted
+ * ERROR Hold the packet and try again later. There is a listening socket
+ * but no recv in place to catch the packet yet.
+ *
+ * Assumptions:
+ * Called from the interrupt level or with interrupts disabled.
+ *
+ ****************************************************************************/
+
+int uip_pktinput(struct uip_driver_s *dev)
+{
+ struct uip_pkt_conn *conn;
+ struct uip_eth_hdr *pbuf = (struct uip_eth_hdr *)dev->d_buf;
+ int ret = OK;
+
+ conn = uip_pktactive(pbuf);
+ if (conn)
+ {
+ uint16_t flags;
+
+ /* Setup for the application callback */
+
+ dev->d_appdata = dev->d_buf;
+ dev->d_snddata = dev->d_buf;
+ dev->d_sndlen = 0;
+
+ /* Perform the application callback */
+
+ flags = uip_pktcallback(dev, conn, UIP_NEWDATA);
+
+ /* If the operation was successful, the UIP_NEWDATA flag is removed
+ * and thus the packet can be deleted (OK will be returned).
+ */
+
+ if ((flags & UIP_NEWDATA) != 0)
+ {
+ /* No.. the packet was not processed now. Return ERROR so
+ * that the driver may retry again later.
+ */
+
+ ret = ERROR;
+ }
+ }
+ else
+ {
+ nlldbg("No listener\n");
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_PKT */
diff --git a/nuttx/net/uip/uip_pktpoll.c b/nuttx/net/uip/uip_pktpoll.c
new file mode 100644
index 000000000..67057b4ef
--- /dev/null
+++ b/nuttx/net/uip/uip_pktpoll.c
@@ -0,0 +1,129 @@
+/****************************************************************************
+ * net/uip/uip_pktpoll.c
+ * Poll for the availability of packet TX data
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Adapted for NuttX from logic in uIP which also has a BSD-like license:
+ *
+ * Original author Adam Dunkels <adam@dunkels.com>
+ * Copyright () 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_PKT)
+
+#include <debug.h>
+
+#include <nuttx/net/uip/uipopt.h>
+#include <nuttx/net/uip/uip.h>
+#include <nuttx/net/uip/uip-arch.h>
+#include <nuttx/net/uip/uip-pkt.h>
+
+#include "uip_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: uip_pktpoll
+ *
+ * Description:
+ * Poll a packet "connection" structure for availability of TX data
+ *
+ * Parameters:
+ * dev - The device driver structure to use in the send operation
+ * conn - The packet "connection" to poll for TX data
+ *
+ * Return:
+ * None
+ *
+ * Assumptions:
+ * Called from the interrupt level or with interrupts disabled.
+ *
+ ****************************************************************************/
+
+void uip_pktpoll(struct uip_driver_s *dev, struct uip_pkt_conn *conn)
+{
+ nlldbg("IN\n");
+
+ /* Verify that the packet connection is valid */
+
+ if (conn)
+ {
+ /* Setup for the application callback */
+
+ dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+ dev->d_snddata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+
+ dev->d_len = 0;
+ dev->d_sndlen = 0;
+
+ /* Perform the application callback */
+
+ (void)uip_pktcallback(dev, conn, UIP_POLL);
+
+ /* If the application has data to send, setup the UDP/IP header */
+
+ if (dev->d_sndlen > 0)
+ {
+// uip_pktsend(dev, conn);
+ return;
+ }
+ }
+
+ /* Make sure that d_len is zero meaning that there is nothing to be sent */
+
+ dev->d_len = 0;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_PKT */
diff --git a/nuttx/net/uip/uip_poll.c b/nuttx/net/uip/uip_poll.c
index 17deca30a..cbd50aef6 100644
--- a/nuttx/net/uip/uip_poll.c
+++ b/nuttx/net/uip/uip_poll.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/uip/uip_poll.c
*
- * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2010, 2012, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -57,6 +57,42 @@
****************************************************************************/
/****************************************************************************
+ * Function: uip_pollpktconnections
+ *
+ * Description:
+ * Poll all packet connections for available packets to send.
+ *
+ * Assumptions:
+ * This function is called from the MAC device driver and may be called from
+ * the timer interrupt/watchdog handle level.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_PKT)
+static int uip_pollpktconnections(struct uip_driver_s *dev,
+ uip_poll_callback_t callback)
+{
+ struct uip_pkt_conn *pkt_conn = NULL;
+ int bstop = 0;
+
+ /* Traverse all of the allocated packet connections and perform the poll action */
+
+ while (!bstop && (pkt_conn = uip_nextpktconn(pkt_conn)))
+ {
+ /* Perform the packet TX poll */
+
+ uip_pktpoll(dev, pkt_conn);
+
+ /* Call back into the driver */
+
+ callback(dev);
+ }
+
+ return bstop;
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
* Function: uip_pollicmp
*
* Description:
@@ -254,34 +290,46 @@ int uip_poll(FAR struct uip_driver_s *dev, uip_poll_callback_t callback)
{
int bstop;
- /* Check for pending IGMP messages */
+ /* Traverse all of the active packet connections and perform the poll
+ * action.
+ */
-#ifdef CONFIG_NET_IGMP
- bstop = uip_polligmp(dev, callback);
+#ifdef CONFIG_NET_PKT
+ bstop = uip_pollpktconnections(dev, callback);
if (!bstop)
#endif
{
- /* Traverse all of the active TCP connections and perform the poll action */
+ /* Check for pendig IGMP messages */
- bstop = uip_polltcpconnections(dev, callback);
+#ifdef CONFIG_NET_IGMP
+ bstop = uip_polligmp(dev, callback);
if (!bstop)
+#endif
{
-#ifdef CONFIG_NET_UDP
- /* Traverse all of the allocated UDP connections and perform the
- * poll action.
+ /* Traverse all of the active TCP connections and perform the poll
+ * action.
*/
- bstop = uip_polludpconnections(dev, callback);
+ bstop = uip_polltcpconnections(dev, callback);
if (!bstop)
-#endif
{
-#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING)
- /* Traverse all of the tasks waiting to send an ICMP ECHO
- * request
+#ifdef CONFIG_NET_UDP
+ /* Traverse all of the allocated UDP connections and perform
+ * the poll action
*/
- bstop = uip_pollicmp(dev, callback);
+ bstop = uip_polludpconnections(dev, callback);
+ if (!bstop)
+#endif
+ {
+#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING)
+ /* Traverse all of the tasks waiting to send an ICMP ECHO
+ * request.
+ */
+
+ bstop = uip_pollicmp(dev, callback);
#endif
+ }
}
}
}
@@ -327,30 +375,46 @@ int uip_timer(FAR struct uip_driver_s *dev, uip_poll_callback_t callback,
}
#endif /* UIP_REASSEMBLY */
- /* Check for pendig IGMP messages */
+ /* Traverse all of the active packet connections and perform the poll
+ * action.
+ */
-#ifdef CONFIG_NET_IGMP
- bstop = uip_polligmp(dev, callback);
+#ifdef CONFIG_NET_PKT
+ bstop = uip_pollpktconnections(dev, callback);
if (!bstop)
#endif
{
- /* Traverse all of the active TCP connections and perform the timer action */
+ /* Check for pending IGMP messages */
- bstop = uip_polltcptimer(dev, callback, hsec);
+#ifdef CONFIG_NET_IGMP
+ bstop = uip_polligmp(dev, callback);
if (!bstop)
+#endif
{
- /* Traverse all of the allocated UDP connections and perform the poll action */
+ /* Traverse all of the active TCP connections and perform the
+ * timer action.
+ */
-#ifdef CONFIG_NET_UDP
- bstop = uip_polludpconnections(dev, callback);
+ bstop = uip_polltcptimer(dev, callback, hsec);
if (!bstop)
-#endif
{
+ /* Traverse all of the allocated UDP connections and perform
+ * the poll action.
+ */
+
+#ifdef CONFIG_NET_UDP
+ bstop = uip_polludpconnections(dev, callback);
+ if (!bstop)
+#endif
+ {
#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING)
- /* Traverse all of the tasks waiting to send an ICMP ECHO request */
+ /* Traverse all of the tasks waiting to send an ICMP ECHO
+ * request.
+ */
- bstop = uip_pollicmp(dev, callback);
+ bstop = uip_pollicmp(dev, callback);
#endif
+ }
}
}
}