NDN-DPDK
High-Speed Named Data Networking Forwarder
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tlv-decoder.h
Go to the documentation of this file.
1 #ifndef NDNDPDK_NDNI_TLV_DECODER_H
2 #define NDNDPDK_NDNI_TLV_DECODER_H
3 
6 #include "nni.h"
7 
9 static __rte_always_inline bool
10 TlvDecoder_IsCriticalType(uint32_t type) {
11  return type <= 0x1F || (type % 2) == 1;
12 }
13 
15 typedef struct TlvDecoder {
16  struct rte_mbuf* p;
17  struct rte_mbuf* m;
18  uint32_t length;
19  uint16_t offset;
21 
23 __attribute__((nonnull)) static inline TlvDecoder
24 TlvDecoder_Init(struct rte_mbuf* p) {
25  return (TlvDecoder){
26  .p = p,
27  .m = p,
28  .length = p->pkt_len,
29  };
30 }
31 
32 __attribute__((nonnull)) static inline void
33 TlvDecoder_Skip_(TlvDecoder* d, uint32_t count, struct rte_mbuf** last) {
34  NDNDPDK_ASSERT(count <= d->length);
35  for (uint32_t remain = count; remain > 0;) {
36  *last = d->m;
37  uint32_t here = d->m->data_len - d->offset;
38  if (likely(remain < here)) {
39  d->offset += remain;
40  break;
41  }
42  remain -= here;
43  d->m = d->m->next;
44  d->offset = 0;
45  }
46  d->length -= count;
47 }
48 
53 __attribute__((nonnull)) static inline void
54 TlvDecoder_Skip(TlvDecoder* d, uint32_t count) {
55  struct rte_mbuf* unusedLast = NULL;
56  TlvDecoder_Skip_(d, count, &unusedLast);
57 }
58 
66 void
68 
69 __attribute__((nonnull)) void
70 TlvDecoder_Copy_(TlvDecoder* d, uint8_t* output, uint16_t count);
71 
77 __attribute__((nonnull)) static inline void
78 TlvDecoder_Copy(TlvDecoder* d, uint8_t* output, uint16_t count) {
79  NDNDPDK_ASSERT(count <= d->length);
80  if (unlikely(count == 0)) {
81  return;
82  }
83 
84  uint16_t here = d->m->data_len - d->offset;
85  if (likely(count < here)) {
86  rte_memcpy(output, rte_pktmbuf_mtod_offset(d->m, const uint8_t*, d->offset), count);
87  d->offset += count;
88  d->length -= count;
89  return;
90  }
91 
92  TlvDecoder_Copy_(d, output, count);
93 }
94 
95 __attribute__((nonnull, returns_nonnull)) static inline const uint8_t*
96 TlvDecoder_Read_Contiguous_(TlvDecoder* d, uint16_t count) {
97  uint16_t here = d->m->data_len - d->offset;
98  const uint8_t* output = rte_pktmbuf_mtod_offset(d->m, const uint8_t*, d->offset);
99 
100  d->length -= count;
101  if (likely(count < here)) {
102  d->offset += count;
103  } else {
104  NDNDPDK_ASSERT(count == here);
105  d->m = d->m->next;
106  d->offset = 0;
107  }
108 
109  return output;
110 }
111 
119 __attribute__((nonnull, returns_nonnull)) static inline const uint8_t*
120 TlvDecoder_Read(TlvDecoder* d, uint8_t* scratch, uint16_t count) {
121  NDNDPDK_ASSERT(count <= d->length);
122  if (unlikely(count == 0)) {
123  return scratch;
124  }
125  if (likely(count <= d->m->data_len - d->offset)) {
126  return TlvDecoder_Read_Contiguous_(d, count);
127  }
128  TlvDecoder_Copy_(d, scratch, count);
129  return scratch;
130 }
131 
139 __attribute__((nonnull)) struct rte_mbuf*
140 TlvDecoder_Clone(TlvDecoder* d, uint32_t count, struct rte_mempool* indirectMp);
141 
154 __attribute__((nonnull)) void
155 TlvDecoder_Fragment(TlvDecoder* d, uint32_t count, struct rte_mbuf* frames[], uint32_t* fragIndex,
156  uint32_t fragCount, uint16_t fragSize, uint16_t headroom);
157 
158 __attribute__((nonnull)) const uint8_t*
160 
169 __attribute__((nonnull)) static inline const uint8_t*
170 TlvDecoder_Linearize(TlvDecoder* d, uint16_t count) {
171  NDNDPDK_ASSERT(count <= d->length);
172  if (unlikely(count == 0)) {
173  return NULL;
174  }
175  if (likely(count < d->m->data_len - d->offset)) {
176  return TlvDecoder_Read_Contiguous_(d, count);
177  }
178  return TlvDecoder_Linearize_NonContiguous_(d, count);
179 }
180 
186 __attribute__((nonnull)) static inline bool
187 TlvDecoder_ReadVarNum(TlvDecoder* d, uint32_t* n) {
188  if (unlikely(d->length < 1)) {
189  return false;
190  }
191  uint8_t scratch[4];
192  uint8_t first = *TlvDecoder_Read(d, scratch, 1);
193  switch (first) {
194  case 0xFD:
195  if (likely(d->length >= 2)) {
196  *n = rte_be_to_cpu_16(*(const unaligned_uint16_t*)TlvDecoder_Read(d, scratch, 2));
197  return likely(*n >= 0xFD);
198  }
199  return false;
200  case 0xFE:
201  if (likely(d->length >= 4)) {
202  *n = rte_be_to_cpu_32(*(const unaligned_uint32_t*)TlvDecoder_Read(d, scratch, 4));
203  return likely(*n > UINT16_MAX);
204  }
205  return false;
206  case 0xFF:
207  return false;
208  default:
209  *n = first;
210  return true;
211  }
212 }
213 
221 __attribute__((nonnull)) static __rte_always_inline uint32_t
222 TlvDecoder_ReadTL_MaybeTruncated(TlvDecoder* d, uint32_t* length) {
223  *length = 0;
224  uint32_t type;
225  if (likely(TlvDecoder_ReadVarNum(d, &type)) && likely(TlvDecoder_ReadVarNum(d, length))) {
226  return type;
227  }
228  return 0;
229 }
230 
238 __attribute__((nonnull)) static inline uint32_t
239 TlvDecoder_ReadTL(TlvDecoder* d, uint32_t* length) {
240  uint32_t type = TlvDecoder_ReadTL_MaybeTruncated(d, length);
241  if (unlikely(*length > d->length)) {
242  return 0;
243  }
244  return type;
245 }
246 
257 #define TlvDecoder_EachTL(d, typeVar, lengthVar) \
258  for (uint32_t lengthVar, typeVar = TlvDecoder_ReadTL((d), &lengthVar); typeVar != 0; \
259  typeVar = TlvDecoder_ReadTL((d), &lengthVar))
260 
268 __attribute__((nonnull)) static inline TlvDecoder
269 TlvDecoder_MakeValueDecoder(TlvDecoder* d, uint32_t length) {
270  TlvDecoder vd = *d;
271  vd.length = length;
272  TlvDecoder_Skip(d, length);
273  return vd;
274 }
275 
282 __attribute__((nonnull)) static __rte_always_inline bool
283 TlvDecoder_ReadNni(TlvDecoder* d, uint32_t length, uint64_t max, uint64_t* n) {
284  uint8_t scratch[8];
285  const uint8_t* value = TlvDecoder_Read(d, scratch, RTE_MIN(sizeof(scratch), length));
286  return Nni_Decode(length, value, n) && *n <= max;
287 }
288 
289 #define TlvDecoder_ReadNniToTypeMax_(sizeofValue) \
290  (sizeofValue) == sizeof(uint8_t) ? UINT8_MAX \
291  : (sizeofValue) == sizeof(uint16_t) ? UINT16_MAX \
292  : (sizeofValue) == sizeof(uint32_t) ? UINT32_MAX \
293  : (sizeofValue) == sizeof(uint64_t) ? UINT64_MAX \
294  : 0
295 #define TlvDecoder_ReadNniTo4_(d, length, max, ptr) \
296  __extension__({ \
297  static_assert(__builtin_constant_p(TlvDecoder_ReadNniToTypeMax_(sizeof(*(ptr)))), ""); \
298  uint64_t value; \
299  bool ok = TlvDecoder_ReadNni( \
300  (d), (length), RTE_MIN((max), TlvDecoder_ReadNniToTypeMax_(sizeof(*(ptr)))), &value); \
301  *(ptr) = value; \
302  ok; \
303  })
304 #define TlvDecoder_ReadNniTo3_(d, length, ptr) \
305  TlvDecoder_ReadNniTo4_((d), (length), UINT64_MAX, (ptr))
306 #define TlvDecoder_ReadNniToArg5_(a1, a2, a3, a4, a5, ...) a5
307 #define TlvDecoder_ReadNniToChoose_(...) \
308  TlvDecoder_ReadNniToArg5_(__VA_ARGS__, TlvDecoder_ReadNniTo4_, TlvDecoder_ReadNniTo3_, )
309 
321 #define TlvDecoder_ReadNniTo(...) (TlvDecoder_ReadNniToChoose_(__VA_ARGS__)(__VA_ARGS__))
322 
323 #endif // NDNDPDK_NDNI_TLV_DECODER_H
#define NDNDPDK_ASSERT(x)
Definition: common.h:60
TLV decoder.
Definition: tlv-decoder.h:15
uint16_t offset
offset within current segment
Definition: tlv-decoder.h:19
struct rte_mbuf * p
first segment
Definition: tlv-decoder.h:16
struct rte_mbuf * m
current segment
Definition: tlv-decoder.h:17
uint32_t length
remaining byte length
Definition: tlv-decoder.h:18
void TlvDecoder_Truncate(TlvDecoder *d)
Truncate mbuf to the remaining bytes.
Definition: tlv-decoder.c:4
void TlvDecoder_Fragment(TlvDecoder *d, uint32_t count, struct rte_mbuf *frames[], uint32_t *fragIndex, uint32_t fragCount, uint16_t fragSize, uint16_t headroom)
Copy next count octets to fragments.
Definition: tlv-decoder.c:136
struct TlvDecoder TlvDecoder
TLV decoder.
struct rte_mbuf * TlvDecoder_Clone(TlvDecoder *d, uint32_t count, struct rte_mempool *indirectMp)
Clone next count octets to indirect mbufs.
Definition: tlv-decoder.c:71
void TlvDecoder_Copy_(TlvDecoder *d, uint8_t *output, uint16_t count)
Definition: tlv-decoder.c:52
const uint8_t * TlvDecoder_Linearize_NonContiguous_(TlvDecoder *d, uint16_t count)
Definition: tlv-decoder.c:226