IP forwarding. Adds a little more structure to handle passing packets received on one network device to another network device. Logic is still incomplete.

This commit is contained in:
Gregory Nutt 2017-07-04 10:19:52 -06:00
parent 59cb2a280b
commit c0c275c8fc
16 changed files with 854 additions and 163 deletions

View File

@ -99,7 +99,26 @@
* Public Type Definitions
****************************************************************************/
/* The ICMP and IP headers */
struct icmp_hdr_s
{
/* ICMP header */
uint8_t type; /* Defines the format of the ICMP message */
uint8_t icode; /* Further qualifies the ICMP messsage */
uint16_t icmpchksum; /* Checksum of ICMP header and data */
/* All ICMP packets have an 8-byte header and variable-sized data section.
* The first 4 bytes of the header have fixed format, while the last 4 bytes
* depend on the type/code of that ICMP packet.
*/
/* ICMP_ECHO_REQUEST and ICMP_ECHO_REPLY data */
uint16_t id; /* Used to match requests with replies */
uint16_t seqno; /* " " "" " " " " " " " " */
};
/* The ICMP and IPv4 headers */
struct icmp_iphdr_s
{
@ -122,8 +141,9 @@ struct icmp_iphdr_s
uint8_t icode; /* Further qualifies the ICMP messsage */
uint16_t icmpchksum; /* Checksum of ICMP header and data */
/* Data following the ICMP header contains the data specific to the
* message type indicated by the Type and Code fields.
/* All ICMP packets have an 8-byte header and variable-sized data section.
* The first 4 bytes of the header have fixed format, while the last 4 bytes
* depend on the type/code of that ICMP packet.
*/
/* ICMP_ECHO_REQUEST and ICMP_ECHO_REPLY data */

View File

@ -95,9 +95,16 @@
# define TCP_STOPPED 0x10 /* Bit 4: stopped */
/* Bit 5-7: Unused, but not available */
/* TCP header sizes */
/* TCP header sizes
*
* The minimum size header is 5 words and the maximum is 15 words thus
* giving the minimum size of 20 bytes and maximum of 60 bytes, allowing for
* up to 40 bytes of options in the header.
*/
#define TCP_HDRLEN 20 /* Size of TCP header */
#define TCP_HDRLEN 20 /* Size of TCP header (minimum) */
#define TCP_OPT_HDRLEN(n) (20 + ((n) << 2)) /* Size of TCP header w/options */
#define TCP_MAX_HDRLEN 60 /* Maximum size of TCP header */
#ifdef CONFIG_NET_IPv4
# define IPv4TCP_HDRLEN (TCP_HDRLEN + IPv4_HDRLEN) /* Size of IPv4 + TCP header */

View File

@ -299,6 +299,23 @@ config NET_IPFORWARD
reason why IPv4 forwarding has not been implemented, it just has
not yet been done.
config NET_IPFORWARD_NSTRUCT
int "Number of pre-allocated forwarding structures"
default 4
depends on NET_IPFORWARD && CONFIG_NETDEV_MULTINIC
---help---
When packets are forward from on device to another, a structure must
be allocated to hold the state of forwarding across several
asynchronous events. Those structures are pre-allocated for
minimal, deterministic performance and to prevent hogging of memory
(of course, that means that this value must be carefully selected
for your application). This setting defines the number of such pre-
allocated structures.
NOTE: This setting effectively puts a maximum on the number of
packets that may be waiting to be forwarded from one network device
to another.
endmenu # Internet Protocol Selection
source "net/socket/Kconfig"

View File

@ -51,6 +51,12 @@ NET_CSRCS += ipv6_forward.c
endif
endif
ifeq ($(CONFIG_NET_IPFORWARD),y)
ifeq ($(CONFIG_NETDEV_MULTINIC),y)
NET_CSRCS += ip_forward.c
endif
endif
# I/O buffer chain support required?
ifeq ($(CONFIG_MM_IOB),y)

View File

@ -1,7 +1,7 @@
/****************************************************************************
* net/devif/devif_initialize.c
*
* Copyright (C) 2007-2011, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2011, 2014, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
@ -50,6 +50,7 @@
#include <nuttx/net/netstats.h>
#include <nuttx/net/ip.h>
#include "devif/ip_forward.h"
#include "devif/devif.h"
/****************************************************************************
@ -167,5 +168,11 @@ void devif_initialize(void)
/* Initialize callback support */
devif_callback_init();
#ifdef HAVE_FWDALLOC
/* Initialize IP forwarding support */
ip_forward_initialize();
#endif
}
#endif /* CONFIG_NET */

139
net/devif/ip_forward.c Normal file
View File

@ -0,0 +1,139 @@
/****************************************************************************
* net/devif/ip_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. 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 <string.h>
#include <debug.h>
#include <errno.h>
#include "devif/ip_forward.h"
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NETDEV_MULTINIC)
/****************************************************************************
* Private Data
****************************************************************************/
/* This is an array of pre-allocating forwarding structures */
static struct forward_s g_fwdpool[CONFIG_NET_IPFORWARD_NSTRUCT];
/* This is a list of free forwarding structures */
static FAR struct forward_s *g_fwdfree;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ip_forward_initialize
*
* Description:
* Initialize the struct forward_s allocator.
*
* Assumptions:
* Called early in system initialization.
*
****************************************************************************/
void ip_forward_initialize(void)
{
FAR struct forward_s *fwd;
int i;
/* Add all pre-allocated forwarding structures to the free list */
g_fwdfree = NULL;
for (i = 0; i < CONFIG_NET_IPFORWARD_NSTRUCT; i++)
{
fwd = &g_fwdpool[i];
fwd->f_flink = g_fwdfree;
g_fwdfree = fwd;
}
}
/****************************************************************************
* Name: ip_forward_alloc
*
* Description:
* Allocate a forwarding structure by removing a pre-allocated entry from
* a free list.
*
* Assumptions:
* Caller holds the network lock. Mutually excluvive access to the free
* list is assured by this lock.
*
****************************************************************************/
FAR struct forward_s *ip_forward_alloc(void)
{
FAR struct forward_s *fwd;
fwd = g_fwdfree;
if (fwd != NULL)
{
g_fwdfree = fwd->f_flink;
memset (fwd, 0, sizeof(struct forward_s));
}
return fwd;
}
/****************************************************************************
* Name: ip_forward_free
*
* Description:
* Free a forwarding structure by adding it to a free list.
*
* Assumptions:
* Caller holds the network lock. Mutually excluvive access to the free
* list is assured by this lock.
*
****************************************************************************/
void ip_forward_free(FAR struct forward_s *fwd)
{
fwd->f_flink = g_fwdfree;
g_fwdfree = fwd;
}
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NETDEV_MULTINIC */

186
net/devif/ip_forward.h Normal file
View File

@ -0,0 +1,186 @@
/****************************************************************************
* net/devif/ip_forward.h
*
* 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.
*
****************************************************************************/
#ifndef __NET_DEVIF_IP_FORWARD_H
#define __NET_DEVIF_IP_FORWARD_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <nuttx/net/ip.h>
#include <nuttx/net/udp.h>
#include <nuttx/net/tcp.h>
#include <nuttx/net/icmpv6.h>
#undef HAVE_FWDALLOC
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NETDEV_MULTINIC)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define HAVE_FWDALLOC 1
#ifndef CONFIG_NET_IPFORWARD_NSTRUCT
# define CONFIG_NET_IPFORWARD_NSTRUCT 4
#endif
/****************************************************************************
* Public Types
****************************************************************************/
/* IPv4 + L2 header */
#ifdef CONFIG_NET_IPv4
struct ipv6_fwdhdr_s
{
struct ipv4_hdr_s l2;
union
{
#ifdef CONFIG_NET_TCP
uint8_t pad[TCP_MAX_HDRLEN];
struct tcp_hdr_s tcp;
#endif
#ifdef CONFIG_NET_UDP
struct udp_hdr_s udp;
#endif
#ifdef CONFIG_NET_ICMPv6
struct icmp_hdr_s icmp;
#endif
} l3;
};
#endif
/* IPv6 + L2 header */
#ifdef CONFIG_NET_IPv6
struct ipv6_fwdhdr_s
{
struct ipv6_hdr_s l2;
union
{
#ifdef CONFIG_NET_TCP
uint8_t pad[TCP_MAX_HDRLEN];
struct tcp_hdr_s tcp;
#endif
#ifdef CONFIG_NET_UDP
struct udp_hdr_s udp;
#endif
#ifdef CONFIG_NET_ICMPv6
struct icmpv6_hdr_s icmpv6;
#endif
} l3;
};
#endif
/* IPv4 or IPv6 + L2 header */
union ip_fwdhdr_u
{
#ifdef CONFIG_NET_IPv4
struct ipv4_fwdhdr_s ipv4;
#endif
#ifdef CONFIG_NET_IPv6
struct ipv6_fwdhdr_s ipv6;
#endif
};
/* This is the send state structure */
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 */
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: ip_forward_initialize
*
* Description:
* Initialize the struct forward_s allocator.
*
* Assumptions:
* Called early in system initialization.
*
****************************************************************************/
void ip_forward_initialize(void);
/****************************************************************************
* Name: ip_forward_alloc
*
* Description:
* Allocate a forwarding structure by removing a pre-allocated entry from
* a free list.
*
* Assumptions:
* Caller holds the network lock. Mutually excluvive access to the free
* list is assured by this lock.
*
****************************************************************************/
FAR struct forward_s *ip_forward_alloc(void);
/****************************************************************************
* Name: ip_forward_free
*
* Description:
* Free a forwarding structure by adding it to a free list.
*
* Assumptions:
* Caller holds the network lock. Mutually excluvive access to the free
* list is assured by this lock.
*
****************************************************************************/
void ip_forward_free(FAR struct forward_s *fwd);
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NETDEV_MULTINIC */
#endif /* __NET_DEVIF_IP_FORWARD_H */

View File

@ -39,6 +39,7 @@
#include <nuttx/config.h>
#include <string.h>
#include <debug.h>
#include <errno.h>
@ -49,45 +50,14 @@
#include "netdev/netdev.h"
#include "sixlowpan/sixlowpan.h"
#include "udp/udp.h"
#include "tcp/tcp.h"
#include "icmpv6/icmpv6.h"
#include "devif/ip_forward.h"
#include "devif/devif.h"
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6)
/****************************************************************************
* Private Types
****************************************************************************/
#if defined(CONFIG_NETDEV_MULTINIC) && \
(defined(CONFIG_NET_UDP) || defined(CONFIG_NET_ICMPv6))
/* IPv6 + UDP or ICMPv6 header */
struct ipv6l3_hdr_s
{
struct ipv6_hdr_s ipv6;
union
{
#ifdef CONFIG_NET_UDP
struct udp_hdr_s udp;
#endif
#ifdef CONFIG_NET_ICMPv6
struct icmpv6_iphdr_s icmp;
#endif
} u;
};
/* This is the send state structure */
struct forward_s
{
FAR struct net_driver_s *dev; /* Forwarding device */
struct ipv6l3_hdr_s hdr; /* Copy of origin L2+L3 headers */
FAR struct iob_queue_s iobq; /* IOBs contained the data payload */
};
#endif /* CONFIG_NETDEV_MULTINIC && (CONFIG_NET_UDP || CONFIG_NET_ICMPv6) */
/****************************************************************************
* Private Functions
****************************************************************************/
@ -218,50 +188,188 @@ static int ipv6_hdrsize(FAR struct ipv6_hdr_s *ipv6)
* Name: ipv6_dev_forward
*
* Description:
* Set up to forward the UDP or 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.
* This function is called from ipv6_forward when it is necessary to
* forward a packet from the current device to different device. In this
* case, the forwarding operation must be performed asynchronously when
* the TX poll is received from the forwarding device.
*
* Input Parameters:
* dev - The device on which the packet should be forwarded.
* ipv6 - A pointer to the IPv6 header in within the IPv6 packet. This
* is immeidately followed by the L3 header which may be UDP or
* ICMPv6.
* iob - A list of IOBs containing the data payload to be sent.
* dev - The device on which the packet was received and which
* contains the IPv6 packet.
* fwdddev - The device on which the packet must be forwarded.
* ipv6 - A pointer to the IPv6 header in within the IPv6 packet
*
* Returned Value:
* Zero is returned if the packet was successfully forwarded; A negated
* Zero is returned if the packet was successfully forward; 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.
* latter case, the caller (ipv6_input()) should drop the packet.
*
****************************************************************************/
#if defined(CONFIG_NETDEV_MULTINIC) && \
(defined(CONFIG_NET_UDP) || defined(CONFIG_NET_ICMPv6))
#ifdef CONFIG_NETDEV_MULTINIC
static int ipv6_dev_forward(FAR struct net_driver_s *dev,
FAR struct ipv6_hdr_s *ipv6,
FAR struct iob_s *iob)
FAR struct net_driver_s *fwddev,
FAR struct ipv6_hdr_s *ipv6)
{
/* Notify the forwarding device that TX data is available */
FAR struct forward_s *fwd = NULL;
int hdrsize;
int ret;
/* Set up to send the packet when the selected device polls for TX data. */
/* Perform any necessary packet conversions. */
#warning Missing logic
ret = ipv6_packet_conversion(dev, fwddev, ipv6);
if (ret < 0)
{
FAR uint8_t *payload;
unsigned int paysize;
/* REVISIT: For Ethernet we may have to fix up the Ethernet header:
* - source MAC, the MAC of the current device.
* - dest MAC, the MAC associated with the destination IPv6 adress.
* This will involve ICMPv6 and Neighbor Discovery.
*/
/* Get a pre-allocated forwarding structure, This structure will be
* completely zeroed when we receive it.
*/
nwarn("WARNING: UPD/ICMPv6 packet forwarding not yet supported\n");
return -ENOSYS;
}
#else
# define ipv6_dev_forward(dev,ipv6,iob) -EPROTONOSUPPORT
fwd = ip_forward_alloc();
if (fwd == NULL)
{
nwarn("WARNING: Failed to allocate forwarding structure\n");
ret = -ENOMEM;
goto errout;
}
/* Initialize the easy stuff in the forwarding structure */
fwd->f_dev = fwddev; /* Forwarding device */
/* Get the size of the IPv6 + L3 header. Use this to determine start
* of the data payload.
*
* Remember that the size of the L1 header has already been subtracted
* from dev->d_len.
*/
hdrsize = ipv6_hdrsize(ipv6);
if (hdrsize < IPv6_HDRLEN)
{
nwarn("WARNING: Could not determine L2+L3 header size\n");
ret = -EPROTONOSUPPORT;
goto errout_with_fwd;
}
/* Save the entire L2 and L3 headers in the state structure */
if (hdrsize > sizeof(union ip_fwdhdr_u))
{
nwarn("WARNING: Header is too big for pre-allocated structure\n");
ret = -E2BIG;
goto errout_with_fwd;
}
memcpy(&fwd->f_hdr, ipv6, hdrsize);
fwd->f_hdrsize = hdrsize;
/* Use the L2 + L3 header size to determine start and size of the data
* payload.
*
* Remember that the size of the L1 header has already been subtracted
* from dev->d_len.
*/
payload = (FAR uint8_t *)ipv6 + hdrsize;
paysize = dev->d_len - hdrsize;
/* If there is a payload, then copy it into an IOB chain */
if (paysize > 0)
{
/* Try to allocate the head of an IOB chain. If this fails,
* the the packet will be dropped; we are not operating in a
* context where waiting for an IOB is a good idea
*/
fwd->f_iob = iob_tryalloc(false);
if (fwd->f_iob == NULL)
{
nwarn("WARNING: iob_tryalloc() failed\n");
ret = -ENOMEM;
goto errout_with_fwd;
}
/* Copy the packet data payload into an IOB chain.
* iob_trycopin() will not wait, but will fail there are no
* available IOBs.
*/
ret = iob_trycopyin(fwd->f_iob, payload, paysize, 0, false);
if (ret < 0)
{
nwarn("WARNING: iob_trycopyin() failed: %d\n", ret);
goto errout_with_iobchain;
}
}
/* Then set up to forward the packet according to the protocol */
switch (ipv6->proto)
{
#ifdef CONFIG_NET_TCP
case IP_PROTO_TCP:
{
/* Forward a TCP packet, handling ACKs, windowing, etc. */
ret = tcp_ipv6_dev_forward(fwd);
}
break;
#endif
#ifdef CONFIG_NET_UDP
case IP_PROTO_UDP:
{
/* Forward a UDP packet */
ret = udp_ipv6_dev_forward(fwd);
}
break;
#endif
#ifdef CONFIG_NET_ICMPv6
case IP_PROTO_ICMP6:
{
/* Forward an ICMPv6 packet */
ret = icmpv6_dev_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:
if (fwd != NULL && fwd->f_iob != NULL)
{
iob_free_chain(fwd->f_iob);
}
errout_with_fwd:
if (fwd != NULL)
{
ip_forward_free(fwd);
}
errout:
return ret;
}
#endif /* CONFIG_NETDEV_MULTINIC */
/****************************************************************************
* Name: ipv6_decr_ttl
*
@ -435,86 +543,12 @@ int ipv6_forward(FAR struct net_driver_s *dev, FAR struct ipv6_hdr_s *ipv6)
if (fwddev != dev)
{
/* Perform any necessary packet conversions. */
/* Send the packet asynchrously on the forwarding device. */
ret = ipv6_packet_conversion(dev, fwddev, ipv6);
ret = ipv6_dev_forward(dev, fwddev, ipv6);
if (ret < 0)
{
FAR struct iob_s *iob = NULL;
FAR uint8_t *payload;
unsigned int paysize;
int hdrsize;
/* Get the size of the IPv6 + L3 header. Use this to determine
* start of the data payload.
*
* Remember that the size of the L1 header has already been
* subtracted from dev->d_len.
*/
hdrsize = ipv6_hdrsize(ipv6);
if (hdrsize < 0)
{
ret = -EPROTONOSUPPORT;
goto drop;
}
payload = (FAR uint8_t *)ipv6 + hdrsize;
paysize = dev->d_len - hdrsize;
if (paysize > 0)
{
/* Try to allocate the head of an IOB chain. If this fails,
* the the packet will be dropped; we are not operating in a
* context where waiting for an IOB is a good idea
*/
iob = iob_tryalloc(false);
if (iob == NULL)
{
ret = -ENOMEM;
goto drop;
}
/* Copy the packet data payload into an IOB chain.
* iob_trycopin() will not wait, but will fail there are no
* available IOBs.
*/
ret = iob_trycopyin(iob, payload, paysize, 0, false);
if (ret < 0)
{
iob_free_chain(iob);
goto drop;
}
}
/* Then set up to forward the packet */
#ifdef CONFIG_NET_TCP
if (ipv6->proto == IP_PROTO_TCP)
{
/* Forward a TCP packet, handling ACKs, windowing, etc. */
ret = tcp_ipv6_forward(fwddev, ipv6, iob);
}
else
#endif
{
/* Forward a UDP or ICMPv6 packet. Because ipv6_hdrsize() succeeded,
* we know that it is a forward-able type.
*/
ret = ipv6_dev_forward(fwddev, ipv6, iob);
}
if (ret < 0)
{
goto drop;
}
dev->d_len = 0;
return OK;
goto drop;
}
}
else
@ -522,7 +556,11 @@ int ipv6_forward(FAR struct net_driver_s *dev, FAR struct ipv6_hdr_s *ipv6)
#if defined(CONFIG_NET_6LOWPAN) /* REVISIT: Currently only suport for 6LoWPAN */
{
/* Single network device */
/* Single network device. The use case here is where an endpoint acts
* as a hub in a star configuration. This is typical for a wireless star
* configuration where not all endpoints are accessible from all other
* endpoints, but seems less useful for a wired network.
*/
/* Perform any necessary packet conversions. If the packet was handled
* via a backdoor path (or dropped), then dev->d_len will be zero. If
@ -545,18 +583,21 @@ int ipv6_forward(FAR struct net_driver_s *dev, FAR struct ipv6_hdr_s *ipv6)
/* Nothing other 6LoWPAN forwarding is currently handled and that
* case was dealt with in ipv6_packet_conversion().
*
* REVISIT: Is tht an issue? Do other use cases make sense?
*/
# warning Missing logic
nwarn("WARNING: Packet forwarding supported only for 6LoWPAN\n");
return -ENOSYS;
ret = -ENOSYS;
goto drop;
}
}
#else /* CONFIG_NET_6LOWPAN */
{
nwarn("WARNING: Packet forwarding not supported in this configuration\n");
return -ENOSYS;
ret = -ENOSYS;
goto drop;
}
#endif /* CONFIG_NET_6LOWPAN */

View File

@ -62,6 +62,13 @@ endif
ifeq ($(CONFIG_NET_ICMPv6_ROUTER),y)
NET_CSRCS += icmpv6_radvertise.c
endif
# IP forwarding
ifeq ($(CONFIG_NET_IPFORWARD),y)
NET_CSRCS += icmpv6_forward.c
endif
# Include ICMPv6 build support
DEPPATH += --dep-path icmpv6

View File

@ -176,6 +176,34 @@ int icmpv6_neighbor(const net_ipv6addr_t ipaddr);
# define icmpv6_neighbor(i) (0)
#endif
/****************************************************************************
* Name: icmpv6_dev_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_dev_forward(FAR struct forward_s *fwd);
#endif
/****************************************************************************
* Name: icmpv6_poll
*

View File

@ -0,0 +1,98 @@
/****************************************************************************
* 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 <errno.h>
#include <debug.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/ip.h>
#include "devif/ip_forward.h"
#include "icmpv6/icmpv6.h"
#if defined(CONFIG_NET) && defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_ICMPv6)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: icmpv6_dev_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_ICMPv6)
int icmpv6_dev_forward(FAR struct forward_s *fwd)
{
/* Set up to send the packet when the selected device polls for TX data. */
/* Notify the forwarding device that TX data is available */
#warning Missing logic
/* REVISIT: For Ethernet we may have to fix up the Ethernet header:
* - source MAC, the MAC of the current device.
* - dest MAC, the MAC associated with the destination IPv6 adress.
* This will involve ICMPv6 and Neighbor Discovery.
*/
nwarn("WARNING: UPD/ICMPv6 packet forwarding not yet supported\n");
return -ENOSYS;
}
#endif /* CONFIG_NET_ICMPv6 && CONFIG_NETDEV_MULTINIC */
#endif /* CONFIG_NET && CONFIG_NET_IPFORWARD && CONFIG_NET_ICMPv6 */

View File

@ -795,19 +795,20 @@ void tcp_send(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
uint16_t flags, uint16_t len);
/****************************************************************************
* Name: tcp_ipv6_forward
* Name: tcp_ipv6_dev_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:
* dev - The device on which the packet should be forwarded.
* ipv6 - A pointer to the IPv6 header in within the IPv6 packet. This
* is immeidately followed by the TCP header.
* iob - A list of IOBs containing the data payload to be sent.
* 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
@ -818,8 +819,8 @@ void tcp_send(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_IPv6) && \
defined(CONFIG_NETDEV_MULTINIC)
int tcp_ipv6_forward(FAR struct net_driver_s *dev,
FAR struct ipv6_hdr_s *ipv6, FAR struct iob_s *iob);
struct forward_s; /* Forward reference */
int tcp_ipv6_dev_forward(FAR struct forward_s *fwd);
#endif
/****************************************************************************

View File

@ -44,6 +44,7 @@
#include <nuttx/net/netdev.h>
#include <nuttx/net/ip.h>
#include "devif/ip_forward.h"
#include "tcp/tcp.h"
#if defined(CONFIG_NET) && defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_TCP)
@ -53,19 +54,20 @@
****************************************************************************/
/****************************************************************************
* Name: tcp_ipv6_forward
* Name: tcp_ipv6_dev_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:
* dev - The device on which the packet should be forwarded.
* ipv6 - A pointer to the IPv6 header in within the IPv6 packet. This
* is immeidately followed by the TCP header.
* iob - A list of IOBs containing the data payload to be sent.
* 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
@ -75,8 +77,7 @@
****************************************************************************/
#if defined(CONFIG_NET_IPv6) && defined(CONFIG_NETDEV_MULTINIC)
int tcp_ipv6_forward(FAR struct net_driver_s *dev,
FAR struct ipv6_hdr_s *ipv6, FAR struct iob_s *iob)
int tcp_ipv6_dev_forward(FAR struct forward_s *fwd)
{
/* Notify the forwarding device that TX data is available */

View File

@ -48,6 +48,12 @@ NET_CSRCS += udp_netpoll.c
endif
endif
# IP forwarding
ifeq ($(CONFIG_NET_IPFORWARD),y)
NET_CSRCS += udp_forward.c
endif
# Transport layer
NET_CSRCS += udp_conn.c udp_devpoll.c udp_send.c udp_input.c udp_finddev.c

View File

@ -428,6 +428,35 @@ 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_ipv6_dev_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_ipv6_dev_forward(FAR struct forward_s *fwd);
#endif
/****************************************************************************
* Name: psock_udp_send
*

98
net/udp/udp_forward.c Normal file
View File

@ -0,0 +1,98 @@
/****************************************************************************
* net/udp/udp_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 <errno.h>
#include <debug.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/ip.h>
#include "devif/ip_forward.h"
#include "udp/udp.h"
#if defined(CONFIG_NET) && defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_UDP)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: udp_ipv6_dev_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_IPv6) && defined(CONFIG_NETDEV_MULTINIC)
int udp_ipv6_dev_forward(FAR struct forward_s *fwd)
{
/* Set up to send the packet when the selected device polls for TX data. */
/* Notify the forwarding device that TX data is available */
#warning Missing logic
/* REVISIT: For Ethernet we may have to fix up the Ethernet header:
* - source MAC, the MAC of the current device.
* - dest MAC, the MAC associated with the destination IPv6 adress.
* This will involve ICMPv6 and Neighbor Discovery.
*/
nwarn("WARNING: UPD/ICMPv6 packet forwarding not yet supported\n");
return -ENOSYS;
}
#endif /* CONFIG_NET_IPv6 && CONFIG_NETDEV_MULTINIC */
#endif /* CONFIG_NET && CONFIG_NET_IPFORWARD && CONFIG_NET_UDP */