/**
* @file
- * RTE IPv4 Fragmentation and Reassembly
+ * RTE IP Fragmentation and Reassembly
*
- * Implementation of IPv4 packet fragmentation and reassembly.
+ * Implementation of IP packet fragmentation and reassembly.
*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stdint.h>
#include <stdio.h>
#include <rte_malloc.h>
-#include <rte_mbuf.h>
+#include <rte_memory.h>
#include <rte_ip.h>
+#include <rte_byteorder.h>
+
+struct rte_mbuf;
enum {
IP_LAST_FRAG_IDX, /**< index of last fragment */
uint32_t key_len; /**< src/dst key length */
};
-/*
+/**
* @internal Fragmented packet to reassemble.
* First two entries in the frags[] array are for the last and first fragments.
*/
-struct rte_ip_frag_pkt {
- TAILQ_ENTRY(rte_ip_frag_pkt) lru; /**< LRU list */
+struct ip_frag_pkt {
+ TAILQ_ENTRY(ip_frag_pkt) lru; /**< LRU list */
struct ip_frag_key key; /**< fragmentation key */
uint64_t start; /**< creation timestamp */
uint32_t total_size; /**< expected reassembled size */
/**< mbufs to be freed */
};
-TAILQ_HEAD(rte_ip_pkt_list, rte_ip_frag_pkt); /**< @internal fragments tailq */
+TAILQ_HEAD(ip_pkt_list, ip_frag_pkt); /**< @internal fragments tailq */
/** fragmentation table statistics */
-struct rte_ip_frag_tbl_stat {
+struct ip_frag_tbl_stat {
uint64_t find_num; /**< total # of find/insert attempts. */
uint64_t add_num; /**< # of add ops. */
uint64_t del_num; /**< # of del ops. */
uint32_t bucket_entries; /**< hash assocaitivity. */
uint32_t nb_entries; /**< total size of the table. */
uint32_t nb_buckets; /**< num of associativity lines. */
- struct rte_ip_frag_pkt *last; /**< last used entry. */
- struct rte_ip_pkt_list lru; /**< LRU list for table entries. */
- struct rte_ip_frag_tbl_stat stat; /**< statistics counters. */
- struct rte_ip_frag_pkt pkt[0]; /**< hash table. */
+ struct ip_frag_pkt *last; /**< last used entry. */
+ struct ip_pkt_list lru; /**< LRU list for table entries. */
+ struct ip_frag_tbl_stat stat; /**< statistics counters. */
+ __extension__ struct ip_frag_pkt pkt[0]; /**< hash table. */
};
/** IPv6 fragment extension header */
+#define RTE_IPV6_EHDR_MF_SHIFT 0
+#define RTE_IPV6_EHDR_MF_MASK 1
+#define RTE_IPV6_EHDR_FO_SHIFT 3
+#define RTE_IPV6_EHDR_FO_MASK (~((1 << RTE_IPV6_EHDR_FO_SHIFT) - 1))
+
+#define RTE_IPV6_FRAG_USED_MASK \
+ (RTE_IPV6_EHDR_MF_MASK | RTE_IPV6_EHDR_FO_MASK)
+
+#define RTE_IPV6_GET_MF(x) ((x) & RTE_IPV6_EHDR_MF_MASK)
+#define RTE_IPV6_GET_FO(x) ((x) >> RTE_IPV6_EHDR_FO_SHIFT)
+
+#define RTE_IPV6_SET_FRAG_DATA(fo, mf) \
+ (((fo) & RTE_IPV6_EHDR_FO_MASK) | ((mf) & RTE_IPV6_EHDR_MF_MASK))
+
struct ipv6_extension_fragment {
uint8_t next_header; /**< Next header type */
- uint8_t reserved1; /**< Reserved */
- union {
- struct {
- uint16_t frag_offset:13; /**< Offset from the start of the packet */
- uint16_t reserved2:2; /**< Reserved */
- uint16_t more_frags:1;
- /**< 1 if more fragments left, 0 if last fragment */
- };
- uint16_t frag_data;
- /**< union of all fragmentation data */
- };
+ uint8_t reserved; /**< Reserved */
+ uint16_t frag_data; /**< All fragmentation data */
uint32_t id; /**< Packet ID */
} __attribute__((__packed__));
-/*
+/**
* Create a new IP fragmentation table.
*
* @param bucket_num
uint32_t bucket_entries, uint32_t max_entries,
uint64_t max_cycles, int socket_id);
-/*
+/**
* Free allocated IP fragmentation table.
*
- * @param btl
+ * @param tbl
* Fragmentation table to free.
*/
-static inline void
-rte_ip_frag_table_destroy( struct rte_ip_frag_tbl *tbl)
-{
- rte_free(tbl);
-}
+void
+rte_ip_frag_table_destroy(struct rte_ip_frag_tbl *tbl);
/**
* This function implements the fragmentation of IPv6 packets.
struct rte_mempool *pool_direct,
struct rte_mempool *pool_indirect);
-
-/*
+/**
* This function implements reassembly of fragmented IPv6 packets.
* Incoming mbuf should have its l2_len/l3_len fields setup correctly.
*
* Pointer to the IPv6 fragment extension header.
* @return
* Pointer to mbuf for reassembled packet, or NULL if:
- * - an error occured.
+ * - an error occurred.
* - not all fragments of the packet are collected yet.
*/
struct rte_mbuf *rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
struct rte_mbuf *mb, uint64_t tms, struct ipv6_hdr *ip_hdr,
struct ipv6_extension_fragment *frag_hdr);
-/*
+/**
* Return a pointer to the packet's fragment header, if found.
* It only looks at the extension header that's right after the fixed IPv6
* header, and doesn't follow the whole chain of extension headers.
struct rte_mempool *pool_direct,
struct rte_mempool *pool_indirect);
-/*
+/**
* This function implements reassembly of fragmented IPv4 packets.
* Incoming mbufs should have its l2_len/l3_len fields setup correclty.
*
* Pointer to the IPV4 header inside the fragment.
* @return
* Pointer to mbuf for reassebled packet, or NULL if:
- * - an error occured.
+ * - an error occurred.
* - not all fragments of the packet are collected yet.
*/
struct rte_mbuf * rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
struct rte_ip_frag_death_row *dr,
struct rte_mbuf *mb, uint64_t tms, struct ipv4_hdr *ip_hdr);
-/*
+/**
* Check if the IPv4 packet is fragmented
*
* @param hdr
return ip_flag != 0 || ip_ofs != 0;
}
-/*
+/**
* Free mbufs on a given death row.
*
* @param dr
uint32_t prefetch);
-/*
+/**
* Dump fragmentation table statistics to file.
*
* @param f
void
rte_ip_frag_table_statistics_dump(FILE * f, const struct rte_ip_frag_tbl *tbl);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _RTE_IP_FRAG_H_ */