diff --git a/net/devif/devif.h b/net/devif/devif.h index e90377dd585..99b389c9b1d 100644 --- a/net/devif/devif.h +++ b/net/devif/devif.h @@ -171,12 +171,14 @@ #define UDP_NEWDATA TCP_NEWDATA #define PKT_NEWDATA TCP_NEWDATA #define WPAN_NEWDATA TCP_NEWDATA +#define IPFWD_NEWDATA TCP_NEWDATA #define TCP_SNDACK (1 << 2) #define TCP_REXMIT (1 << 3) #define TCP_POLL (1 << 4) #define UDP_POLL TCP_POLL #define PKT_POLL TCP_POLL #define WPAN_POLL TCP_POLL +#define IPFWD_POLL TCP_POLL #define TCP_BACKLOG (1 << 5) #define TCP_CLOSE (1 << 6) #define TCP_ABORT (1 << 7) diff --git a/net/devif/devif_forward.c b/net/devif/devif_forward.c index 00bf2e3690b..4f93ee3cbbb 100644 --- a/net/devif/devif_forward.c +++ b/net/devif/devif_forward.c @@ -87,7 +87,8 @@ void devif_forward(FAR struct forward_s *fwd) DEBUGASSERT(ret == fwd->f_iob->io_pktlen); offset += fwd->f_iob->io_pktlen; - fwd->f_dev->d_sndlen = offset; + fwd->f_dev->d_sndlen = 0; + fwd->f_dev->d_len = offset; } #endif /* CONFIG_NET_IPFORWARD && CONFIG_NETDEV_MULTINIC */ diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c index 08d6c99e8ae..73c5050f588 100644 --- a/net/devif/devif_poll.c +++ b/net/devif/devif_poll.c @@ -251,6 +251,28 @@ static inline int devif_poll_icmpv6(FAR struct net_driver_s *dev, } #endif /* CONFIG_NET_ICMPv6_PING || CONFIG_NET_ICMPv6_NEIGHBOR*/ +/**************************************************************************** + * Name: devif_poll_forward + * + * Description: + * Poll the device event to see if any task is waiting to forward a packet. + * + ****************************************************************************/ + +#if defined(CONFIG_NET_IPFORWARD) || defined(CONFIG_NETDEV_MULTINIC) +static inline int devif_poll_forward(FAR struct net_driver_s *dev, + devif_poll_callback_t callback) +{ + /* Perform the ICMPv6 poll */ + + devif_dev_event(dev, NULL, IPFWD_POLL); + + /* Call back into the driver */ + + return callback(dev); +} +#endif /* CONFIG_NET_ICMPv6_PING || CONFIG_NET_ICMPv6_NEIGHBOR*/ + /**************************************************************************** * Name: devif_poll_igmp * @@ -506,6 +528,15 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback) bstop = devif_poll_icmpv6(dev, callback); } + if (!bstop) +#endif +#if defined(CONFIG_NET_IPFORWARD) || defined(CONFIG_NETDEV_MULTINIC) + { + /* Traverse all of the tasks waiting to forward a packet to this device. */ + + bstop = devif_poll_forward(dev, callback); + } + if (!bstop) #endif { diff --git a/net/icmp/Make.defs b/net/icmp/Make.defs index 6b002964e4f..d5a67c2065f 100644 --- a/net/icmp/Make.defs +++ b/net/icmp/Make.defs @@ -43,14 +43,6 @@ ifeq ($(CONFIG_NET_ICMP_PING),y) NET_CSRCS += icmp_ping.c icmp_poll.c icmp_send.c endif -# IP forwarding - -ifeq ($(CONFIG_NET_IPFORWARD),y) -ifeq ($(CONFIG_NETDEV_MULTINIC),y) -NET_CSRCS += icmp_forward.c -endif -endif - # Include ICMP build support DEPPATH += --dep-path icmp diff --git a/net/icmp/icmp_foward.c b/net/icmp/icmp_foward.c deleted file mode 100644 index 2730e355404..00000000000 --- a/net/icmp/icmp_foward.c +++ /dev/null @@ -1,304 +0,0 @@ -/**************************************************************************** - * net/icmp/icmp_forward.c - * - * Copyright (C) 2017 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. 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 - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "ipforward/ipforward.h" -#include "devif/devif.h" -#include "netdev/netdev.h" -#include "arp/arp.h" -#include "neighbor/neighbor.h" -#include "icmp/icmp.h" - -#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_ICMP) && \ - defined(CONFIG_NETDEV_MULTINIC) - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: icmp_forward_addrchck - * - * Description: - * Check if the destination IP address is in the IPv4 ARP table. If not, - * then the send won't actually make it out... it will be replaced with an - * ARP request (IPv4). - * - * NOTE 1: This could be an expensive check if there are a lot of - * entries in the ARP table. - * - * NOTE 2: If we are actually harvesting IP addresses on incoming IP - * packets, then this check should not be necessary; the MAC mapping - * should already be in the ARP table in many cases. - * - * NOTE 3: If CONFIG_NET_ARP_SEND then we can be assured that the IP - * address mapping is already in the ARP table. - * - * Parameters: - * fwd - The forwarding state structure - * - * Returned Value: - * true - The Ethernet MAC address is in the ARP table (OR the network - * device is not Ethernet). - * - * Assumptions: - * The network is locked. - * - ****************************************************************************/ - -#ifdef CONFIG_NET_ETHERNET -static inline bool icmp_forward_addrchck(FAR struct forward_s *fwd) -{ -#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND) - FAR union fwd_iphdr_u *iphdr; -#endif - - DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL); - - /* REVISIT: Could the MAC address not also be in a routing table? */ - -#ifdef CONFIG_NET_MULTILINK - if (fwd->f_dev->d_lltype != NET_LL_ETHERNET) - { - return true; - } -#endif - -#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND) - iphdr = FWD_HEADER(fwd); - return (arp_find(iphdr->ipv4.l2.destipaddr) != NULL); -#else - return true; -#endif -} - -#else /* CONFIG_NET_ETHERNET */ -# define icmp_forward_addrchck(fwd) (true) -#endif /* CONFIG_NET_ETHERNET */ - -/**************************************************************************** - * Name: icmp_dropstats - * - * Description: - * Update statistics for a dropped packet. - * - * Input Parameters: - * fwd - The forwarding state structure - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef CONFIG_NET_STATISTICS -static inline void icmp_dropstats(FAR struct forward_s *fwd) -{ - /* Increment the count of dropped ICMP packets */ - - g_netstats.icmp.drop++; - g_netstats.ipv4.drop++; -} -#else -# define icmp_dropstats(fwd) -#endif - -/**************************************************************************** - * Name: icmp_forward_interrupt - * - * Description: - * This function is called from the interrupt level to perform the actual - * send operation when polled by the lower, device interfacing layer. - * - * Parameters: - * dev The structure of the network driver that caused the interrupt - * conn An instance of the ICMP connection structure cast to void * - * pvpriv An instance of struct forward_s cast to void* - * flags Set of events describing why the callback was invoked - * - * Returned Value: - * Modified value of the input flags - * - * Assumptions: - * The network is locked - * - ****************************************************************************/ - -static uint16_t icmp_forward_interrupt(FAR struct net_driver_s *dev, - FAR void *conn, FAR void *pvpriv, - uint16_t flags) -{ - FAR struct forward_s *fwd = (FAR struct forward_s *)pvpriv; - - ninfo("flags: %04x\n", flags); - DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL); - - /* Make sure that this is from the forwarding device */ - - if (dev == fwd->f_dev) - { - /* If the network device has gone down, then we will have terminate - * the wait now with an error. - */ - - if ((flags & NETDEV_DOWN) != 0) - { - /* Terminate the transfer with an error. */ - - nwarn("WARNING: Network is down... Dropping\n"); - icmp_dropstats(fwd); - } - - /* Check if the outgoing packet is available. It may have been claimed - * by another 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. - */ - - else if (dev->d_sndlen > 0 || (flags & ICMP_NEWDATA) != 0) - { - /* Another thread has beat us sending data or the buffer is busy, - * Wait for the next polling cycle and check again. - */ - - return flags; - } - - /* It looks like we are good to forward the data */ - - else - { - /* Copy the ICMP data into driver's packet buffer and send it. */ - - devif_forward(fwd); - - /* Check if the destination IP address is in the ARP or Neighbor - * table. If not, then the send won't actually make it out... it - * will be replaced with an ARP request or Neighbor Solicitation. - */ - - if (!icmp_forward_addrchck(fwd)) - { - return flags; - } - } - - /* Free the allocated callback structure */ - - fwd->f_cb->flags = 0; - fwd->f_cb->priv = NULL; - fwd->f_cb->event = NULL; - - icmp_callback_free(dev, fwd->f_cb); - - /* Free any IOBs */ - - if (fwd->f_iob != NULL) - { - iob_free_chain(fwd->f_iob); - } - - /* And release the forwarding state structure */ - - ipfwd_free(fwd); - } - - return flags; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: icmp_forward - * - * Description: - * Called by the IP forwarding logic when an ICMP packet is received on - * one network device, but must be forwarded on another network device. - * - * Set up to forward the ICMP packet on the specified device. This - * function will set up a send "interrupt" handler that will perform the - * actual send asynchronously and must return without waiting for the - * send to complete. - * - * Input Parameters: - * fwd - An initialized instance of the common forwarding structure that - * includes everything needed to perform the forwarding operation. - * - * Returned Value: - * Zero is returned if the packet was successfully forwarded; A negated - * errno value is returned if the packet is not forwardable. In that - * latter case, the caller should free the IOB list and drop the packet. - * - ****************************************************************************/ - -int icmp_forward(FAR struct forward_s *fwd) -{ - DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL); - - /* Set up the callback in the connection */ - - fwd->f_cb = icmp_callback_alloc(fwd->f_dev); - if (fwd->f_cb != NULL) - { - fwd->f_cb->flags = (ICMP_POLL | NETDEV_DOWN); - fwd->f_cb->priv = (FAR void *)fwd; - fwd->f_cb->event = icmp_forward_interrupt; - - /* Notify the device driver of the availability of TX data */ - - netdev_txnotify_dev(fwd->f_dev); - return OK; - } - - return -EBUSY; -} - -#endif /* CONFIG_NET_IPFORWARD && CONFIG_NET_ICMP && CONFIG_NETDEV_MULTINIC */ diff --git a/net/icmpv6/Make.defs b/net/icmpv6/Make.defs index b8231151fc2..6c9b70aee7e 100644 --- a/net/icmpv6/Make.defs +++ b/net/icmpv6/Make.defs @@ -63,14 +63,6 @@ ifeq ($(CONFIG_NET_ICMPv6_ROUTER),y) NET_CSRCS += icmpv6_radvertise.c endif -# IP forwarding - -ifeq ($(CONFIG_NET_IPFORWARD),y) -ifeq ($(CONFIG_NETDEV_MULTINIC),y) -NET_CSRCS += icmpv6_forward.c -endif -endif - # Include ICMPv6 build support DEPPATH += --dep-path icmpv6 diff --git a/net/icmpv6/icmpv6.h b/net/icmpv6/icmpv6.h index 8ff15abaee2..d1150de6980 100644 --- a/net/icmpv6/icmpv6.h +++ b/net/icmpv6/icmpv6.h @@ -178,34 +178,6 @@ int icmpv6_neighbor(const net_ipv6addr_t ipaddr); # define icmpv6_neighbor(i) (0) #endif -/**************************************************************************** - * Name: icmpv6_forward - * - * Description: - * Called by the IP forwarding logic when an ICMPv6 packet is received on - * one network device, but must be forwarded on another network device. - * - * Set up to forward the ICMPv6 packet on the specified device. The - * function will set up a send "interrupt" handler that will perform the - * actual send asynchronously and must return without waiting for the - * send to complete. - * - * Input Parameters: - * fwd - An initialized instance of the common forwarding structure that - * includes everything needed to perform the forwarding operation. - * - * Returned Value: - * Zero is returned if the packet was successfully forwarded; A negated - * errno value is returned if the packet is not forwardable. In that - * latter case, the caller should free the IOB list and drop the packet. - * - ****************************************************************************/ - -#if defined(CONFIG_NETDEV_MULTINIC) && defined(CONFIG_NET_IPFORWARD) -struct forward_s; -int icmpv6_forward(FAR struct forward_s *fwd); -#endif - /**************************************************************************** * Name: icmpv6_poll * diff --git a/net/icmpv6/icmpv6_forward.c b/net/icmpv6/icmpv6_forward.c deleted file mode 100644 index 866a67d6a06..00000000000 --- a/net/icmpv6/icmpv6_forward.c +++ /dev/null @@ -1,300 +0,0 @@ -/**************************************************************************** - * net/icmpv6/icmpv6_forward.c - * - * Copyright (C) 2017 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. 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 - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "ipforward/ipforward.h" -#include "devif/devif.h" -#include "netdev/netdev.h" -#include "arp/arp.h" -#include "neighbor/neighbor.h" -#include "icmpv6/icmpv6.h" - -#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_ICMPv6) && \ - defined(CONFIG_NETDEV_MULTINIC) - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: icmpv6_forward_addrchck - * - * Description: - * Check if the destination IP address is in the Pv6 Neighbor table. If - * not, then the send won't actually make it out... it will be replaced - * with a Neighbor Solicitation. - * - * NOTE 1: This could be an expensive check if there are a lot of - * entries in the Neighbor table. - * - * NOTE 2: If CONFIG_NET_ARP_SEND then we can be assured that the IP - * address mapping is already in the ARP table. - * - * Parameters: - * fwd - The forwarding state structure - * - * Returned Value: - * true - The Ethernet MAC address is in the Neighbor table (OR the - * network device is not Ethernet). - * - * Assumptions: - * The network is locked. - * - ****************************************************************************/ - -#ifdef CONFIG_NET_ETHERNET -static inline bool icmpv6_forward_addrchck(FAR struct forward_s *fwd) -{ -#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND) - FAR union fwd_iphdr_u *iphdr; -#endif - - DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL); - - /* REVISIT: Could the MAC address not also be in a routing table? */ - -#ifdef CONFIG_NET_MULTILINK - if (fwd->f_dev->d_lltype != NET_LL_ETHERNET) - { - return true; - } -#endif - -#if !defined(CONFIG_NET_ICMPv6_NEIGHBOR) - iphdr = FWD_HEADER(fwd); - return (arp_find(iphdr->ipv6.l2.destipaddr) != NULL); -#else - return true; -#endif -} - -#else /* CONFIG_NET_ETHERNET */ -# define icmpv6_forward_addrchck(fwd) (true) -#endif /* CONFIG_NET_ETHERNET */ - -/**************************************************************************** - * Name: icmpv6_dropstats - * - * Description: - * Update statistics for a dropped packet. - * - * Input Parameters: - * fwd - The forwarding state structure - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef CONFIG_NET_STATISTICS -static inline void icmpv6_dropstats(FAR struct forward_s *fwd) -{ - /* Increment the count of dropped ICMPv6 packets */ - - g_netstats.icmpv6.drop++; - g_netstats.ipv6.drop++; -} -#else -# define icmpv6_dropstats(fwd) -#endif - -/**************************************************************************** - * Name: icmpv6_forward_interrupt - * - * Description: - * This function is called from the interrupt level to perform the actual - * send operation when polled by the lower, device interfacing layer. - * - * Parameters: - * dev The structure of the network driver that caused the interrupt - * conn An instance of the ICMPv6 connection structure cast to void * - * pvpriv An instance of struct forward_s cast to void* - * flags Set of events describing why the callback was invoked - * - * Returned Value: - * Modified value of the input flags - * - * Assumptions: - * The network is locked - * - ****************************************************************************/ - -static uint16_t icmpv6_forward_interrupt(FAR struct net_driver_s *dev, - FAR void *conn, FAR void *pvpriv, - uint16_t flags) -{ - FAR struct forward_s *fwd = (FAR struct forward_s *)pvpriv; - - ninfo("flags: %04x\n", flags); - DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL); - - /* Make sure that this is from the forwarding device */ - - if (dev == fwd->f_dev) - { - /* If the network device has gone down, then we will have terminate - * the wait now with an error. - */ - - if ((flags & NETDEV_DOWN) != 0) - { - /* Terminate the transfer with an error. */ - - nwarn("WARNING: Network is down... Dropping\n"); - icmpv6_dropstats(fwd); - } - - /* Check if the outgoing packet is available. It may have been claimed - * by another 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. - */ - - else if (dev->d_sndlen > 0 || (flags & ICMPv6_NEWDATA) != 0) - { - /* Another thread has beat us sending data or the buffer is busy, - * Wait for the next polling cycle and check again. - */ - - return flags; - } - - /* It looks like we are good to forward the data */ - - else - { - /* Copy the ICMPv6 data into driver's packet buffer and send it. */ - - devif_forward(fwd); - - /* Check if the destination IP address is in the ARP or Neighbor - * table. If not, then the send won't actually make it out... it - * will be replaced with an ARP request or Neighbor Solicitation. - */ - - if (!icmpv6_forward_addrchck(fwd)) - { - return flags; - } - } - - /* Free the allocated callback structure */ - - fwd->f_cb->flags = 0; - fwd->f_cb->priv = NULL; - fwd->f_cb->event = NULL; - - icmpv6_callback_free(dev, fwd->f_cb); - - /* Free any IOBs */ - - if (fwd->f_iob != NULL) - { - iob_free_chain(fwd->f_iob); - } - - /* And release the forwarding state structure */ - - ipfwd_free(fwd); - } - - return flags; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: icmpv6_forward - * - * Description: - * Called by the IP forwarding logic when an ICMPv6 packet is received on - * one network device, but must be forwarded on another network device. - * - * Set up to forward the ICMPv6 packet on the specified device. This - * function will set up a send "interrupt" handler that will perform the - * actual send asynchronously and must return without waiting for the - * send to complete. - * - * Input Parameters: - * fwd - An initialized instance of the common forwarding structure that - * includes everything needed to perform the forwarding operation. - * - * Returned Value: - * Zero is returned if the packet was successfully forwarded; A negated - * errno value is returned if the packet is not forwardable. In that - * latter case, the caller should free the IOB list and drop the packet. - * - ****************************************************************************/ - -int icmpv6_forward(FAR struct forward_s *fwd) -{ - DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL); - - /* Set up the callback in the connection */ - - fwd->f_cb = icmpv6_callback_alloc(fwd->f_dev); - if (fwd->f_cb != NULL) - { - fwd->f_cb->flags = (ICMPv6_POLL | NETDEV_DOWN); - fwd->f_cb->priv = (FAR void *)fwd; - fwd->f_cb->event = icmpv6_forward_interrupt; - - /* Notify the device driver of the availability of TX data */ - - netdev_txnotify_dev(fwd->f_dev); - return OK; - } - - return -EBUSY; -} - -#endif /* CONFIG_NET_IPFORWARD && CONFIG_NET_ICMPv6 && CONFIG_NETDEV_MULTINIC */ diff --git a/net/ipforward/Make.defs b/net/ipforward/Make.defs index 56789ceb57e..cc46826da53 100644 --- a/net/ipforward/Make.defs +++ b/net/ipforward/Make.defs @@ -37,6 +37,8 @@ ifeq ($(CONFIG_NET_IPFORWARD),y) +NET_CSRCS += ipfwd_forward.c + ifeq ($(CONFIG_NET_IPv4),y) NET_CSRCS += ipv4_forward.c endif @@ -49,6 +51,10 @@ ifeq ($(CONFIG_NETDEV_MULTINIC),y) NET_CSRCS += ipfwd_alloc.c endif +ifeq ($(CONFIG_NET_STATISTICS),y) +NET_CSRCS += ipfwd_dropstats.c +endif + # Include IP forwaring build support DEPPATH += --dep-path ipforward diff --git a/net/ipforward/ipforward.h b/net/ipforward/ipforward.h index ee27f464479..52069b80abe 100644 --- a/net/ipforward/ipforward.h +++ b/net/ipforward/ipforward.h @@ -135,21 +135,6 @@ union fwd_iphdr_u #endif }; -/* Connection structures */ - -union fwd_conn_u -{ -#ifdef CONFIG_NET_TCP - struct tcp_conn_s tcp; -#endif -#ifdef CONFIG_NET_UDP - struct udp_conn_s udp; -#endif -#ifdef CONFIG_NET_ICMPv6 - struct icmpv6_conn_s icmpv6; -#endif -}; - /* This is the send state structure */ struct devif_callback_s; /* Forward refernce */ @@ -162,7 +147,6 @@ struct forward_s FAR struct net_driver_s *f_dev; /* Forwarding device */ FAR struct iob_s *f_iob; /* IOB chain containing the packet */ FAR struct devif_callback_s *f_cb; /* Reference to callback instance */ - union fwd_conn_u f_conn; /* Protocol-specific connection struct */ #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) uint8_t f_domain; /* Domain: PF_INET or PF_INET6 */ #endif @@ -296,6 +280,31 @@ void ipv6_forward_broadcast(FAR struct net_driver_s *dev, void devif_forward(FAR struct forward_s *fwd); +/**************************************************************************** + * Name: ipfwd_forward + * + * Description: + * Called by the IP forwarding logic when a packet is received on one + * network device, but must be forwarded on another network device. + * + * Set up to forward the packet on the specified device. This function + * will set up a send "interrupt" handler that will perform the actual + * send asynchronously and must return without waiting for the send to + * complete. + * + * Input Parameters: + * fwd - An initialized instance of the common forwarding structure that + * includes everything needed to perform the forwarding operation. + * + * Returned Value: + * Zero is returned if the packet was successfully forwarded; A negated + * errno value is returned if the packet is not forwardable. In that + * latter case, the caller should free the IOB list and drop the packet. + * + ****************************************************************************/ + +int ipfwd_forward(FAR struct forward_s *fwd); + #endif /* CONFIG_NETDEV_MULTINIC */ /**************************************************************************** @@ -358,5 +367,67 @@ int ipv4_forward(FAR struct net_driver_s *dev, FAR struct ipv4_hdr_s *ipv4); int ipv6_forward(FAR struct net_driver_s *dev, FAR struct ipv6_hdr_s *ipv6); #endif +/**************************************************************************** + * Name: ipv6_dropstats + * + * Description: + * Update statistics for a dropped Ipv6 packet. + * + * Input Parameters: + * ipv6 - A pointer to the IPv6 header in within the IPv6 packet to be + * dropped. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_NET_STATISTICS) && defined(CONFIG_NET_IPv6) +void ipv6_dropstats(FAR struct ipv6_hdr_s *ipv6); +#else +# define ipv6_dropstats(ipv6) +#endif + +/**************************************************************************** + * Name: ipv4_dropstats + * + * Description: + * Update statistics for a dropped Ipv4 packet. + * + * Input Parameters: + * ipv4 - A pointer to the IPv4 header in within the IPv4 packet to be + * dropped. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_NET_STATISTICS) && defined(CONFIG_NET_IPv4) +void ipv4_dropstats(FAR struct ipv4_hdr_s *ipv4); +#else +# define ipv4_dropstats(ipv4) +#endif + +/**************************************************************************** + * Name: ipfwd_dropstats + * + * Description: + * Update statistics for a dropped packet. + * + * Input Parameters: + * fwd - The forwarding state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NET_STATISTICS +void ipfwd_dropstats(FAR struct forward_s *fwd) +#else +# define ipfwd_dropstats(fwd) +#endif + #endif /* CONFIG_NET_IPFORWARD */ #endif /* __NET_IPFORWARD_IPFORWARD_H */ diff --git a/net/ipforward/ipfwd_dropstats.c b/net/ipforward/ipfwd_dropstats.c new file mode 100644 index 00000000000..d743b17916c --- /dev/null +++ b/net/ipforward/ipfwd_dropstats.c @@ -0,0 +1,192 @@ +/**************************************************************************** + * net/ipforward/ipfwd_dropstats.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 "ipforward/ipforward.h" + +#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_STATISTICS) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: proto_dropstats + * + * Description: + * Update statistics for a dropped L2 protocol packet. + * + * Input Parameters: + * proto - The protocol from the IPv4 or IPv6 header. + * + * Returned Value: + * On success, zero (OK) is returned. Otherwise, a negated errno value + * is returned. The only error is if th protocol is not recognized. + * + ****************************************************************************/ + +static int proto_dropstats(int proto) +{ + switch (proto) + { +#ifdef CONFIG_NET_TCP + case IP_PROTO_TCP: + g_netstats.tcp.drop++; + break; +#endif + +#ifdef CONFIG_NET_UDP + case IP_PROTO_UDP: + g_netstats.udp.drop++; + break; +#endif + +#ifdef CONFIG_NET_ICMPv6 + case IP_PROTO_ICMP6: + g_netstats.icmpv6.drop++; + break; +#endif + + default: + retrun -EPROTONOSUPPORT; + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipv6_dropstats + * + * Description: + * Update statistics for a dropped Ipv6 packet. + * + * Input Parameters: + * ipv6 - A pointer to the IPv6 header in within the IPv6 packet to be + * dropped. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +void ipv6_dropstats(FAR struct ipv6_hdr_s *ipv6) +{ + int ret; + + ret = proto_dropstats(ipv6->proto); + if (ret < 0) + { + g_netstats.ipv6.protoerr++; + } + + g_netstats.ipv6.drop++; +} +#endif + +/**************************************************************************** + * Name: ipv4_dropstats + * + * Description: + * Update statistics for a dropped Ipv4 packet. + * + * Input Parameters: + * ipv4 - A pointer to the IPv4 header in within the IPv4 packet to be + * dropped. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 +void ipv4_dropstats(FAR struct ipv4_hdr_s *ipv4) +{ + int ret; + + ret = proto_dropstats(ipv6->ipv4); + if (ret < 0) + { + g_netstats.ipv4.protoerr++; + } + + g_netstats.ipv4.drop++; +} +#endif + +/**************************************************************************** + * Name: ipfwd_dropstats + * + * Description: + * Update statistics for a dropped packet. + * + * Input Parameters: + * fwd - The forwarding state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +void ipfwd_dropstats(FAR struct forward_s *fwd) +{ +#ifdef CONFIG_NET_IPv4 +#ifdef CONFIG_NET_IPv6 + if (fwd->domain == PF_INET) +#endif + { + ipv4_dropstats((FAR struct ipv4_hdr_s *)fwd->f_iob->io_data); + } +#endif +#ifdef CONFIG_NET_IPv6 +#ifdef CONFIG_NET_IPv4 + else +#endif + { + ipv6_dropstats((FAR struct ipv6_hdr_s *)fwd->f_iob->io_data); + } +#endif +} diff --git a/net/udp/udp_forward.c b/net/ipforward/ipfwd_forward.c similarity index 78% rename from net/udp/udp_forward.c rename to net/ipforward/ipfwd_forward.c index e65cbe6ea17..c7e1156b105 100644 --- a/net/udp/udp_forward.c +++ b/net/ipforward/ipfwd_forward.c @@ -1,5 +1,5 @@ /**************************************************************************** - * net/udp/udp_forward.c + * net/ipforward/ipfwd_forward.c * * Copyright (C) 2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -49,15 +49,13 @@ #include #include -#include "ipforward/ipforward.h" #include "devif/devif.h" #include "netdev/netdev.h" #include "arp/arp.h" #include "neighbor/neighbor.h" -#include "udp/udp.h" +#include "ipforward/ipforward.h" -#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_UDP) && \ - defined(CONFIG_NETDEV_MULTINIC) +#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NETDEV_MULTINIC) /**************************************************************************** * Public Functions @@ -86,23 +84,35 @@ #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) static inline void forward_ipselect(FAR struct forward_s *fwd) { - FAR union fwd_iphdr_u *iphdr = FWD_HEADER(fwd); + FAR struct net_driver_s *dev = fwd->f_dev; /* Select IPv4 or IPv6 */ if (fwd->f_domain == PF_INET) { - udp_ipv4_select(fwd->f_dev); + /* Clear a bit in the d_flags to distinguish this from an IPv6 packet */ + + IFF_SET_IPv4(dev->d_flags); + + /* Set the offset to the beginning of the UDP data payload */ + + dev->d_appdata = &dev->d_buf[IPv4UDP_HDRLEN + NET_LL_HDRLEN(dev)]; } else { - udp_ipv6_select(fwd->f_dev); + /* Set a bit in the d_flags to distinguish this from an IPv6 packet */ + + IFF_SET_IPv6(dev->d_flags); + + /* Set the offset to the beginning of the UDP data payload */ + + dev->d_appdata = &dev->d_buf[IPv6_HDRLEN + NET_LL_HDRLEN(dev)]; } } #endif /**************************************************************************** - * Name: udp_forward_addrchk + * Name: ipfwd_addrchk * * Description: * Check if the destination IP address is in the IPv4 ARP or IPv6 Neighbor @@ -132,7 +142,7 @@ static inline void forward_ipselect(FAR struct forward_s *fwd) ****************************************************************************/ #ifdef CONFIG_NET_ETHERNET -static inline bool udp_forward_addrchk(FAR struct forward_s *fwd) +static inline bool ipfwd_addrchk(FAR struct forward_s *fwd) { FAR union fwd_iphdr_u *iphdr; @@ -177,59 +187,11 @@ static inline bool udp_forward_addrchk(FAR struct forward_s *fwd) } #else /* CONFIG_NET_ETHERNET */ -# define udp_forward_addrchk(r) (true) +# define ipfwd_addrchk(r) (true) #endif /* CONFIG_NET_ETHERNET */ /**************************************************************************** - * Name: udp_dropstats - * - * Description: - * Update statistics for a dropped packet. - * - * Input Parameters: - * fwd - The forwarding state structure - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef CONFIG_NET_STATISTICS -static void udp_dropstats(FAR struct forward_s *fwd) -{ -#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) - FAR union fwd_iphdr_u *iphdr = FWD_HEADER(fwd); -#endif - - /* Increment the count of dropped UDP packets */ - - g_netstats.udp.drop++; - - /* Increment the count of dropped IPv4 or IPv6 packets */ - -#ifdef CONFIG_NET_IPv4 -#ifdef CONFIG_NET_IPv6 - if (fwd->f_domain == PF_INET) -#endif - { - g_netstats.ipv4.drop++; - } -#endif -#ifdef CONFIG_NET_IPv6 -#ifdef CONFIG_NET_IPv4 - else -#endif - { - g_netstats.ipv6.drop++; - } -#endif -} -#else -# define udp_dropstats(ipv6) -#endif - -/**************************************************************************** - * Name: udp_forward_interrupt + * Name: ipfwd_interrupt * * Description: * This function is called from the interrupt level to perform the actual @@ -237,7 +199,7 @@ static void udp_dropstats(FAR struct forward_s *fwd) * * Parameters: * dev The structure of the network driver that caused the interrupt - * conn An instance of the UDP connection structure cast to void * + * conn An instance of the forwarding structure cast to void * * pvpriv An instance of struct forward_s cast to void* * flags Set of events describing why the callback was invoked * @@ -249,9 +211,8 @@ static void udp_dropstats(FAR struct forward_s *fwd) * ****************************************************************************/ -static uint16_t udp_forward_interrupt(FAR struct net_driver_s *dev, - FAR void *conn, FAR void *pvpriv, - uint16_t flags) +static uint16_t ipfwd_interrupt(FAR struct net_driver_s *dev, FAR void *conn, + FAR void *pvpriv, uint16_t flags) { FAR struct forward_s *fwd = (FAR struct forward_s *)pvpriv; @@ -271,7 +232,7 @@ static uint16_t udp_forward_interrupt(FAR struct net_driver_s *dev, /* Terminate the transfer with an error. */ nwarn("WARNING: Network is down... Dropping\n"); - udp_dropstats(fwd); + ipfwd_dropstats(fwd); } /* Check if the outgoing packet is available. It may have been claimed @@ -280,7 +241,7 @@ static uint16_t udp_forward_interrupt(FAR struct net_driver_s *dev, * we will just have to wait for the next polling cycle. */ - else if (dev->d_sndlen > 0 || (flags & UDP_NEWDATA) != 0) + else if (dev->d_sndlen > 0 || (flags & IPFWD_NEWDATA) != 0) { /* Another thread has beat us sending data or the buffer is busy, * Wait for the next polling cycle and check again. @@ -311,7 +272,7 @@ static uint16_t udp_forward_interrupt(FAR struct net_driver_s *dev, * will be replaced with an ARP request or Neighbor Solicitation. */ - if (!udp_forward_addrchk(fwd)) + if (!ipfwd_addrchk(fwd)) { return flags; } @@ -323,7 +284,7 @@ static uint16_t udp_forward_interrupt(FAR struct net_driver_s *dev, fwd->f_cb->priv = NULL; fwd->f_cb->event = NULL; - udp_callback_free(dev, &fwd->f_conn.udp, fwd->f_cb); + devif_conn_callback_free(dev, fwd->f_cb, NULL); /* Free any IOBs */ @@ -345,16 +306,16 @@ static uint16_t udp_forward_interrupt(FAR struct net_driver_s *dev, ****************************************************************************/ /**************************************************************************** - * Name: udp_forward + * Name: ipfwd_forward * * Description: - * Called by the IP forwarding logic when an UDP packet is received on - * one network device, but must be forwarded on another network device. + * Called by the IP forwarding logic when a packet is received on one + * network device, but must be forwarded on another network device. * - * Set up to forward the UDP packet on the specified device. This - * function will set up a send "interrupt" handler that will perform the - * actual send asynchronously and must return without waiting for the - * send to complete. + * Set up to forward the packet on the specified device. This function + * will set up a send "interrupt" handler that will perform the actual + * send asynchronously and must return without waiting for the send to + * complete. * * Input Parameters: * fwd - An initialized instance of the common forwarding structure that @@ -367,18 +328,18 @@ static uint16_t udp_forward_interrupt(FAR struct net_driver_s *dev, * ****************************************************************************/ -int udp_forward(FAR struct forward_s *fwd) +int ipfwd_forward(FAR struct forward_s *fwd) { DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL); /* Set up the callback in the connection */ - fwd->f_cb = udp_callback_alloc(fwd->f_dev, &fwd->f_conn.udp); + fwd->f_cb = devif_callback_alloc(fwd->f_dev, NULL); if (fwd->f_cb != NULL) { - fwd->f_cb->flags = (UDP_POLL | NETDEV_DOWN); + fwd->f_cb->flags = (IPFWD_POLL | NETDEV_DOWN); fwd->f_cb->priv = (FAR void *)fwd; - fwd->f_cb->event = udp_forward_interrupt; + fwd->f_cb->event = ipfwd_interrupt; /* Notify the device driver of the availability of TX data */ @@ -389,4 +350,4 @@ int udp_forward(FAR struct forward_s *fwd) return -EBUSY; } -#endif /* CONFIG_NET_IPFORWARD && CONFIG_NET_UDP && CONFIG_NETDEV_MULTINIC */ +#endif /* CONFIG_NET_IPFORWARD && CONFIG_NETDEV_MULTINIC */ diff --git a/net/ipforward/ipv4_forward.c b/net/ipforward/ipv4_forward.c index 63dd5aae5bf..2c1e5f8756a 100644 --- a/net/ipforward/ipv4_forward.c +++ b/net/ipforward/ipv4_forward.c @@ -51,9 +51,6 @@ #include "netdev/netdev.h" #include "utils/utils.h" #include "sixlowpan/sixlowpan.h" -#include "udp/udp.h" -#include "tcp/tcp.h" -#include "icmp/icmp.h" #include "ipforward/ipforward.h" #include "devif/devif.h" @@ -190,55 +187,6 @@ static int ipv4_decr_ttl(FAR struct ipv4_hdr_s *ipv4) } #endif -/**************************************************************************** - * Name: ipv4_dropstats - * - * Description: - * Update statistics for a dropped packet. - * - * Input Parameters: - * ipv4 - A convenience pointer to the IPv4 header in within the IPv4 - * packet to be dropped. - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef CONFIG_NET_STATISTICS -static void ipv4_dropstats(FAR struct ipv4_hdr_s *ipv4) -{ - switch (ipv4->proto) - { -#ifdef CONFIG_NET_TCP - case IP_PROTO_TCP: - g_netstats.tcp.drop++; - break; -#endif - -#ifdef CONFIG_NET_UDP - case IP_PROTO_UDP: - g_netstats.udp.drop++; - break; -#endif - -#ifdef CONFIG_NET_ICMP - case IP_PROTO_ICMP: - g_netstats.icmp.drop++; - break; -#endif - - default: - g_netstats.ipv4.protoerr++; - break; - } - - g_netstats.ipv4.drop++; -} -#else -# define ipv4_dropstats(ipv4) -#endif - /**************************************************************************** * Name: ipv4_dev_forward * @@ -366,51 +314,9 @@ static int ipv4_dev_forward(FAR struct net_driver_s *dev, goto errout_with_iobchain; } - /* Then set up to forward the packet according to the protocol. - * - * REVISIT: Are these protocol specific forwarders necessary? I think - * that this could be done with a single forwarding function for all - * protocols. - */ - - switch (ipv4->proto) - { -#ifdef CONFIG_NET_TCP - case IP_PROTO_TCP: - { - /* Forward a TCP packet. */ - - ret = tcp_forward(fwd); - } - break; -#endif - -#ifdef CONFIG_NET_UDP - case IP_PROTO_UDP: - { - /* Forward a UDP packet */ - - ret = udp_forward(fwd); - } - break; -#endif - -#ifdef CONFIG_NET_ICMP - case IP_PROTO_ICMP: - { - /* Forward an ICMP packet */ - - ret = icmp_forward(fwd); - } - break; -#endif - - default: - nwarn("WARNING: Unrecognized proto: %u\n", ipv4->proto); - ret = -EPROTONOSUPPORT; - break; - } + /* Then set up to forward the packet according to the protocol. */ + ret = ipfwd_forward(fwd); if (ret >= 0) { dev->d_len = 0; diff --git a/net/ipforward/ipv6_forward.c b/net/ipforward/ipv6_forward.c index e50fe7c2b0f..b76a219d81c 100644 --- a/net/ipforward/ipv6_forward.c +++ b/net/ipforward/ipv6_forward.c @@ -50,11 +50,8 @@ #include "netdev/netdev.h" #include "sixlowpan/sixlowpan.h" -#include "udp/udp.h" -#include "tcp/tcp.h" -#include "icmpv6/icmpv6.h" -#include "ipforward/ipforward.h" #include "devif/devif.h" +#include "ipforward/ipforward.h" #if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6) @@ -183,55 +180,6 @@ static int ipv6_decr_ttl(FAR struct ipv6_hdr_s *ipv6) } #endif -/**************************************************************************** - * Name: ipv6_dropstats - * - * Description: - * Update statistics for a dropped packet. - * - * Input Parameters: - * ipv6 - A convenience pointer to the IPv6 header in within the IPv6 - * packet to be dropped. - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef CONFIG_NET_STATISTICS -static void ipv6_dropstats(FAR struct ipv6_hdr_s *ipv6) -{ - switch (ipv6->proto) - { -#ifdef CONFIG_NET_TCP - case IP_PROTO_TCP: - g_netstats.tcp.drop++; - break; -#endif - -#ifdef CONFIG_NET_UDP - case IP_PROTO_UDP: - g_netstats.udp.drop++; - break; -#endif - -#ifdef CONFIG_NET_ICMPv6 - case IP_PROTO_ICMP6: - g_netstats.icmpv6.drop++; - break; -#endif - - default: - g_netstats.ipv6.protoerr++; - break; - } - - g_netstats.ipv6.drop++; -} -#else -# define ipv6_dropstats(ipv6) -#endif - /**************************************************************************** * Name: ipv6_packet_conversion * @@ -477,58 +425,16 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev, goto errout_with_iobchain; } - /* Then set up to forward the packet according to the protocol. - * - * REVISIT: Are these protocol specific forwarders necessary? I think - * that this could be done with a single forwarding function for all - * protocols. - */ + /* Then set up to forward the packet according to the protocol. */ - switch (ipv6->proto) + ret = ipfwd_forward(fwd); + if (ret >= 0) { -#ifdef CONFIG_NET_TCP - case IP_PROTO_TCP: - { - /* Forward a TCP packet. */ - - ret = tcp_forward(fwd); - } - break; -#endif - -#ifdef CONFIG_NET_UDP - case IP_PROTO_UDP: - { - /* Forward a UDP packet */ - - ret = udp_forward(fwd); - } - break; -#endif - -#ifdef CONFIG_NET_ICMPv6 - case IP_PROTO_ICMP6: - { - /* Forward an ICMPv6 packet */ - - ret = icmpv6_forward(fwd); - } - break; -#endif - - default: - nwarn("WARNING: Unrecognized proto: %u\n", ipv6->proto); - ret = -EPROTONOSUPPORT; - break; + dev->d_len = 0; + return OK; } } - if (ret >= 0) - { - dev->d_len = 0; - return OK; - } - errout_with_iobchain: if (fwd != NULL && fwd->f_iob != NULL) { diff --git a/net/tcp/Make.defs b/net/tcp/Make.defs index 7f3a88582b5..c7b00b60406 100644 --- a/net/tcp/Make.defs +++ b/net/tcp/Make.defs @@ -60,14 +60,6 @@ NET_CSRCS += tcp_conn.c tcp_seqno.c tcp_devpoll.c tcp_finddev.c tcp_timer.c NET_CSRCS += tcp_send.c tcp_input.c tcp_appsend.c tcp_listen.c NET_CSRCS += tcp_callback.c tcp_backlog.c tcp_ipselect.c -# IP forwarding - -ifeq ($(CONFIG_NET_IPFORWARD),y) -ifeq ($(CONFIG_NETDEV_MULTINIC),y) -NET_CSRCS += tcp_forward.c -endif -endif - # TCP write buffering ifeq ($(CONFIG_NET_TCP_WRITE_BUFFERS),y) diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index 9497e426ec1..f13170668d9 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -794,37 +794,6 @@ int tcp_accept_connection(FAR struct net_driver_s *dev, void tcp_send(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn, uint16_t flags, uint16_t len); -/**************************************************************************** - * Name: tcp_forward - * - * Description: - * Called by the IP forwarding logic when an TCP packet is received on - * one network device, but must be forwarded on another network device. - * - * Set up to forward the TCP packet on the specified device. This - * function will set up a send "interrupt" handler that will perform - * the actual send asynchronously and must return without waiting for the - * send to complete. - * - * Input Parameters: - * domain - Either PF_INET or PF_INET6 - * fwd - An initialized instance of the common forwarding structure - * that includes everything needed to perform the forwarding - * operation. - * - * Returned Value: - * Zero is returned if the packet was successfully forwarded; A negated - * errno value is returned if the packet is not forwardable. In that - * latter case, the caller should free the IOB list and drop the packet. - * - ****************************************************************************/ - -#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6) && \ - defined(CONFIG_NETDEV_MULTINIC) -struct forward_s; /* Forward reference */ -int tcp_forward(FAR struct forward_s *fwd); -#endif - /**************************************************************************** * Name: tcp_reset * diff --git a/net/tcp/tcp_forward.c b/net/tcp/tcp_forward.c deleted file mode 100644 index 542b0e8e1cb..00000000000 --- a/net/tcp/tcp_forward.c +++ /dev/null @@ -1,443 +0,0 @@ -/**************************************************************************** - * net/tcp/tcp_forward.c - * - * Copyright (C) 2017 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. 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 - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "ipforward/ipforward.h" -#include "devif/devif.h" -#include "netdev/netdev.h" -#include "arp/arp.h" -#include "neighbor/neighbor.h" -#include "tcp/tcp.h" - -#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_TCP) && \ - defined(CONFIG_NETDEV_MULTINIC) - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: forward_ipselect - * - * Description: - * If both IPv4 and IPv6 support are enabled, then we will need to select - * which one to use when generating the outgoing packet. If only one - * domain is selected, then the setup is already in place and we need do - * nothing. - * - * Parameters: - * fwd - The forwarding state structure - * - * Returned Value: - * None - * - * Assumptions: - * The network is locked. - * - ****************************************************************************/ - -#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) -static inline void forward_ipselect(FAR struct forward_s *fwd) -{ - /* Which domain the connection support */ - - if (fwd->f_domain == PF_INET) - { - /* Select the IPv4 domain */ - - tcp_ipv4_select(fwd->f_dev); - } - else /* if (conn->domain == PF_INET6) */ - { - /* Select the IPv6 domain */ - - DEBUGASSERT(fwd->f_conn.tcp.domain == PF_INET6); - tcp_ipv6_select(fwd->f_dev); - } -} -#endif - -/**************************************************************************** - * Name: tcp_forward_addrchck - * - * Description: - * Check if the destination IP address is in the IPv4 ARP or IPv6 Neighbor - * tables. If not, then the send won't actually make it out... it will be - * replaced with an ARP request (IPv4) or a Neighbor Solicitation (IPv6). - * - * NOTE 1: This could be an expensive check if there are a lot of - * entries in the ARP or Neighbor tables. - * - * NOTE 2: If we are actually harvesting IP addresses on incoming IP - * packets, then this check should not be necessary; the MAC mapping - * should already be in the ARP table in many cases (IPv4 only). - * - * NOTE 3: If CONFIG_NET_ARP_SEND then we can be assured that the IP - * address mapping is already in the ARP table. - * - * Parameters: - * fwd - The forwarding state structure - * - * Returned Value: - * true - The Ethernet MAC address is in the ARP or Neighbor table (OR - * the network device is not Ethernet). - * - * Assumptions: - * The network is locked. - * - ****************************************************************************/ - -#ifdef CONFIG_NET_ETHERNET -static inline bool tcp_forward_addrchck(FAR struct forward_s *fwd) -{ - FAR struct tcp_conn_s *conn = &fwd->f_conn.tcp; - - /* REVISIT: Could the MAC address not also be in a routing table? */ - -#ifdef CONFIG_NET_MULTILINK - if (fwd->f_dev->d_lltype != NET_LL_ETHERNET) - { - return true; - } -#endif - -#ifdef CONFIG_NET_IPv4 -#ifdef CONFIG_NET_IPv6 - if (fwd->f_domain == PF_INET) -#endif - { -#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND) - return (arp_find(conn->u.ipv4.raddr) != NULL); -#else - return true; -#endif - } -#endif /* CONFIG_NET_IPv4 */ - -#ifdef CONFIG_NET_IPv6 -#ifdef CONFIG_NET_IPv4 - else -#endif - { -#if !defined(CONFIG_NET_ICMPv6_NEIGHBOR) - return (neighbor_findentry(conn->u.ipv6.raddr) != NULL); -#else - return true; -#endif - } -#endif /* CONFIG_NET_IPv6 */ - - UNUSED(conn); -} - -#else /* CONFIG_NET_ETHERNET */ -# define tcp_forward_addrchck(r) (true) -#endif /* CONFIG_NET_ETHERNET */ - -/**************************************************************************** - * Name: tcp_dropstats - * - * Description: - * Update statistics for a dropped packet. - * - * Input Parameters: - * fwd - The forwarding state structure - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef CONFIG_NET_STATISTICS -static void tcp_dropstats(FAR struct forward_s *fwd) -{ - /* Increment the count of dropped TCP packets */ - - g_netstats.tcp.drop++; - - /* Increment the count of dropped IPv4 or IPv6 packets */ - -#ifdef CONFIG_NET_IPv4 -#ifdef CONFIG_NET_IPv6 - if (fwd->f_domain == PF_INET) -#endif - { - g_netstats.ipv4.drop++; - } -#endif -#ifdef CONFIG_NET_IPv6 -#ifdef CONFIG_NET_IPv4 - else -#endif - { - g_netstats.ipv6.drop++; - } -#endif -} -#else -# define tcp_dropstats(ipv6) -#endif - -/**************************************************************************** - * Name: tcp_forward_interrupt - * - * Description: - * This function is called from the interrupt level to perform the actual - * send operation when polled by the lower, device interfacing layer. - * - * NOTE: Our role here is just data passthrough. We don't really care - * about ACKing, dynamic windows or any of the other TCP complexities. - * That is really something between the two endpoints and does not matter - * the forwarding hub. - * - * Parameters: - * dev The structure of the network driver that caused the interrupt - * conn An instance of the TCP connection structure cast to void * - * pvpriv An instance of struct forward_s cast to void* - * flags Set of events describing why the callback was invoked - * - * Returned Value: - * Modified value of the input flags - * - * Assumptions: - * The network is locked - * - ****************************************************************************/ - -static uint16_t tcp_forward_interrupt(FAR struct net_driver_s *dev, - FAR void *conn, FAR void *pvpriv, - uint16_t flags) -{ - FAR struct forward_s *fwd = (FAR struct forward_s *)pvpriv; - - ninfo("flags: %04x\n", flags); - DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL); - - /* Make sure that this is from the forwarding device */ - - if (dev == fwd->f_dev) - { - /* If the network device has gone down, then we will have terminate - * the wait now with an error. - * - * REVISIT: TCP disconnection events should should not be recieved here. - * Rather the disconnection events will be handled by the TCP endpoints. - */ - - if ((flags & NETDEV_DOWN) != 0) - { - /* Terminate the transfer with an error. */ - - nwarn("WARNING: Network is down... Dropping\n"); - tcp_dropstats(fwd); - } - - /* Check if the outgoing packet is available. It may have been claimed - * by a sendto 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. - */ - - else if (dev->d_sndlen > 0 || (flags & TCP_NEWDATA) != 0) - { - /* Another thread has beat us sending data or the buffer is busy, - * Wait for the next polling cycle and check again. - */ - - return flags; - } - - /* It looks like we are good to forward the data */ - - else - { -#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) - /* If both IPv4 and IPv6 support are enabled, then we will need to - * select which one to use when generating the outgoing packet. - * If only one domain is selected, then the setup is already in - * place and we need do nothing. - */ - - forward_ipselect(fwd); -#endif - /* Copy the user data into d_appdata and send it. */ - - devif_forward(fwd); - - /* Check if the destination IP address is in the ARP or Neighbor - * table. If not, then the send won't actually make it out... it - * will be replaced with an ARP request or Neighbor Solicitation. - */ - - if (!tcp_forward_addrchck(fwd)) - { - return flags; - } - } - - /* Free the allocated callback structure */ - - fwd->f_cb->flags = 0; - fwd->f_cb->priv = NULL; - fwd->f_cb->event = NULL; - - tcp_callback_free(&fwd->f_conn.tcp, fwd->f_cb); - - /* Free any IOBs */ - - if (fwd->f_iob != NULL) - { - iob_free_chain(fwd->f_iob); - } - - /* And release the forwarding state structure */ - - ipfwd_free(fwd); - } - - return flags; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: tcp_forward - * - * Description: - * Called by the IP forwarding logic when an TCP packet is received on - * one network device, but must be forwarded on another network device. - * - * Set up to forward the TCP packet on the specified device. This - * function will set up a send "interrupt" handler that will perform the - * actual send asynchronously and must return without waiting for the - * send to complete. - * - * Input Parameters: - * fwd - An initialized instance of the common forwarding structure that - * includes everything needed to perform the forwarding operation. - * - * Returned Value: - * Zero is returned if the packet was successfully forwarded; A negated - * errno value is returned if the packet is not forwardable. In that - * latter case, the caller should free the IOB list and drop the packet. - * - ****************************************************************************/ - -int tcp_forward(FAR struct forward_s *fwd) -{ - FAR struct tcp_conn_s *conn = &fwd->f_conn.tcp; - FAR union fwd_iphdr_u *iphdr; - - DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL); - - /* Set up some minimal connection structure so that we appear to be a - * real TCP connection. - */ - - conn->dev = fwd->f_dev; - iphdr = FWD_HEADER(fwd); - -#ifdef CONFIG_NET_IPv4 -#ifdef CONFIG_NET_IPv6 - if (fwd->f_domain == PF_INET) -#endif - { - FAR struct ipv4_hdr_s *ipv4 = &iphdr->ipv4.l2; - FAR struct tcp_hdr_s *tcp = &iphdr->ipv4.l3.tcp; - -#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) - conn->domain = PF_INET; -#endif - conn->lport = tcp->srcport; - conn->rport = tcp->destport; - net_ipv4addr_copy(conn->u.ipv4.laddr, ipv4->srcipaddr); - net_ipv4addr_copy(conn->u.ipv4.raddr, ipv4->destipaddr); - } -#endif -#ifdef CONFIG_NET_IPv6 -#ifdef CONFIG_NET_IPv4 - else -#endif - { - FAR struct ipv6_hdr_s *ipv6 = &iphdr->ipv6.l2; - FAR struct tcp_hdr_s *tcp = &iphdr->ipv6.l3.tcp; - -#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) - conn->domain = PF_INET6; -#endif - conn->lport = tcp->srcport; - conn->rport = tcp->destport; - net_ipv6addr_copy(conn->u.ipv6.laddr, ipv6->srcipaddr); - net_ipv6addr_copy(conn->u.ipv6.raddr, ipv6->destipaddr); - } -#endif - - /* Set up the callback in the connection */ - - fwd->f_cb = tcp_callback_alloc(conn); - if (fwd->f_cb != NULL) - { - fwd->f_cb->flags = (TCP_POLL | NETDEV_DOWN); - fwd->f_cb->priv = (FAR void *)fwd; - fwd->f_cb->event = tcp_forward_interrupt; - - /* Notify the device driver of the availability of TX data */ - - netdev_txnotify_dev(fwd->f_dev); - return OK; - } - - return -EBUSY; -} - -#endif /* CONFIG_NET_IPFORWARD && CONFIG_NET_TCP && CONFIG_NETDEV_MULTINIC */ diff --git a/net/udp/Make.defs b/net/udp/Make.defs index 9dda0a16042..4b3992911df 100644 --- a/net/udp/Make.defs +++ b/net/udp/Make.defs @@ -48,14 +48,6 @@ NET_CSRCS += udp_netpoll.c endif endif -# IP forwarding - -ifeq ($(CONFIG_NET_IPFORWARD),y) -ifeq ($(CONFIG_NETDEV_MULTINIC),y) -NET_CSRCS += udp_forward.c -endif -endif - # Transport layer NET_CSRCS += udp_conn.c udp_devpoll.c udp_send.c udp_input.c udp_finddev.c diff --git a/net/udp/udp.h b/net/udp/udp.h index 91a690f5fe0..cb6ca378f5c 100644 --- a/net/udp/udp.h +++ b/net/udp/udp.h @@ -428,35 +428,6 @@ FAR struct net_driver_s *udp_find_raddr_device(FAR struct udp_conn_s *conn); uint16_t udp_callback(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn, uint16_t flags); -/**************************************************************************** - * Name: udp_forward - * - * Description: - * Called by the IP forwarding logic when an UDP packet is received on - * one network device, but must be forwarded on another network device. - * - * Set up to forward the UDP packet on the specified device. This - * function will set up a send "interrupt" handler that will perform the - * actual send asynchronously and must return without waiting for the - * send to complete. - * - * Input Parameters: - * fwd - An initialized instance of the common forwarding structure that - * includes everything needed to perform the forwarding operation. - * - * Returned Value: - * Zero is returned if the packet was successfully forwarded; A negated - * errno value is returned if the packet is not forwardable. In that - * latter case, the caller should free the IOB list and drop the packet. - * - ****************************************************************************/ - -#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6) && \ - defined(CONFIG_NETDEV_MULTINIC) -struct forward_s; /* Forward reference */ -int udp_forward(FAR struct forward_s *fwd); -#endif - /**************************************************************************** * Name: psock_udp_send *