forked from nuttx/nuttx-update
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:
parent
803235ad4b
commit
aa2e9c15a5
19 changed files with 369 additions and 1460 deletions
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
||||
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
|
||||
|
|
|
@ -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 */
|
||||
|
|
192
net/ipforward/ipfwd_dropstats.c
Normal file
192
net/ipforward/ipfwd_dropstats.c
Normal file
|
@ -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.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
|
@ -49,15 +49,13 @@
|
|||
#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 "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 */
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
||||
# 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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue