IP forwarding: Flesh out TCP, UDP, and ICMPv6 packet forwarding logic.

This commit is contained in:
Gregory Nutt 2017-07-05 11:01:16 -06:00
parent 65c3fa6375
commit 31f832d8c5
20 changed files with 1102 additions and 162 deletions

View file

@ -883,8 +883,8 @@ Click Shield
D2 PA5 microBUS1 GPIO interrupt input PA5
D3 PA6 microBUS2 GPIO interrupt input PA6
D4 PD27 *** Not used ***
D5 PD11 microBUS2 PWM PD11 PWMC0_H0
D6 PC19 microBUS1 PWN PC19 PWMC0_H2
D5 PD11 microBUS2 PWMB PD11 PWMC0_H0
D6 PC19 microBUS1 PWMA PC19 PWMC0_H2
D7 PA2 *** Not used ***
D8 PA17 *** Not used ***
D9 PC9 microBUS2 CS GPIO output PC9

View file

@ -1486,8 +1486,8 @@ Click Shield
D2 PA5 microBUS1 GPIO interrupt input PA5
D3 PA6 microBUS2 GPIO interrupt input PA6
D4 PD27 *** Not used ***
D5 PD11 microBUS2 PWM PD11 PWMC0_H0
D6 PC19 microBUS1 PWN PC19 PWMC0_H2
D5 PD11 microBUS2 PWMB PD11 PWMC0_H0
D6 PC19 microBUS1 PWMA PC19 PWMC0_H2
D7 PA2 *** Not used ***
D8 PA17 *** Not used ***
D9 PC9 microBUS2 CS GPIO output PC9

View file

@ -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

102
net/devif/devif_forward.c Normal file
View file

@ -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 */

View file

@ -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
****************************************************************************/

View file

@ -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.
*
****************************************************************************/

View file

@ -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 */

View file

@ -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

View file

@ -66,8 +66,10 @@ endif
# IP forwarding
ifeq ($(CONFIG_NET_IPFORWARD),y)
ifeq ($(CONFIG_NETDEV_MULTINIC),y)
NET_CSRCS += icmpv6_forward.c
endif
endif
# Include ICMPv6 build support

View file

@ -55,8 +55,10 @@
/* Allocate a new ICMPv6 data callback */
#define icmpv6_callback_alloc(dev) devif_callback_alloc(dev, &(dev)->d_conncb)
#define icmpv6_callback_free(dev,cb) devif_dev_callback_free(dev, cb)
#define icmpv6_callback_alloc(dev) \
devif_callback_alloc((dev), &(dev)->d_conncb)
#define icmpv6_callback_free(dev,cb) \
devif_dev_callback_free((dev), (cb))
/****************************************************************************
* Public Type Definitions
@ -177,7 +179,7 @@ int icmpv6_neighbor(const net_ipv6addr_t ipaddr);
#endif
/****************************************************************************
* Name: icmpv6_dev_forward
* Name: icmpv6_forward
*
* Description:
* Called by the IP forwarding logic when an ICMPv6 packet is received on
@ -201,7 +203,7 @@ int icmpv6_neighbor(const net_ipv6addr_t ipaddr);
#if defined(CONFIG_NETDEV_MULTINIC) && defined(CONFIG_NET_IPFORWARD)
struct forward_s;
int icmpv6_dev_forward(FAR struct forward_s *fwd);
int icmpv6_forward(FAR struct forward_s *fwd);
#endif
/****************************************************************************

View file

@ -37,30 +37,251 @@
#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/netdev.h>
#include <nuttx/net/ip.h>
#include <nuttx/net/netstats.h>
#include "devif/ip_forward.h"
#include "devif/devif.h"
#include "netdev/netdev.h"
#include "icmpv6/icmpv6.h"
#if defined(CONFIG_NET) && defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_ICMPv6)
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_ICMPv6) && \
defined(CONFIG_NETDEV_MULTINIC)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: icmpv6_dev_forward
* Name: icmpv6_forward_addrchck
*
* Description:
* Called by the IP forwarding logic when an ICMPv6 packet is received on
* 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:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_ETHERNET
static inline bool icmpv6_forward_addrchck(FAR struct forward_s *fwd)
{
#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
if (conn->domain == PF_INET)
#endif
{
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
return (arp_find(fwd->f_hdr.ipv4.l2.destipaddr) != 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(fwd->f_hdr.ipv6.l2.destipaddr) != NULL);
#else
return true;
#endif
}
#endif /* CONFIG_NET_IPv6 */
}
#else /* CONFIG_NET_ETHERNET */
# define icmpv6_forward_addrchck(r) (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 void icmpv6_dropstats(FAR struct forward_s *fwd)
{
/* Increment the count of dropped ICMPV6 packets */
g_netstats.icmpv6.drop++;
/* Increment the count of dropped IPv4 or IPv6 packets */
#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
if ((fwd->f_hdr.ipv4.l2.vhl & IP_VERSION_MASK) == IPv4_VERSION)
#endif
{
g_netstats.ipv4.drop++;
}
#endif
#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
else
#endif
{
g_netstats.ipv6.drop++;
}
#endif
}
#else
# define icmpv6_dropstats(ipv6)
#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);
/* 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 */
ip_forward_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. The
* 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.
@ -76,23 +297,26 @@
*
****************************************************************************/
#if defined(CONFIG_NETDEV_MULTINIC) && defined(CONFIG_NET_ICMPv6)
int icmpv6_dev_forward(FAR struct forward_s *fwd)
int icmpv6_forward(FAR struct forward_s *fwd)
{
/* Set up to send the packet when the selected device polls for TX data. */
DEBUGASSERT(fwd != NULL && fwd->f_dev != NULL);
/* Notify the forwarding device that TX data is available */
/* Set up the callback in the connection */
#warning Missing logic
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;
/* 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.
*/
/* Notify the device driver of the availability of TX data */
nwarn("WARNING: UPD/ICMPv6 packet forwarding not yet supported\n");
return -ENOSYS;
netdev_txnotify_dev(fwd->f_dev);
return OK;
}
return -EBUSY;
}
#endif /* CONFIG_NET_ICMPv6 && CONFIG_NETDEV_MULTINIC */
#endif /* CONFIG_NET && CONFIG_NET_IPFORWARD && CONFIG_NET_ICMPv6 */
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NET_ICMPv6 && CONFIG_NETDEV_MULTINIC */

View file

@ -314,7 +314,7 @@ int icmpv6_neighbor(const net_ipv6addr_t ipaddr)
(void)sem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
sem_setprotocol(&state.snd_sem, SEM_PRIO_NONE);
state.snd_retries = 0; /* No retries yet */
state.snd_retries = 0; /* No retries yet */
net_ipv6addr_copy(state.snd_ipaddr, lookup); /* IP address to query */
#ifdef CONFIG_NETDEV_MULTINIC

View file

@ -1,7 +1,7 @@
############################################################################
# net/tcp/Make.defs
#
# Copyright (C) 2014 Gregory Nutt. All rights reserved.
# Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@ -63,8 +63,10 @@ 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

View file

@ -71,18 +71,18 @@
*/
# define tcp_callback_alloc(conn) \
devif_callback_alloc(conn->dev, &conn->list)
devif_callback_alloc((conn)->dev, &(conn)->list)
# define tcp_callback_free(conn,cb) \
devif_conn_callback_free(conn->dev, cb, &conn->list)
devif_conn_callback_free((conn)->dev, (cb), &(conn)->list)
/* These macros allocate and free callback structures used for receiving
* notifications of device-related events.
*/
# define tcp_monitor_callback_alloc(conn) \
devif_callback_alloc(conn->dev, NULL)
devif_callback_alloc((conn)->dev, NULL)
# define tcp_monitor_callback_free(conn,cb) \
devif_conn_callback_free(conn->dev, cb, NULL)
devif_conn_callback_free((conn)->dev, (cb), NULL)
#else
/* These macros allocate and free callback structures used for receiving
@ -90,9 +90,9 @@
*/
# define tcp_callback_alloc(conn) \
devif_callback_alloc(g_netdevices, &conn->list)
devif_callback_alloc(g_netdevices, &(conn)->list)
# define tcp_callback_free(conn,cb) \
devif_conn_callback_free(g_netdevices, cb, &conn->list)
devif_conn_callback_free(g_netdevices, (cb), &(conn)->list)
/* These macros allocate and free callback structures used for receiving
* notifications of device-related events.
@ -101,7 +101,7 @@
# define tcp_monitor_callback_alloc(conn) \
devif_callback_alloc(g_netdevices, NULL)
# define tcp_monitor_callback_free(conn,cb) \
devif_conn_callback_free(g_netdevices, cb, NULL)
devif_conn_callback_free(g_netdevices, (cb), NULL)
#endif
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
@ -795,7 +795,7 @@ void tcp_send(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
uint16_t flags, uint16_t len);
/****************************************************************************
* Name: tcp_ipv6_dev_forward
* Name: tcp_forward
*
* Description:
* Called by the IP forwarding logic when an TCP packet is received on
@ -820,7 +820,7 @@ 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)
struct forward_s; /* Forward reference */
int tcp_ipv6_dev_forward(FAR struct forward_s *fwd);
int tcp_forward(FAR struct forward_s *fwd);
#endif
/****************************************************************************

View file

@ -37,32 +37,316 @@
#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/netdev.h>
#include <nuttx/net/ip.h>
#include <nuttx/net/netstats.h>
#include "devif/ip_forward.h"
#include "devif/devif.h"
#include "netdev/netdev.h"
#include "tcp/tcp.h"
#if defined(CONFIG_NET) && defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_TCP)
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_TCP) && \
defined(CONFIG_NETDEV_MULTINIC)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: tcp_ipv6_dev_forward
* 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_conn.tcp.domain == PF_INET)
{
/* Select the IPv4 domain */
tcp_ipv4_select(dev);
}
else /* if (conn->domain == PF_INET6) */
{
/* Select the IPv6 domain */
DEBUGASSERT(conn->domain == PF_INET6);
tcp_ipv6_select(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:
* None
*
* 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;
#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
if (conn->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_conn.tcp.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);
/* 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(dev, 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 */
ip_forward_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
* 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:
@ -76,27 +360,68 @@
*
****************************************************************************/
#if defined(CONFIG_NET_IPv6) && defined(CONFIG_NETDEV_MULTINIC)
int tcp_ipv6_dev_forward(FAR struct forward_s *fwd)
int tcp_forward(FAR struct forward_s *fwd)
{
/* Notify the forwarding device that TX data is available */
DEBUGASSERT(fwd != NULL && fwd->f_dev != NULL);
FAR struct tcp_conn_s *conn = &fwd->f_conn.tcp;
/* Set up to send the packet when the selected device polls for TX data.
* TCP packets must obey ACK and windowing rules.
/* Set up some minimal connection structure so that we appear to be a
* real TCP connection.
*/
#warning Missing logic
conn->dev = fwd->f_dev;
/* 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.
* - Because of TCP window, the packet may have to be sent in smaller
* pieces.
*/
#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
if ((fwd->f_hdr.ipv4.l2.vhl & IP_VERSION_MASK) == IPv4_VERSION)
#endif
{
FAR struct ipv4_hdr_s *ipv4 = &fwd->f_hdr.ipv4.l2;
FAR struct tcp_hdr_s *tcp = &fwd->f_hdr.ipv4.l3.tcp;
nwarn("WARNING: TCP packet forwarding not yet supported\n");
return -ENOSYS;
#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 = &fwd->f_hdr.ipv6.l2;
FAR struct tcp_hdr_s *tcp = &fwd->f_hdr.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_IPv6 && CONFIG_NETDEV_MULTINIC */
#endif /* CONFIG_NET && CONFIG_NET_IPFORWARD && CONFIG_NET_TCP */
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NET_TCP && CONFIG_NETDEV_MULTINIC */

View file

@ -181,7 +181,7 @@ static inline int send_timeout(FAR struct send_s *pstate)
static inline void tcpsend_ipselect(FAR struct net_driver_s *dev,
FAR struct tcp_conn_s *conn)
{
/* Which domain the socket support */
/* Which domain does the socket support */
if (conn->domain == PF_INET)
{

View file

@ -51,8 +51,10 @@ endif
# IP forwarding
ifeq ($(CONFIG_NET_IPFORWARD),y)
ifeq ($(CONFIG_NETDEV_MULTINIC),y)
NET_CSRCS += udp_forward.c
endif
endif
# Transport layer

View file

@ -68,10 +68,10 @@
/* Allocate a new UDP data callback */
#define udp_callback_alloc(dev, conn) \
devif_callback_alloc(dev, &conn->list)
#define udp_callback_free(dev, conn,cb) \
devif_conn_callback_free(dev, cb, &conn->list)
#define udp_callback_alloc(dev,conn) \
devif_callback_alloc((dev), &(conn)->list)
#define udp_callback_free(dev,conn,cb) \
devif_conn_callback_free((dev), (cb), &(conn)->list)
/****************************************************************************
* Public Type Definitions
@ -429,7 +429,7 @@ uint16_t udp_callback(FAR struct net_driver_s *dev,
FAR struct udp_conn_s *conn, uint16_t flags);
/****************************************************************************
* Name: udp_ipv6_dev_forward
* Name: udp_forward
*
* Description:
* Called by the IP forwarding logic when an UDP packet is received on
@ -454,7 +454,7 @@ uint16_t udp_callback(FAR struct net_driver_s *dev,
#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);
int udp_forward(FAR struct forward_s *fwd);
#endif
/****************************************************************************

View file

@ -37,24 +37,290 @@
#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/netdev.h>
#include <nuttx/net/ip.h>
#include <nuttx/net/netstats.h>
#include "devif/ip_forward.h"
#include "devif/devif.h"
#include "netdev/netdev.h"
#include "udp/udp.h"
#if defined(CONFIG_NET) && defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_UDP)
#if defined(CONFIG_NET_IPFORWARD) && defined(CONFIG_NET_UDP) && \
defined(CONFIG_NETDEV_MULTINIC)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: udp_ipv6_dev_forward
* 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)
{
/* Select IPv4 or IPv6 */
if ((fwd->f_hdr.ipv4.l2.vhl & IP_VERSION_MASK) == IPv4_VERSION)
{
udp_ipv4_select(fwd->f_dev);
}
else
{
udp_ipv6_select(fwd->f_dev);
}
}
#endif
/****************************************************************************
* Name: udp_forward_addrchk
*
* 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:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_ETHERNET
static inline bool udp_forward_addrchk(FAR struct forward_s *fwd)
{
#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
if (conn->domain == PF_INET)
#endif
{
#if !defined(CONFIG_NET_ARP_IPIN) && !defined(CONFIG_NET_ARP_SEND)
return (arp_find(fwd->f_hdr.ipv4.l2.destipaddr) != 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(fwd->f_hdr.ipv6.l2.destipaddr) != NULL);
#else
return true;
#endif
}
#endif /* CONFIG_NET_IPv6 */
}
#else /* CONFIG_NET_ETHERNET */
# define udp_forward_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)
{
/* 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_hdr.ipv4.l2.vhl & IP_VERSION_MASK) == IPv4_VERSION)
#endif
{
g_netstats.ipv4.drop++;
}
#endif
#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
else
#endif
{
g_netstats.ipv6.drop++;
}
#endif
}
#else
# define udp_dropstats(ipv6)
#endif
/****************************************************************************
* Name: udp_forward_interrupt
*
* Description:
* 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 UDP 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 udp_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);
/* 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");
udp_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 & UDP_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(dev, 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 (!udp_forward_addrchk(fwd))
{
return flags;
}
}
/* Free the allocated callback structure */
fwd->f_cb->flags = 0;
fwd->f_cb->priv = NULL;
fwd->f_cb->event = NULL;
udp_callback_free(dev, &fwd->f_conn.udp, fwd->f_cb);
/* Free any IOBs */
if (fwd->f_iob != NULL)
{
iob_free_chain(fwd->f_iob);
}
/* And release the forwarding state structure */
ip_forward_free(fwd);
}
return flags;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: udp_forward
*
* Description:
* Called by the IP forwarding logic when an UDP packet is received on
@ -76,23 +342,26 @@
*
****************************************************************************/
#if defined(CONFIG_NET_IPv6) && defined(CONFIG_NETDEV_MULTINIC)
int udp_ipv6_dev_forward(FAR struct forward_s *fwd)
int udp_forward(FAR struct forward_s *fwd)
{
/* Set up to send the packet when the selected device polls for TX data. */
DEBUGASSERT(fwd != NULL && fwd->f_dev != NULL);
/* Notify the forwarding device that TX data is available */
/* Set up the callback in the connection */
#warning Missing logic
fwd->f_cb = udp_callback_alloc(fwd->f_dev, &fwd->f_conn.udp);
if (fwd->f_cb != NULL)
{
fwd->f_cb->flags = (UDP_POLL | NETDEV_DOWN);
fwd->f_cb->priv = (FAR void *)fwd;
fwd->f_cb->event = udp_forward_interrupt;
/* 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.
*/
/* Notify the device driver of the availability of TX data */
nwarn("WARNING: UPD/ICMPv6 packet forwarding not yet supported\n");
return -ENOSYS;
netdev_txnotify_dev(fwd->f_dev);
return OK;
}
return -EBUSY;
}
#endif /* CONFIG_NET_IPv6 && CONFIG_NETDEV_MULTINIC */
#endif /* CONFIG_NET && CONFIG_NET_IPFORWARD && CONFIG_NET_UDP */
#endif /* CONFIG_NET_IPFORWARD && CONFIG_NET_UDP && CONFIG_NETDEV_MULTINIC */

View file

@ -126,7 +126,7 @@ struct sendto_s
* TRUE:timeout FALSE:no timeout
*
* Assumptions:
* Running at the interrupt level
* The network is locked
*
****************************************************************************/
@ -170,7 +170,7 @@ static inline int send_timeout(FAR struct sendto_s *pstate)
* None
*
* Assumptions:
* Running at the interrupt level
* The network is locked
*
****************************************************************************/
@ -216,7 +216,7 @@ static inline void sendto_ipselect(FAR struct net_driver_s *dev,
* Modified value of the input flags
*
* Assumptions:
* Running at the interrupt level
* The network is locked
*
****************************************************************************/