1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #ifndef _IP_FRAG_COMMON_H_ 6 #define _IP_FRAG_COMMON_H_ 7 8 #include "rte_ip_frag.h" 9 10 /* logging macros. */ 11 #ifdef RTE_LIBRTE_IP_FRAG_DEBUG 12 #define IP_FRAG_LOG(lvl, fmt, args...) RTE_LOG(lvl, USER1, fmt, ##args) 13 #else 14 #define IP_FRAG_LOG(lvl, fmt, args...) do {} while(0) 15 #endif /* IP_FRAG_DEBUG */ 16 17 #define IPV4_KEYLEN 1 18 #define IPV6_KEYLEN 4 19 20 /* helper macros */ 21 #define IP_FRAG_MBUF2DR(dr, mb) ((dr)->row[(dr)->cnt++] = (mb)) 22 23 #define IPv6_KEY_BYTES(key) \ 24 (key)[0], (key)[1], (key)[2], (key)[3] 25 #define IPv6_KEY_BYTES_FMT \ 26 "%08" PRIx64 "%08" PRIx64 "%08" PRIx64 "%08" PRIx64 27 28 #ifdef RTE_LIBRTE_IP_FRAG_TBL_STAT 29 #define IP_FRAG_TBL_STAT_UPDATE(s, f, v) ((s)->f += (v)) 30 #else 31 #define IP_FRAG_TBL_STAT_UPDATE(s, f, v) do {} while (0) 32 #endif /* IP_FRAG_TBL_STAT */ 33 34 /* internal functions declarations */ 35 struct rte_mbuf * ip_frag_process(struct ip_frag_pkt *fp, 36 struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, 37 uint16_t ofs, uint16_t len, uint16_t more_frags); 38 39 struct ip_frag_pkt * ip_frag_find(struct rte_ip_frag_tbl *tbl, 40 struct rte_ip_frag_death_row *dr, 41 const struct ip_frag_key *key, uint64_t tms); 42 43 struct ip_frag_pkt * ip_frag_lookup(struct rte_ip_frag_tbl *tbl, 44 const struct ip_frag_key *key, uint64_t tms, 45 struct ip_frag_pkt **free, struct ip_frag_pkt **stale); 46 47 /* these functions need to be declared here as ip_frag_process relies on them */ 48 struct rte_mbuf *ipv4_frag_reassemble(struct ip_frag_pkt *fp); 49 struct rte_mbuf *ipv6_frag_reassemble(struct ip_frag_pkt *fp); 50 51 52 53 /* 54 * misc frag key functions 55 */ 56 57 /* check if key is empty */ 58 static inline int 59 ip_frag_key_is_empty(const struct ip_frag_key * key) 60 { 61 return (key->key_len == 0); 62 } 63 64 /* invalidate the key */ 65 static inline void 66 ip_frag_key_invalidate(struct ip_frag_key * key) 67 { 68 key->key_len = 0; 69 } 70 71 /* compare two keys */ 72 static inline uint64_t 73 ip_frag_key_cmp(const struct ip_frag_key * k1, const struct ip_frag_key * k2) 74 { 75 uint32_t i; 76 uint64_t val; 77 val = k1->id_key_len ^ k2->id_key_len; 78 for (i = 0; i < k1->key_len; i++) 79 val |= k1->src_dst[i] ^ k2->src_dst[i]; 80 return val; 81 } 82 83 /* 84 * misc fragment functions 85 */ 86 87 /* put fragment on death row */ 88 static inline void 89 ip_frag_free(struct ip_frag_pkt *fp, struct rte_ip_frag_death_row *dr) 90 { 91 uint32_t i, k; 92 93 k = dr->cnt; 94 for (i = 0; i != fp->last_idx; i++) { 95 if (fp->frags[i].mb != NULL) { 96 dr->row[k++] = fp->frags[i].mb; 97 fp->frags[i].mb = NULL; 98 } 99 } 100 101 fp->last_idx = 0; 102 dr->cnt = k; 103 } 104 105 /* delete fragment's mbufs immediately instead of using death row */ 106 static inline void 107 ip_frag_free_immediate(struct ip_frag_pkt *fp) 108 { 109 uint32_t i; 110 111 for (i = 0; i < fp->last_idx; i++) { 112 if (fp->frags[i].mb != NULL) { 113 IP_FRAG_LOG(DEBUG, "%s:%d\n" 114 "mbuf: %p, tms: %" PRIu64", key: <%" PRIx64 ", %#x>\n", 115 __func__, __LINE__, fp->frags[i].mb, fp->start, 116 fp->key.src_dst[0], fp->key.id); 117 rte_pktmbuf_free(fp->frags[i].mb); 118 fp->frags[i].mb = NULL; 119 } 120 } 121 122 fp->last_idx = 0; 123 } 124 125 /* if key is empty, mark key as in use */ 126 static inline void 127 ip_frag_inuse(struct rte_ip_frag_tbl *tbl, const struct ip_frag_pkt *fp) 128 { 129 if (ip_frag_key_is_empty(&fp->key)) { 130 TAILQ_REMOVE(&tbl->lru, fp, lru); 131 tbl->use_entries--; 132 } 133 } 134 135 /* reset the fragment */ 136 static inline void 137 ip_frag_reset(struct ip_frag_pkt *fp, uint64_t tms) 138 { 139 static const struct ip_frag zero_frag = { 140 .ofs = 0, 141 .len = 0, 142 .mb = NULL, 143 }; 144 145 fp->start = tms; 146 fp->total_size = UINT32_MAX; 147 fp->frag_size = 0; 148 fp->last_idx = IP_MIN_FRAG_NUM; 149 fp->frags[IP_LAST_FRAG_IDX] = zero_frag; 150 fp->frags[IP_FIRST_FRAG_IDX] = zero_frag; 151 } 152 153 /* local frag table helper functions */ 154 static inline void 155 ip_frag_tbl_del(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr, 156 struct ip_frag_pkt *fp) 157 { 158 ip_frag_free(fp, dr); 159 ip_frag_key_invalidate(&fp->key); 160 TAILQ_REMOVE(&tbl->lru, fp, lru); 161 tbl->use_entries--; 162 IP_FRAG_TBL_STAT_UPDATE(&tbl->stat, del_num, 1); 163 } 164 165 #endif /* _IP_FRAG_COMMON_H_ */ 166