mirror of
https://github.com/apache/nuttx.git
synced 2026-05-20 12:33:27 +08:00
IP forwarding: Major rearchitecting of the outgoing portion of the IP forwarding logic necessary into to properly received device-related forwarding events.
This commit is contained in:
@@ -171,12 +171,14 @@
|
|||||||
#define UDP_NEWDATA TCP_NEWDATA
|
#define UDP_NEWDATA TCP_NEWDATA
|
||||||
#define PKT_NEWDATA TCP_NEWDATA
|
#define PKT_NEWDATA TCP_NEWDATA
|
||||||
#define WPAN_NEWDATA TCP_NEWDATA
|
#define WPAN_NEWDATA TCP_NEWDATA
|
||||||
|
#define IPFWD_NEWDATA TCP_NEWDATA
|
||||||
#define TCP_SNDACK (1 << 2)
|
#define TCP_SNDACK (1 << 2)
|
||||||
#define TCP_REXMIT (1 << 3)
|
#define TCP_REXMIT (1 << 3)
|
||||||
#define TCP_POLL (1 << 4)
|
#define TCP_POLL (1 << 4)
|
||||||
#define UDP_POLL TCP_POLL
|
#define UDP_POLL TCP_POLL
|
||||||
#define PKT_POLL TCP_POLL
|
#define PKT_POLL TCP_POLL
|
||||||
#define WPAN_POLL TCP_POLL
|
#define WPAN_POLL TCP_POLL
|
||||||
|
#define IPFWD_POLL TCP_POLL
|
||||||
#define TCP_BACKLOG (1 << 5)
|
#define TCP_BACKLOG (1 << 5)
|
||||||
#define TCP_CLOSE (1 << 6)
|
#define TCP_CLOSE (1 << 6)
|
||||||
#define TCP_ABORT (1 << 7)
|
#define TCP_ABORT (1 << 7)
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ void devif_forward(FAR struct forward_s *fwd)
|
|||||||
DEBUGASSERT(ret == fwd->f_iob->io_pktlen);
|
DEBUGASSERT(ret == fwd->f_iob->io_pktlen);
|
||||||
offset += 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 */
|
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NETDEV_MULTINIC */
|
||||||
|
|||||||
@@ -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*/
|
#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
|
* 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);
|
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)
|
if (!bstop)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,14 +43,6 @@ ifeq ($(CONFIG_NET_ICMP_PING),y)
|
|||||||
NET_CSRCS += icmp_ping.c icmp_poll.c icmp_send.c
|
NET_CSRCS += icmp_ping.c icmp_poll.c icmp_send.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# IP forwarding
|
|
||||||
|
|
||||||
ifeq ($(CONFIG_NET_IPFORWARD),y)
|
|
||||||
ifeq ($(CONFIG_NETDEV_MULTINIC),y)
|
|
||||||
NET_CSRCS += icmp_forward.c
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Include ICMP build support
|
# Include ICMP build support
|
||||||
|
|
||||||
DEPPATH += --dep-path icmp
|
DEPPATH += --dep-path icmp
|
||||||
|
|||||||
@@ -1,304 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* net/icmp/icmp_forward.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. 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>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include <net/if.h>
|
|
||||||
|
|
||||||
#include <nuttx/mm/iob.h>
|
|
||||||
#include <nuttx/net/net.h>
|
|
||||||
#include <nuttx/net/netdev.h>
|
|
||||||
#include <nuttx/net/ip.h>
|
|
||||||
#include <nuttx/net/netstats.h>
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
@@ -63,14 +63,6 @@ ifeq ($(CONFIG_NET_ICMPv6_ROUTER),y)
|
|||||||
NET_CSRCS += icmpv6_radvertise.c
|
NET_CSRCS += icmpv6_radvertise.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# IP forwarding
|
|
||||||
|
|
||||||
ifeq ($(CONFIG_NET_IPFORWARD),y)
|
|
||||||
ifeq ($(CONFIG_NETDEV_MULTINIC),y)
|
|
||||||
NET_CSRCS += icmpv6_forward.c
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Include ICMPv6 build support
|
# Include ICMPv6 build support
|
||||||
|
|
||||||
DEPPATH += --dep-path icmpv6
|
DEPPATH += --dep-path icmpv6
|
||||||
|
|||||||
@@ -178,34 +178,6 @@ int icmpv6_neighbor(const net_ipv6addr_t ipaddr);
|
|||||||
# define icmpv6_neighbor(i) (0)
|
# define icmpv6_neighbor(i) (0)
|
||||||
#endif
|
#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
|
* Name: icmpv6_poll
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,300 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* net/icmpv6/icmpv6_forward.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. 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>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include <net/if.h>
|
|
||||||
|
|
||||||
#include <nuttx/mm/iob.h>
|
|
||||||
#include <nuttx/net/net.h>
|
|
||||||
#include <nuttx/net/netdev.h>
|
|
||||||
#include <nuttx/net/ip.h>
|
|
||||||
#include <nuttx/net/netstats.h>
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
@@ -37,6 +37,8 @@
|
|||||||
|
|
||||||
ifeq ($(CONFIG_NET_IPFORWARD),y)
|
ifeq ($(CONFIG_NET_IPFORWARD),y)
|
||||||
|
|
||||||
|
NET_CSRCS += ipfwd_forward.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_NET_IPv4),y)
|
ifeq ($(CONFIG_NET_IPv4),y)
|
||||||
NET_CSRCS += ipv4_forward.c
|
NET_CSRCS += ipv4_forward.c
|
||||||
endif
|
endif
|
||||||
@@ -49,6 +51,10 @@ ifeq ($(CONFIG_NETDEV_MULTINIC),y)
|
|||||||
NET_CSRCS += ipfwd_alloc.c
|
NET_CSRCS += ipfwd_alloc.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_NET_STATISTICS),y)
|
||||||
|
NET_CSRCS += ipfwd_dropstats.c
|
||||||
|
endif
|
||||||
|
|
||||||
# Include IP forwaring build support
|
# Include IP forwaring build support
|
||||||
|
|
||||||
DEPPATH += --dep-path ipforward
|
DEPPATH += --dep-path ipforward
|
||||||
|
|||||||
+87
-16
@@ -135,21 +135,6 @@ union fwd_iphdr_u
|
|||||||
#endif
|
#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 */
|
/* This is the send state structure */
|
||||||
|
|
||||||
struct devif_callback_s; /* Forward refernce */
|
struct devif_callback_s; /* Forward refernce */
|
||||||
@@ -162,7 +147,6 @@ struct forward_s
|
|||||||
FAR struct net_driver_s *f_dev; /* Forwarding device */
|
FAR struct net_driver_s *f_dev; /* Forwarding device */
|
||||||
FAR struct iob_s *f_iob; /* IOB chain containing the packet */
|
FAR struct iob_s *f_iob; /* IOB chain containing the packet */
|
||||||
FAR struct devif_callback_s *f_cb; /* Reference to callback instance */
|
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)
|
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||||
uint8_t f_domain; /* Domain: PF_INET or PF_INET6 */
|
uint8_t f_domain; /* Domain: PF_INET or PF_INET6 */
|
||||||
#endif
|
#endif
|
||||||
@@ -296,6 +280,31 @@ void ipv6_forward_broadcast(FAR struct net_driver_s *dev,
|
|||||||
|
|
||||||
void devif_forward(FAR struct forward_s *fwd);
|
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 */
|
#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);
|
int ipv6_forward(FAR struct net_driver_s *dev, FAR struct ipv6_hdr_s *ipv6);
|
||||||
#endif
|
#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 /* CONFIG_NET_IPFORWARD */
|
||||||
#endif /* __NET_IPFORWARD_IPFORWARD_H */
|
#endif /* __NET_IPFORWARD_IPFORWARD_H */
|
||||||
|
|||||||
@@ -0,0 +1,192 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* net/ipforward/ipfwd_dropstats.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <nuttx/net/netstats.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/udp/udp_forward.c
|
* net/ipforward/ipfwd_forward.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
@@ -49,15 +49,13 @@
|
|||||||
#include <nuttx/net/ip.h>
|
#include <nuttx/net/ip.h>
|
||||||
#include <nuttx/net/netstats.h>
|
#include <nuttx/net/netstats.h>
|
||||||
|
|
||||||
#include "ipforward/ipforward.h"
|
|
||||||
#include "devif/devif.h"
|
#include "devif/devif.h"
|
||||||
#include "netdev/netdev.h"
|
#include "netdev/netdev.h"
|
||||||
#include "arp/arp.h"
|
#include "arp/arp.h"
|
||||||
#include "neighbor/neighbor.h"
|
#include "neighbor/neighbor.h"
|
||||||
#include "udp/udp.h"
|
#include "ipforward/ipforward.h"
|
||||||
|
|
||||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_UDP) && \
|
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NETDEV_MULTINIC)
|
||||||
defined(CONFIG_NETDEV_MULTINIC)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
@@ -86,23 +84,35 @@
|
|||||||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||||
static inline void forward_ipselect(FAR struct forward_s *fwd)
|
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 */
|
/* Select IPv4 or IPv6 */
|
||||||
|
|
||||||
if (fwd->f_domain == PF_INET)
|
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
|
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
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: udp_forward_addrchk
|
* Name: ipfwd_addrchk
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Check if the destination IP address is in the IPv4 ARP or IPv6 Neighbor
|
* 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
|
#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;
|
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 */
|
#else /* CONFIG_NET_ETHERNET */
|
||||||
# define udp_forward_addrchk(r) (true)
|
# define ipfwd_addrchk(r) (true)
|
||||||
#endif /* CONFIG_NET_ETHERNET */
|
#endif /* CONFIG_NET_ETHERNET */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: udp_dropstats
|
* Name: ipfwd_interrupt
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This function is called from the interrupt level to perform the actual
|
* 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:
|
* Parameters:
|
||||||
* dev The structure of the network driver that caused the interrupt
|
* 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*
|
* pvpriv An instance of struct forward_s cast to void*
|
||||||
* flags Set of events describing why the callback was invoked
|
* 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,
|
static uint16_t ipfwd_interrupt(FAR struct net_driver_s *dev, FAR void *conn,
|
||||||
FAR void *conn, FAR void *pvpriv,
|
FAR void *pvpriv, uint16_t flags)
|
||||||
uint16_t flags)
|
|
||||||
{
|
{
|
||||||
FAR struct forward_s *fwd = (FAR struct forward_s *)pvpriv;
|
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. */
|
/* Terminate the transfer with an error. */
|
||||||
|
|
||||||
nwarn("WARNING: Network is down... Dropping\n");
|
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
|
/* 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.
|
* 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,
|
/* Another thread has beat us sending data or the buffer is busy,
|
||||||
* Wait for the next polling cycle and check again.
|
* 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.
|
* will be replaced with an ARP request or Neighbor Solicitation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!udp_forward_addrchk(fwd))
|
if (!ipfwd_addrchk(fwd))
|
||||||
{
|
{
|
||||||
return flags;
|
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->priv = NULL;
|
||||||
fwd->f_cb->event = 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 */
|
/* 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:
|
* Description:
|
||||||
* Called by the IP forwarding logic when an UDP packet is received on
|
* Called by the IP forwarding logic when a packet is received on one
|
||||||
* one network device, but must be forwarded on another network device.
|
* network device, but must be forwarded on another network device.
|
||||||
*
|
*
|
||||||
* Set up to forward the UDP packet on the specified device. This
|
* Set up to forward the packet on the specified device. This function
|
||||||
* function will set up a send "interrupt" handler that will perform the
|
* will set up a send "interrupt" handler that will perform the actual
|
||||||
* actual send asynchronously and must return without waiting for the
|
* send asynchronously and must return without waiting for the send to
|
||||||
* send to complete.
|
* complete.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* fwd - An initialized instance of the common forwarding structure that
|
* 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);
|
DEBUGASSERT(fwd != NULL && fwd->f_iob != NULL && fwd->f_dev != NULL);
|
||||||
|
|
||||||
/* Set up the callback in the connection */
|
/* 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)
|
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->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 */
|
/* Notify the device driver of the availability of TX data */
|
||||||
|
|
||||||
@@ -389,4 +350,4 @@ int udp_forward(FAR struct forward_s *fwd)
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NET_UDP && CONFIG_NETDEV_MULTINIC */
|
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NETDEV_MULTINIC */
|
||||||
@@ -51,9 +51,6 @@
|
|||||||
#include "netdev/netdev.h"
|
#include "netdev/netdev.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include "sixlowpan/sixlowpan.h"
|
#include "sixlowpan/sixlowpan.h"
|
||||||
#include "udp/udp.h"
|
|
||||||
#include "tcp/tcp.h"
|
|
||||||
#include "icmp/icmp.h"
|
|
||||||
#include "ipforward/ipforward.h"
|
#include "ipforward/ipforward.h"
|
||||||
#include "devif/devif.h"
|
#include "devif/devif.h"
|
||||||
|
|
||||||
@@ -190,55 +187,6 @@ static int ipv4_decr_ttl(FAR struct ipv4_hdr_s *ipv4)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
* Name: ipv4_dev_forward
|
||||||
*
|
*
|
||||||
@@ -366,51 +314,9 @@ static int ipv4_dev_forward(FAR struct net_driver_s *dev,
|
|||||||
goto errout_with_iobchain;
|
goto errout_with_iobchain;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then set up to forward the packet according to the protocol.
|
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ret = ipfwd_forward(fwd);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
dev->d_len = 0;
|
dev->d_len = 0;
|
||||||
|
|||||||
@@ -50,11 +50,8 @@
|
|||||||
|
|
||||||
#include "netdev/netdev.h"
|
#include "netdev/netdev.h"
|
||||||
#include "sixlowpan/sixlowpan.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 "devif/devif.h"
|
||||||
|
#include "ipforward/ipforward.h"
|
||||||
|
|
||||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6)
|
#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
|
#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
|
* Name: ipv6_packet_conversion
|
||||||
*
|
*
|
||||||
@@ -477,58 +425,16 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
|
|||||||
goto errout_with_iobchain;
|
goto errout_with_iobchain;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then set up to forward the packet according to the protocol.
|
/* 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 (ipv6->proto)
|
ret = ipfwd_forward(fwd);
|
||||||
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_NET_TCP
|
dev->d_len = 0;
|
||||||
case IP_PROTO_TCP:
|
return OK;
|
||||||
{
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret >= 0)
|
|
||||||
{
|
|
||||||
dev->d_len = 0;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
errout_with_iobchain:
|
errout_with_iobchain:
|
||||||
if (fwd != NULL && fwd->f_iob != NULL)
|
if (fwd != NULL && fwd->f_iob != NULL)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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_send.c tcp_input.c tcp_appsend.c tcp_listen.c
|
||||||
NET_CSRCS += tcp_callback.c tcp_backlog.c tcp_ipselect.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
|
# TCP write buffering
|
||||||
|
|
||||||
ifeq ($(CONFIG_NET_TCP_WRITE_BUFFERS),y)
|
ifeq ($(CONFIG_NET_TCP_WRITE_BUFFERS),y)
|
||||||
|
|||||||
@@ -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,
|
void tcp_send(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||||
uint16_t flags, uint16_t len);
|
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
|
* Name: tcp_reset
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,443 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* net/tcp/tcp_forward.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. 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>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include <net/if.h>
|
|
||||||
|
|
||||||
#include <nuttx/mm/iob.h>
|
|
||||||
#include <nuttx/net/net.h>
|
|
||||||
#include <nuttx/net/netdev.h>
|
|
||||||
#include <nuttx/net/ip.h>
|
|
||||||
#include <nuttx/net/netstats.h>
|
|
||||||
|
|
||||||
#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 */
|
|
||||||
@@ -48,14 +48,6 @@ NET_CSRCS += udp_netpoll.c
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# IP forwarding
|
|
||||||
|
|
||||||
ifeq ($(CONFIG_NET_IPFORWARD),y)
|
|
||||||
ifeq ($(CONFIG_NETDEV_MULTINIC),y)
|
|
||||||
NET_CSRCS += udp_forward.c
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Transport layer
|
# Transport layer
|
||||||
|
|
||||||
NET_CSRCS += udp_conn.c udp_devpoll.c udp_send.c udp_input.c udp_finddev.c
|
NET_CSRCS += udp_conn.c udp_devpoll.c udp_send.c udp_input.c udp_finddev.c
|
||||||
|
|||||||
@@ -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,
|
uint16_t udp_callback(FAR struct net_driver_s *dev,
|
||||||
FAR struct udp_conn_s *conn, uint16_t flags);
|
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
|
* Name: psock_udp_send
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user