mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
IP forwarding: Flesh out TCP, UDP, and ICMPv6 packet forwarding logic.
This commit is contained in:
+1
-1
@@ -53,7 +53,7 @@ endif
|
||||
|
||||
ifeq ($(CONFIG_NET_IPFORWARD),y)
|
||||
ifeq ($(CONFIG_NETDEV_MULTINIC),y)
|
||||
NET_CSRCS += ip_forward.c
|
||||
NET_CSRCS += ip_forward.c devif_forward.c
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/****************************************************************************
|
||||
* net/devif/devif_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 <debug.h>
|
||||
|
||||
#include <nuttx/net/netdev.h>
|
||||
|
||||
#include "devif/ip_forward.h"
|
||||
#include "devif/devif.h"
|
||||
|
||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NETDEV_MULTINIC)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: devif_forward
|
||||
*
|
||||
* Description:
|
||||
* Called from protocol-specific IP forwarding logic to re-send a packet.
|
||||
*
|
||||
* Input Parameters:
|
||||
* fwd - An initialized instance of the common forwarding structure that
|
||||
* includes everything needed to perform the forwarding operation.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void devif_forward(FAR struct forward_s *fwd)
|
||||
{
|
||||
unsigned int offset;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(fwd != NULL && fwd->f_dev != NULL);
|
||||
offset = NET_LL_HDRLEN(fwd->f_dev);
|
||||
|
||||
/* Copy the saved L2 + L3 header */
|
||||
|
||||
DEBUGASSERT(offset + fwd->f_hdrsize <= NET_DEV_MTU(fwd->f_dev));
|
||||
memcpy(&fwd->f_dev->d_buf[offset], &fwd->f_hdr, fwd->f_hdrsize);
|
||||
offset += fwd->f_hdrsize;
|
||||
|
||||
/* Copy the IOB chain that contains the payload */
|
||||
|
||||
if (fwd->f_iob != NULL && fwd->f_iob->io_pktlen > 0)
|
||||
{
|
||||
DEBUGASSERT(offset + fwd->f_iob->io_pktlen <= NET_DEV_MTU(fwd->f_dev));
|
||||
ret = iob_copyout(&fwd->f_dev->d_buf[offset], fwd->f_iob,
|
||||
fwd->f_iob->io_pktlen, 0);
|
||||
|
||||
DEBUGASSERT(ret == fwd->f_iob->io_pktlen);
|
||||
offset += fwd->f_iob->io_pktlen;
|
||||
}
|
||||
|
||||
fwd->f_dev->d_sndlen = offset;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NETDEV_MULTINIC */
|
||||
@@ -48,34 +48,6 @@
|
||||
|
||||
#ifdef CONFIG_MM_IOB
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Declarations
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Constant Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Constant Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
+2
-29
@@ -47,33 +47,7 @@
|
||||
|
||||
#include <nuttx/net/netdev.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Declarations
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Constant Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Constant Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
#include "devif/devif.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -87,8 +61,7 @@
|
||||
* the network interface driver.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from the interrupt level or, at a minimum, with interrupts
|
||||
* disabled.
|
||||
* The network is locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
+54
-12
@@ -49,6 +49,10 @@
|
||||
#include <nuttx/net/tcp.h>
|
||||
#include <nuttx/net/icmpv6.h>
|
||||
|
||||
#include "udp/udp.h"
|
||||
#include "tcp/tcp.h"
|
||||
#include "icmpv6/icmpv6.h"
|
||||
|
||||
#undef HAVE_FWDALLOC
|
||||
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NETDEV_MULTINIC)
|
||||
|
||||
@@ -69,7 +73,7 @@
|
||||
/* IPv4 + L2 header */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
struct ipv6_fwdhdr_s
|
||||
struct fwd_ipv4hdr_u
|
||||
{
|
||||
struct ipv4_hdr_s l2;
|
||||
union
|
||||
@@ -91,7 +95,7 @@ struct ipv6_fwdhdr_s
|
||||
/* IPv6 + L2 header */
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
struct ipv6_fwdhdr_s
|
||||
struct fwd_ipv6hdr_u
|
||||
{
|
||||
struct ipv6_hdr_s l2;
|
||||
union
|
||||
@@ -112,28 +116,46 @@ struct ipv6_fwdhdr_s
|
||||
|
||||
/* IPv4 or IPv6 + L2 header */
|
||||
|
||||
union ip_fwdhdr_u
|
||||
union fwd_iphdr_u
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
struct ipv4_fwdhdr_s ipv4;
|
||||
struct fwd_ipv4hdr_u ipv4;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
struct ipv6_fwdhdr_s ipv6;
|
||||
struct fwd_ipv6hdr_u ipv6;
|
||||
#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 net_driver_s; /* Forward reference */
|
||||
struct iob_s; /* Forward reference */
|
||||
struct devif_callback_s; /* Forward refernce */
|
||||
struct net_driver_s; /* Forward reference */
|
||||
struct iob_s; /* Forward reference */
|
||||
|
||||
struct forward_s
|
||||
{
|
||||
FAR struct forward_s *f_flink; /* Supports a singly linked list */
|
||||
FAR struct net_driver_s *f_dev; /* Forwarding device */
|
||||
FAR struct iob_s *f_iob; /* IOBs containing the data payload */
|
||||
union ip_fwdhdr_u f_hdr; /* Copy of original L2+L3 headers */
|
||||
uint8_t f_hdrsize; /* The size of the L2+L3 headers */
|
||||
FAR struct forward_s *f_flink; /* Supports a singly linked list */
|
||||
FAR struct net_driver_s *f_dev; /* Forwarding device */
|
||||
FAR struct iob_s *f_iob; /* IOBs containing the data payload */
|
||||
FAR struct devif_callback_s *f_cb; /* Reference to callback instance */
|
||||
union fwd_iphdr_u f_hdr; /* Copy of original L2+L3 headers */
|
||||
union fwd_conn_u f_conn; /* Protocol-specific connectin struct */
|
||||
uint8_t f_hdrsize; /* The size of the L2+L3 headers */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -182,5 +204,25 @@ FAR struct forward_s *ip_forward_alloc(void);
|
||||
|
||||
void ip_forward_free(FAR struct forward_s *fwd);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: devif_forward
|
||||
*
|
||||
* Description:
|
||||
* Called from protocol-specific IP forwarding logic to re-send a packet.
|
||||
*
|
||||
* Input Parameters:
|
||||
* fwd - An initialized instance of the common forwarding structure that
|
||||
* includes everything needed to perform the forwarding operation.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void devif_forward(FAR struct forward_s *fwd);
|
||||
|
||||
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NETDEV_MULTINIC */
|
||||
#endif /* __NET_DEVIF_IP_FORWARD_H */
|
||||
|
||||
@@ -225,6 +225,17 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
|
||||
FAR uint8_t *payload;
|
||||
unsigned int paysize;
|
||||
|
||||
/* Verify that the full packet will fit within the forwarding devices
|
||||
* MTU. We provide no support for fragmenting forwarded packets.
|
||||
*/
|
||||
|
||||
if (NET_LL_HDRLEN(fwddev) + dev->d_len > NET_DEV_MTU(fwddev))
|
||||
{
|
||||
nwarn("WARNING: Packet > MTU... Dropping\n");
|
||||
ret = -EFBIG;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get a pre-allocated forwarding structure, This structure will be
|
||||
* completely zeroed when we receive it.
|
||||
*/
|
||||
@@ -246,6 +257,10 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
|
||||
*
|
||||
* Remember that the size of the L1 header has already been subtracted
|
||||
* from dev->d_len.
|
||||
*
|
||||
* REVISIT: Consider an alternative design that does not require data
|
||||
* copying. This would require a pool of d_buf's that are managed by
|
||||
* the network rather than the network device.
|
||||
*/
|
||||
|
||||
hdrsize = ipv6_hdrsize(ipv6);
|
||||
@@ -258,7 +273,7 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
|
||||
|
||||
/* Save the entire L2 and L3 headers in the state structure */
|
||||
|
||||
if (hdrsize > sizeof(union ip_fwdhdr_u))
|
||||
if (hdrsize > sizeof(union fwd_iphdr_u))
|
||||
{
|
||||
nwarn("WARNING: Header is too big for pre-allocated structure\n");
|
||||
ret = -E2BIG;
|
||||
@@ -278,7 +293,12 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
|
||||
payload = (FAR uint8_t *)ipv6 + hdrsize;
|
||||
paysize = dev->d_len - hdrsize;
|
||||
|
||||
/* If there is a payload, then copy it into an IOB chain */
|
||||
/* If there is a payload, then copy it into an IOB chain.
|
||||
*
|
||||
* REVISIT: Consider an alternative design that does not require data
|
||||
* copying. This would require a pool of d_buf's that are managed by
|
||||
* the network rather than the network device.
|
||||
*/
|
||||
|
||||
if (paysize > 0)
|
||||
{
|
||||
@@ -308,16 +328,21 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP
|
||||
case IP_PROTO_TCP:
|
||||
{
|
||||
/* Forward a TCP packet, handling ACKs, windowing, etc. */
|
||||
/* Forward a TCP packet. */
|
||||
|
||||
ret = tcp_ipv6_dev_forward(fwd);
|
||||
ret = tcp_forward(fwd);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -327,7 +352,7 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
|
||||
{
|
||||
/* Forward a UDP packet */
|
||||
|
||||
ret = udp_ipv6_dev_forward(fwd);
|
||||
ret = udp_forward(fwd);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -337,7 +362,7 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
|
||||
{
|
||||
/* Forward an ICMPv6 packet */
|
||||
|
||||
ret = icmpv6_dev_forward(fwd);
|
||||
ret = icmpv6_forward(fwd);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -428,7 +453,7 @@ static int ipv6_decr_ttl(FAR struct ipv6_hdr_s *ipv6)
|
||||
* Name: ipv6_dropstats
|
||||
*
|
||||
* Description:
|
||||
* Update statistics for a droped packet.
|
||||
* Update statistics for a dropped packet.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipv6 - A convenience pointer to the IPv6 header in within the IPv6
|
||||
|
||||
Reference in New Issue
Block a user