2023-01-09 13:47:11 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* net/ipfrag/ipfrag.h
|
|
|
|
*
|
2024-09-11 14:39:39 +02:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*
|
2023-01-09 13:47:11 +01:00
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
|
|
* this work for additional information regarding copyright ownership. The
|
|
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
|
|
* "License"); you may not use this file except in compliance with the
|
|
|
|
* License. You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifndef __NET_IPFRAG_IPFRAG_H
|
|
|
|
#define __NET_IPFRAG_IPFRAG_H
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include <nuttx/mutex.h>
|
|
|
|
#include <nuttx/queue.h>
|
|
|
|
#include <nuttx/mm/iob.h>
|
|
|
|
#include <nuttx/net/ip.h>
|
|
|
|
#include <nuttx/net/net.h>
|
|
|
|
#include <nuttx/net/netdev.h>
|
|
|
|
|
|
|
|
#include "devif/devif.h"
|
|
|
|
|
|
|
|
#if defined(CONFIG_NET_IPFRAG)
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public types
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
enum ip_fragverify_e
|
|
|
|
{
|
|
|
|
/* Indicates whether received all fragments */
|
|
|
|
|
|
|
|
IP_FRAGVERIFY_RECVDALLFRAGS = 0x01 << 0,
|
|
|
|
|
|
|
|
/* Indicates whether received the first fragment which is used to:
|
|
|
|
* 1.construct the ICMP time exceeded msg(type=11, code=1) when reassembly
|
|
|
|
* timeout, but if the first fragment has not been received when timeout,
|
|
|
|
* no ICMP error message will be sent;
|
|
|
|
* 2.build NAT entry with the L4 port number and do forwarding.
|
|
|
|
*/
|
|
|
|
|
|
|
|
IP_FRAGVERIFY_RECVDZEROFRAG = 0x01 << 1,
|
|
|
|
|
|
|
|
/* Indicates whether the tail fragment is received(which morefrag flag is
|
|
|
|
* set to 0)
|
|
|
|
*/
|
|
|
|
|
|
|
|
IP_FRAGVERIFY_RECVDTAILFRAG = 0x01 << 2,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ip_fraglink_s
|
|
|
|
{
|
|
|
|
/* This link is used to maintain a single-linked list of ip_fraglink_s,
|
|
|
|
* it links all framgents with the same IP ID
|
|
|
|
*/
|
|
|
|
|
|
|
|
FAR struct ip_fraglink_s *flink;
|
|
|
|
|
|
|
|
FAR struct ip_fragsnode_s *fragsnode; /* Point to parent struct */
|
|
|
|
FAR struct iob_s *frag; /* Point to fragment data */
|
|
|
|
uint8_t isipv4; /* IPv4 or IPv6 */
|
|
|
|
uint16_t fragoff; /* Fragment offset */
|
|
|
|
uint16_t fraglen; /* Payload length */
|
|
|
|
uint16_t morefrags; /* The more frag flag */
|
|
|
|
|
|
|
|
/* The identification field is 16 bits in IPv4 header but 32 bits in IPv6
|
|
|
|
* fragment header
|
|
|
|
*/
|
|
|
|
|
|
|
|
uint32_t ipid;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ip_fragsnode_s
|
|
|
|
{
|
|
|
|
/* This link is used to maintain a single-linked list of ip_fragsnode_s.
|
|
|
|
* Must be the first field in the structure due to flink type casting.
|
|
|
|
*/
|
|
|
|
|
|
|
|
FAR struct ip_fragsnode_s *flink;
|
|
|
|
|
|
|
|
/* Another link which connects all ip_fragsnode_s in order of addition
|
|
|
|
* time
|
|
|
|
*/
|
|
|
|
|
|
|
|
FAR sq_entry_t *flinkat;
|
|
|
|
|
|
|
|
/* Interface understood by the network */
|
|
|
|
|
|
|
|
FAR struct net_driver_s *dev;
|
|
|
|
|
|
|
|
/* IP Identification (IP ID) field defined in ipv4 header or in ipv6
|
|
|
|
* fragment header.
|
|
|
|
*/
|
|
|
|
|
|
|
|
uint32_t ipid;
|
|
|
|
|
|
|
|
/* Count ticks, used by ressembly timer */
|
|
|
|
|
|
|
|
clock_t tick;
|
|
|
|
|
|
|
|
/* Remember some running flags */
|
|
|
|
|
|
|
|
uint16_t verifyflag;
|
|
|
|
|
|
|
|
/* Remember the total number of I/O buffers of this node */
|
|
|
|
|
|
|
|
uint32_t bufcnt;
|
|
|
|
|
|
|
|
/* Linked all fragments with the same IP ID. */
|
|
|
|
|
|
|
|
FAR struct ip_fraglink_s *frags;
|
|
|
|
|
|
|
|
/* Points to the reassembled outgoing IP frame */
|
|
|
|
|
|
|
|
FAR struct iob_s *outgoframe;
|
|
|
|
};
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Data
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
# define EXTERN extern "C"
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
#else
|
|
|
|
# define EXTERN extern
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Only one thread can access g_assemblyhead_ipid and g_assemblyhead_time
|
|
|
|
* at a time
|
|
|
|
*/
|
|
|
|
|
2023-06-10 19:24:08 +02:00
|
|
|
extern mutex_t g_ipfrag_lock;
|
2023-01-09 13:47:11 +01:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Function Prototypes
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ip_frag_remnode
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* free ip_fragsnode_s
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* node - node of the upper-level linked list, it maintains
|
|
|
|
* information about all fragments belonging to an IP datagram
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* I/O buffer count of this node
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
uint32_t ip_frag_remnode(FAR struct ip_fragsnode_s *node);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ip_fragin_enqueue
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Enqueue one fragment.
|
|
|
|
* All fragments belonging to one IP frame are organized in a linked list
|
|
|
|
* form, that is a ip_fragsnode_s node. All ip_fragsnode_s nodes are also
|
|
|
|
* organized in an upper-level linked list.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* dev - NIC Device instance
|
|
|
|
* curfraglink - node of the lower-level linked list, it maintains
|
|
|
|
* information of one fragment
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* Whether queue is empty before enqueue the new node
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
bool ip_fragin_enqueue(FAR struct net_driver_s *dev,
|
|
|
|
FAR struct ip_fraglink_s *curfraglink);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ipv4_fragin
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Handling incoming IPv4 fragment input, the input data
|
|
|
|
* (dev->d_iob) can be an I/O buffer chain
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* dev - The NIC device that the fragmented data comes from
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* ENOMEM - No memory
|
|
|
|
* OK - The input fragment is processed as expected
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int32_t ipv4_fragin(FAR struct net_driver_s *dev);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ipv6_fragin
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Handling incoming IPv6 fragment input, the input data
|
|
|
|
* (dev->d_iob) can be an I/O buffer chain
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* dev - The NIC device that the fragmented data comes from
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* ENOMEM - No memory
|
|
|
|
* OK - The input fragment is processed as expected
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int32_t ipv6_fragin(FAR struct net_driver_s *dev);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ip_fragout_slice
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* According to the MTU of a given NIC, split the original data into
|
|
|
|
* multiple data pieces, and the space for filling the L3 header is
|
|
|
|
* reserved at the forefront of each piece. Each piece is stored in
|
|
|
|
* independent I/O buffer(s) and eventually forms an I/O buffer queue.
|
|
|
|
* Note:
|
|
|
|
* 1.About the 'piece' above
|
|
|
|
* 1).If MTU < CONFIG_IOB_BUFSIZE, a piece consists of an I/O buffer;
|
|
|
|
* 2).If MTU >= CONFIG_IOB_BUFSIZE, a piece consists of multiple I/O
|
|
|
|
* buffers.
|
|
|
|
* 2.This function split and gathers the incoming data into outgoing
|
|
|
|
* I/O buffers according to the MTU, but is not responsible for
|
|
|
|
* building the L3 header related to the fragmentation.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* iob - The data comes from
|
|
|
|
* domain - PF_INET or PF_INET6
|
|
|
|
* mtu - MTU of given NIC
|
|
|
|
* unfraglen - The starting position to fragmentation processing
|
|
|
|
* fragq - Those output slices
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* Number of fragments
|
|
|
|
*
|
|
|
|
* Assumptions:
|
|
|
|
* Data length(iob->io_pktlen) is grater than the MTU of current NIC
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int32_t ip_fragout_slice(FAR struct iob_s *iob, uint8_t domain, uint16_t mtu,
|
|
|
|
uint16_t unfraglen, FAR struct iob_queue_s *fragq);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ipv4_fragout
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Execute the ipv4 fragment function. After this work is done, all
|
|
|
|
* fragments are maintained by dev->d_fragout. In order to reduce the
|
|
|
|
* cyclomatic complexity and facilitate maintenance, fragmentation is
|
|
|
|
* performed in two steps:
|
|
|
|
* 1. Reconstruct I/O Buffer according to MTU, which will reserve
|
|
|
|
* the space for the L3 header;
|
|
|
|
* 2. Fill the L3 header into the reserved space.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* dev - The NIC device
|
|
|
|
* mtu - The MTU of current NIC
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* 0 if success or a negative value if fail.
|
|
|
|
*
|
|
|
|
* Assumptions:
|
|
|
|
* Data length(dev->d_iob->io_pktlen) is grater than the MTU of
|
|
|
|
* current NIC
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int32_t ipv4_fragout(FAR struct net_driver_s *dev, uint16_t mtu);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ipv6_fragout
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Execute the ipv6 fragment function. After this work is done, all
|
|
|
|
* fragments are maintained by dev->d_fragout. In order to reduce the
|
|
|
|
* cyclomatic complexity and facilitate maintenance, fragmentation is
|
|
|
|
* performed in two steps:
|
|
|
|
* 1. Reconstruct I/O Buffer according to MTU, which will reserve
|
|
|
|
* the space for the L3 header;
|
|
|
|
* 2. Fill the L3 header into the reserved space.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* dev - The NIC device
|
|
|
|
* mtu - The MTU of current NIC
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* 0 if success or a negative value if fail.
|
|
|
|
*
|
|
|
|
* Assumptions:
|
|
|
|
* Data length(dev->d_iob->io_pktlen) is grater than the MTU of
|
|
|
|
* current NIC
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int32_t ipv6_fragout(FAR struct net_driver_s *dev, uint16_t mtu);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ip_frag_startwdog
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Start the reassembly timeout timer
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void ip_frag_startwdog(void);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ip_frag_stop
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Stop the fragment process function for the specified NIC.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* dev - NIC Device instance which will be bring down
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void ip_frag_stop(FAR struct net_driver_s *dev);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ip_frag_remallfrags
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Release all I/O Buffers used by fragment processing module when
|
|
|
|
* I/O Buffer resources are exhausted.
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void ip_frag_remallfrags(void);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: ip_fragout
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Fragout processing
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* dev - The NIC device
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* A non-negative value is returned on success; negative value on failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int32_t ip_fragout(FAR struct net_driver_s *dev);
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* CONFIG_NET_IPFRAG */
|
|
|
|
#endif /* __NET_IPFRAG_IPFRAG_H */
|