/**************************************************************************** * net/ipfrag/ipfrag.h * * SPDX-License-Identifier: Apache-2.0 * * 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 #include #include #include #include #include #include #include #include #include #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 */ extern mutex_t g_ipfrag_lock; /**************************************************************************** * 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 */