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