API Reference Manual  1.46.0
ipsec_crypto/odp_ipsec_stream.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2014-2018 Linaro Limited
3  */
4 
7 /* enable strtok */
8 #ifndef _GNU_SOURCE
9 #define _GNU_SOURCE
10 #endif
11 
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <openssl/des.h>
16 #include <openssl/rand.h>
17 #include <openssl/hmac.h>
18 #include <openssl/opensslv.h>
19 
20 #include <odp_api.h>
21 
22 #include <odp/helper/odph_api.h>
23 
24 #include <odp_ipsec_stream.h>
25 
26 #define STREAM_MAGIC 0xBABE01234567CAFE
27 
28 #define LOOP_DEQ_COUNT 32
30 /* Ignore warnings about APIs deprecated in OpenSSL 3.0 */
31 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
32 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
33 #endif
34 
38 typedef struct ODP_PACKED stream_pkt_hdr_s {
39  odp_u64be_t magic;
40  uint8_t data[];
41 } stream_pkt_hdr_t;
42 
43 static const char *shm_name = "stream_db";
44 stream_db_t *stream_db;
45 
46 void init_stream_db(void)
47 {
48  odp_shm_t shm;
49 
50  shm = odp_shm_reserve(shm_name,
51  sizeof(stream_db_t),
52  ODP_CACHE_LINE_SIZE,
53  0);
54 
55  if (shm == ODP_SHM_INVALID) {
56  ODPH_ERR("Error: shared mem reserve failed.\n");
57  exit(EXIT_FAILURE);
58  }
59 
60  stream_db = odp_shm_addr(shm);
61 
62  if (stream_db == NULL) {
63  ODPH_ERR("Error: shared mem alloc failed.\n");
64  exit(EXIT_FAILURE);
65  }
66  memset(stream_db, 0, sizeof(*stream_db));
67 }
68 
69 void deinit_stream_db(void)
70 {
71  stream_db_entry_t *stream = NULL;
72 
73  for (stream = stream_db->list; NULL != stream; stream = stream->next) {
74  free(stream->input.intf);
75  free(stream->output.intf);
76  }
77 
78  odp_shm_t shm = odp_shm_lookup(shm_name);
79 
80  if (shm == ODP_SHM_INVALID) {
81  ODPH_ERR("Error: shared mem not found.\n");
82  exit(EXIT_FAILURE);
83  }
84 
85  if (odp_shm_free(shm)) {
86  ODPH_ERR("Error: shared mem free failed.\n");
87  exit(EXIT_FAILURE);
88  }
89 }
90 
91 int create_stream_db_entry(char *input)
92 {
93  int pos = 0;
94  char *local;
95  char *str;
96  char *save;
97  char *token;
98  stream_db_entry_t *entry = &stream_db->array[stream_db->index];
99 
100  /* Verify we have a good entry */
101  if (MAX_DB <= stream_db->index)
102  return -1;
103 
104  /* Make a local copy */
105  local = malloc(strlen(input) + 1);
106  if (NULL == local)
107  return -1;
108  strcpy(local, input);
109 
110  /* Setup for using "strtok_r" to search input string */
111  str = local;
112  save = NULL;
113 
114  /* Parse tokens separated by ',' */
115  while (NULL != (token = strtok_r(str, ",", &save))) {
116  str = NULL; /* reset str for subsequent strtok_r calls */
117 
118  /* Parse token based on its position */
119  switch (pos) {
120  case 0:
121  parse_ipv4_string(token, &entry->src_ip, NULL);
122  break;
123  case 1:
124  parse_ipv4_string(token, &entry->dst_ip, NULL);
125  break;
126  case 2:
127  entry->input.intf = strdup(token);
128  break;
129  case 3:
130  entry->output.intf = strdup(token);
131  break;
132  case 4:
133  entry->count = atoi(token);
134  break;
135  case 5:
136  entry->length = atoi(token);
137  if (entry->length < sizeof(stream_pkt_hdr_t))
138  entry->length = 0;
139  else
140  entry->length -= sizeof(stream_pkt_hdr_t);
141  break;
142  default:
143  printf("ERROR: extra token \"%s\" at position %d\n",
144  token, pos);
145  break;
146  }
147 
148  /* Advance to next position */
149  pos++;
150  }
151 
152  /* Verify we parsed exactly the number of tokens we expected */
153  if (6 != pos) {
154  printf("ERROR: \"%s\" contains %d tokens, expected 6\n",
155  input,
156  pos);
157  free(local);
158  return -1;
159  }
160 
161  /* Add stream to the list */
162  entry->id = stream_db->index++;
163  entry->next = stream_db->list;
164  stream_db->list = entry;
165 
166  free(local);
167  return 0;
168 }
169 
170 static const EVP_MD *get_evp_md(odp_auth_alg_t auth)
171 {
172  const EVP_MD *evp_md;
173 
174  switch (auth) {
176  evp_md = EVP_md5();
177  break;
179  evp_md = EVP_sha1();
180  break;
182  evp_md = EVP_sha256();
183  break;
184  default:
185  evp_md = NULL;
186  }
187 
188  return evp_md;
189 }
190 
191 void resolve_stream_db(void)
192 {
193  stream_db_entry_t *stream = NULL;
194 
195  /* For each stream look for input and output IPsec entries */
196  for (stream = stream_db->list; NULL != stream; stream = stream->next) {
197  ipsec_cache_entry_t *entry;
198 
199  /* Lookup input entry */
200  entry = find_ipsec_cache_entry_in(stream->src_ip,
201  stream->dst_ip,
202  NULL,
203  NULL);
204  stream->input.entry = entry;
205 
206  stream->input.pktio = odp_pktio_lookup(stream->input.intf);
207 
208  if (entry)
209  stream->evp_md = get_evp_md(entry->ah.alg);
210 
211  /* Lookup output entry */
212  entry = find_ipsec_cache_entry_out(stream->src_ip,
213  stream->dst_ip,
214  0);
215  stream->output.entry = entry;
216 
217  stream->output.pktio = odp_pktio_lookup(stream->output.intf);
218 
219  if (stream->evp_md == NULL && entry)
220  stream->evp_md = get_evp_md(entry->ah.alg);
221  }
222 }
223 
224 odp_packet_t create_ipv4_packet(stream_db_entry_t *stream,
225  uint8_t *dmac,
226  odp_pool_t pkt_pool,
227  uint32_t max_len)
228 {
229  ipsec_cache_entry_t *entry = NULL;
230  odp_packet_t pkt;
231  uint8_t *base;
232  uint8_t *data;
233  odph_ethhdr_t *eth;
234  odph_ipv4hdr_t *ip;
235  odph_ipv4hdr_t *inner_ip = NULL;
236  odph_ahhdr_t *ah = NULL;
237  odph_esphdr_t *esp = NULL;
238  odph_icmphdr_t *icmp;
239  stream_pkt_hdr_t *test;
240  unsigned i;
241 
242  if (stream->input.entry)
243  entry = stream->input.entry;
244  else if (stream->output.entry)
245  entry = stream->output.entry;
246 
247  /* Make sure there is enough space for protocol overhead */
248  if ((stream->length + 200) > max_len) {
249  ODPH_ERR("Error: too large test packet\n");
250  return ODP_PACKET_INVALID;
251  }
252 
253  /* Get packet */
254  pkt = odp_packet_alloc(pkt_pool, max_len);
255  if (ODP_PACKET_INVALID == pkt) {
256  ODPH_ERR("Error: packet alloc failed\n");
257  return ODP_PACKET_INVALID;
258  }
259  base = odp_packet_data(pkt);
260  data = odp_packet_data(pkt);
261 
262  /* Ethernet */
263  odp_packet_has_eth_set(pkt, 1);
264  eth = (odph_ethhdr_t *)data;
265  data += sizeof(*eth);
266 
267  memset((char *)eth->src.addr, (0x80 | stream->id), ODPH_ETHADDR_LEN);
268  memcpy((char *)eth->dst.addr, dmac, ODPH_ETHADDR_LEN);
269  eth->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4);
270 
271  /* IPv4 */
272  odp_packet_has_ipv4_set(pkt, 1);
273  ip = (odph_ipv4hdr_t *)data;
274  data += sizeof(*ip);
275 
276  /* Wait until almost finished to fill in mutable fields */
277  memset((char *)ip, 0, sizeof(*ip));
278  ip->ver_ihl = 0x45;
279  ip->id = odp_cpu_to_be_16(stream->id);
280  /* Outer IP header in tunnel mode */
281  if (entry && entry->mode == IPSEC_SA_MODE_TUNNEL &&
282  (entry == stream->input.entry)) {
283  ip->proto = ODPH_IPV4;
284  ip->src_addr = odp_cpu_to_be_32(entry->tun_src_ip);
285  ip->dst_addr = odp_cpu_to_be_32(entry->tun_dst_ip);
286  } else {
287  ip->proto = ODPH_IPPROTO_ICMPV4;
288  ip->src_addr = odp_cpu_to_be_32(stream->src_ip);
289  ip->dst_addr = odp_cpu_to_be_32(stream->dst_ip);
290  }
291 
292  /* AH (if specified) */
293  if (entry && (entry == stream->input.entry) &&
294  (ODP_AUTH_ALG_NULL != entry->ah.alg)) {
295  if (entry->ah.alg != ODP_AUTH_ALG_MD5_HMAC &&
296  entry->ah.alg != ODP_AUTH_ALG_SHA1_HMAC &&
297  entry->ah.alg != ODP_AUTH_ALG_SHA256_HMAC)
298  abort();
299 
300  ah = (odph_ahhdr_t *)data;
301  data += sizeof(*ah);
302  data += entry->ah.icv_len;
303 
304  memset((char *)ah, 0, sizeof(*ah) + entry->ah.icv_len);
305  ah->ah_len = 1 + (entry->ah.icv_len / 4);
306  ah->spi = odp_cpu_to_be_32(entry->ah.spi);
307  ah->seq_no = odp_cpu_to_be_32(stream->input.ah_seq++);
308  }
309 
310  /* ESP (if specified) */
311  if (entry && (entry == stream->input.entry) &&
312  (ODP_CIPHER_ALG_NULL != entry->esp.alg)) {
313  if (ODP_CIPHER_ALG_3DES_CBC != entry->esp.alg)
314  abort();
315 
316  esp = (odph_esphdr_t *)data;
317  data += sizeof(*esp);
318  data += entry->esp.iv_len;
319 
320  esp->spi = odp_cpu_to_be_32(entry->esp.spi);
321  esp->seq_no = odp_cpu_to_be_32(stream->input.esp_seq++);
322  RAND_bytes(esp->iv, 8);
323  }
324 
325  /* Inner IP header in tunnel mode */
326  if (entry && (entry == stream->input.entry) &&
327  (entry->mode == IPSEC_SA_MODE_TUNNEL)) {
328  inner_ip = (odph_ipv4hdr_t *)data;
329  memset((char *)inner_ip, 0, sizeof(*inner_ip));
330  inner_ip->ver_ihl = 0x45;
331  inner_ip->tot_len = odp_cpu_to_be_16(sizeof(odph_ipv4hdr_t) +
332  sizeof(odph_icmphdr_t) +
333  sizeof(stream_pkt_hdr_t) +
334  stream->length);
335  inner_ip->proto = ODPH_IPPROTO_ICMPV4;
336  inner_ip->id = odp_cpu_to_be_16(stream->id);
337  inner_ip->ttl = 64;
338  inner_ip->tos = 0;
339  inner_ip->frag_offset = 0;
340  inner_ip->src_addr = odp_cpu_to_be_32(stream->src_ip);
341  inner_ip->dst_addr = odp_cpu_to_be_32(stream->dst_ip);
342  inner_ip->chksum = ~odp_chksum_ones_comp16(inner_ip,
343  sizeof(*inner_ip));
344  data += sizeof(*inner_ip);
345  }
346 
347  /* ICMP header so we can see it on wireshark */
348  icmp = (odph_icmphdr_t *)data;
349  data += sizeof(*icmp);
350  icmp->type = ODPH_ICMP_ECHO;
351  icmp->code = 0;
352  icmp->un.echo.id = odp_cpu_to_be_16(0x1234);
353  icmp->un.echo.sequence = odp_cpu_to_be_16(stream->created);
354 
355  /* Packet payload of incrementing bytes */
356  test = (stream_pkt_hdr_t *)data;
357  data += sizeof(*test);
358  test->magic = odp_cpu_to_be_64(STREAM_MAGIC);
359  for (i = 0; i < stream->length; i++)
360  *data++ = (uint8_t)i;
361 
362  /* Close ICMP */
363  icmp->chksum = 0;
364  icmp->chksum = ~odp_chksum_ones_comp16(icmp, data - (uint8_t *)icmp);
365 
366  /* Close ESP if specified */
367  if (esp) {
368  int payload_len = data - (uint8_t *)icmp;
369  uint8_t *encrypt_start = (uint8_t *)icmp;
370 
371  if (entry->mode == IPSEC_SA_MODE_TUNNEL) {
372  payload_len = data - (uint8_t *)inner_ip;
373  encrypt_start = (uint8_t *)inner_ip;
374  }
375 
376  int encrypt_len;
377  odph_esptrl_t *esp_t;
378  DES_key_schedule ks1, ks2, ks3;
379  uint8_t iv[8];
380 
381  memcpy(iv, esp->iv, sizeof(iv));
382 
383  encrypt_len = ESP_ENCODE_LEN(payload_len + sizeof(*esp_t),
384  entry->esp.block_len);
385  for (int n = 0; n < encrypt_len - payload_len; n++)
386  *data++ = n + 1;
387 
388  esp_t = (odph_esptrl_t *)(data) - 1;
389  esp_t->pad_len = encrypt_len - payload_len - sizeof(*esp_t);
390  esp_t->next_header = ip->proto;
391  ip->proto = ODPH_IPPROTO_ESP;
392 
393  DES_set_key((DES_cblock *)&entry->esp.key.data[0], &ks1);
394  DES_set_key((DES_cblock *)&entry->esp.key.data[8], &ks2);
395  DES_set_key((DES_cblock *)&entry->esp.key.data[16], &ks3);
396 
397  DES_ede3_cbc_encrypt(encrypt_start,
398  encrypt_start,
399  encrypt_len,
400  &ks1,
401  &ks2,
402  &ks3,
403  (DES_cblock *)iv,
404  1);
405  }
406 
407  /* Since ESP can pad we can now fix IP length */
408  ip->tot_len = odp_cpu_to_be_16(data - (uint8_t *)ip);
409 
410  /* Close AH if specified */
411  if (ah) {
412  uint8_t hash[EVP_MAX_MD_SIZE];
413  int auth_len = data - (uint8_t *)ip;
414 
415  ah->next_header = ip->proto;
416  ip->proto = ODPH_IPPROTO_AH;
417 
418  HMAC(stream->evp_md,
419  entry->ah.key.data,
420  entry->ah.key.length,
421  (uint8_t *)ip,
422  auth_len,
423  hash,
424  NULL);
425 
426  memcpy(ah->icv, hash, entry->ah.icv_len);
427  }
428 
429  /* Correct set packet length offsets */
430  odp_packet_pull_tail(pkt, max_len - (data - base));
431  odp_packet_l2_offset_set(pkt, (uint8_t *)eth - base);
432  odp_packet_l3_offset_set(pkt, (uint8_t *)ip - base);
433  odp_packet_l4_offset_set(pkt, ((uint8_t *)ip - base) + sizeof(*ip));
434 
435  /* Now fill in final IP header fields */
436  ip->ttl = 64;
437  ip->tos = 0;
438  ip->frag_offset = 0;
439  ip->chksum = 0;
440  odph_ipv4_csum_update(pkt);
441  return pkt;
442 }
443 
444 odp_bool_t verify_ipv4_packet(stream_db_entry_t *stream,
445  odp_packet_t pkt)
446 {
447  ipsec_cache_entry_t *entry = NULL;
448  uint8_t *data;
449  odph_ipv4hdr_t *ip;
450  odph_ahhdr_t *ah = NULL;
451  odph_esphdr_t *esp = NULL;
452  int hdr_len;
453  odph_icmphdr_t *icmp;
454  stream_pkt_hdr_t *test;
455  uint32_t src_ip, dst_ip;
456 
457  if (stream->input.entry)
458  entry = stream->input.entry;
459  else if (stream->output.entry)
460  entry = stream->output.entry;
461 
462  /* Basic IPv4 verify (add checksum verification) */
463  data = odp_packet_l3_ptr(pkt, NULL);
464  ip = (odph_ipv4hdr_t *)data;
465  data += sizeof(*ip);
466  if (0x45 != ip->ver_ihl)
467  return FALSE;
468 
469  src_ip = odp_be_to_cpu_32(ip->src_addr);
470  dst_ip = odp_be_to_cpu_32(ip->dst_addr);
471  if ((stream->src_ip != src_ip) && stream->output.entry &&
472  (stream->output.entry->tun_src_ip != src_ip))
473  return FALSE;
474  if ((stream->dst_ip != dst_ip) && stream->output.entry &&
475  (stream->output.entry->tun_dst_ip != dst_ip))
476  return FALSE;
477 
478  if ((stream->src_ip != src_ip) && stream->input.entry &&
479  (stream->input.entry->tun_src_ip != src_ip))
480  return FALSE;
481  if ((stream->dst_ip != dst_ip) && stream->input.entry &&
482  (stream->input.entry->tun_dst_ip != dst_ip))
483  return FALSE;
484 
485  /* Find IPsec headers if any and compare against entry */
486  hdr_len = locate_ipsec_headers(ip, &ah, &esp);
487 
488  /* Verify if the packet is IPsec encapsulated or is cleartext as
489  * expected
490  */
491  if (((stream->output.entry && (!ah && !esp))) ||
492  (stream->input.entry && (ah || esp)))
493  return FALSE;
494 
495  /* Cleartext packet */
496  if (!ah && !esp)
497  goto clear_packet;
498  if (ah) {
499  if (!entry)
500  return FALSE;
501  if (ODP_AUTH_ALG_NULL == entry->ah.alg)
502  return FALSE;
503  if (odp_be_to_cpu_32(ah->spi) != entry->ah.spi)
504  return FALSE;
505  if (ODP_AUTH_ALG_MD5_HMAC != entry->ah.alg &&
506  ODP_AUTH_ALG_SHA1_HMAC != entry->ah.alg &&
507  ODP_AUTH_ALG_SHA256_HMAC != entry->ah.alg)
508  abort();
509  } else {
510  if (entry && (ODP_AUTH_ALG_NULL != entry->ah.alg))
511  return FALSE;
512  }
513  if (esp) {
514  if (!entry)
515  return FALSE;
516  if (ODP_CIPHER_ALG_NULL == entry->esp.alg)
517  return FALSE;
518  if (odp_be_to_cpu_32(esp->spi) != entry->esp.spi)
519  return FALSE;
520  if (ODP_CIPHER_ALG_3DES_CBC != entry->esp.alg)
521  abort();
522  hdr_len += entry->esp.iv_len;
523  } else {
524  if (entry && (ODP_CIPHER_ALG_NULL != entry->esp.alg))
525  return FALSE;
526  }
527  data += hdr_len;
528 
529  /* Verify authentication (if present) */
530  if (ah) {
531  uint8_t ip_tos;
532  uint8_t ip_ttl;
533  uint16_t ip_frag_offset;
534  uint8_t icv[entry->ah.icv_len];
535  uint8_t hash[EVP_MAX_MD_SIZE];
536 
537  /* Save/clear mutable fields */
538  ip_tos = ip->tos;
539  ip_ttl = ip->ttl;
540  ip_frag_offset = odp_be_to_cpu_16(ip->frag_offset);
541  ip->tos = 0;
542  ip->ttl = 0;
543  ip->frag_offset = 0;
544  ip->chksum = 0;
545  memcpy(icv, ah->icv, entry->ah.icv_len);
546  memset(ah->icv, 0, entry->ah.icv_len);
547 
548  /* Calculate HMAC and compare */
549  HMAC(stream->evp_md,
550  entry->ah.key.data,
551  entry->ah.key.length,
552  (uint8_t *)ip,
553  odp_be_to_cpu_16(ip->tot_len),
554  hash,
555  NULL);
556 
557  if (0 != memcmp(icv, hash, sizeof(icv)))
558  return FALSE;
559 
560  ip->proto = ah->next_header;
561  ip->tos = ip_tos;
562  ip->ttl = ip_ttl;
563  ip->frag_offset = odp_cpu_to_be_16(ip_frag_offset);
564  }
565 
566  /* Decipher if present */
567  if (esp) {
568  odph_esptrl_t *esp_t;
569  DES_key_schedule ks1, ks2, ks3;
570  uint8_t iv[8];
571  int encrypt_len = ipv4_data_len(ip) - hdr_len;
572 
573  memcpy(iv, esp->iv, sizeof(iv));
574 
575  DES_set_key((DES_cblock *)&entry->esp.key.data[0], &ks1);
576  DES_set_key((DES_cblock *)&entry->esp.key.data[8], &ks2);
577  DES_set_key((DES_cblock *)&entry->esp.key.data[16], &ks3);
578 
579  DES_ede3_cbc_encrypt((uint8_t *)data,
580  (uint8_t *)data,
581  encrypt_len,
582  &ks1,
583  &ks2,
584  &ks3,
585  (DES_cblock *)iv,
586  0);
587 
588  esp_t = (odph_esptrl_t *)(data + encrypt_len) - 1;
589  ip->proto = esp_t->next_header;
590  }
591 
592 clear_packet:
593  /* Verify IP/ICMP packet */
594  if (entry && (entry->mode == IPSEC_SA_MODE_TUNNEL) && (ah || esp)) {
595  if (ODPH_IPV4 != ip->proto)
596  return FALSE;
597  odph_ipv4hdr_t *inner_ip = (odph_ipv4hdr_t *)data;
598 
599  icmp = (odph_icmphdr_t *)(inner_ip + 1);
600  data = (uint8_t *)icmp;
601  } else {
602  if (ODPH_IPPROTO_ICMPV4 != ip->proto)
603  return FALSE;
604  icmp = (odph_icmphdr_t *)data;
605  }
606 
607  /* Verify ICMP header */
608  data += sizeof(*icmp);
609  if (ODPH_ICMP_ECHO != icmp->type)
610  return FALSE;
611  if (0x1234 != odp_be_to_cpu_16(icmp->un.echo.id))
612  return FALSE;
613 
614  /* Now check our packet */
615  test = (stream_pkt_hdr_t *)data;
616  if (STREAM_MAGIC != odp_be_to_cpu_64(test->magic))
617  return FALSE;
618 
619  return TRUE;
620 }
621 
622 int create_stream_db_inputs(void)
623 {
624  int created = 0;
625  odp_pool_t pkt_pool;
626  odp_pool_info_t pool_info;
627  stream_db_entry_t *stream = NULL;
628  uint32_t max_len;
629 
630  /* Lookup the packet pool */
631  pkt_pool = odp_pool_lookup("packet_pool");
632  if (pkt_pool == ODP_POOL_INVALID) {
633  ODPH_ERR("Error: pkt_pool not found\n");
634  return -1;
635  }
636  if (odp_pool_info(pkt_pool, &pool_info)) {
637  ODPH_ERR("Error: pool info failed\n");
638  return -1;
639  }
640 
641  /* Only single segment packets are supported */
642  max_len = pool_info.params.pkt.seg_len;
643 
644  /* For each stream create corresponding input packets */
645  for (stream = stream_db->list; NULL != stream; stream = stream->next) {
646  int count;
647  int ret;
648  uint8_t dmac[ODPH_ETHADDR_LEN];
649  odp_pktout_queue_t queue;
650 
651  ret = odp_pktio_mac_addr(stream->input.pktio,
652  dmac, sizeof(dmac));
653  if (ret <= 0) {
654  ODPH_ERR("Error: failed during MAC address get for "
655  "%s\n", stream->input.intf);
656  continue;
657  }
658 
659  ret = odp_pktout_queue(stream->input.pktio, &queue, 1);
660  if (ret < 1) {
661  ODPH_ERR("Error: failed to get outqueue for %s\n",
662  stream->input.intf);
663  continue;
664  }
665 
666  for (count = stream->count; count > 0; count--) {
667  odp_packet_t pkt;
668 
669  pkt = create_ipv4_packet(stream, dmac, pkt_pool, max_len);
670  if (ODP_PACKET_INVALID == pkt) {
671  ODPH_ERR("Error: packet buffers exhausted\n");
672  break;
673  }
674  stream->created++;
675  if (odp_pktout_send(queue, &pkt, 1) != 1) {
676  odp_packet_free(pkt);
677  ODPH_ERR("Error: queue enqueue failed\n");
678  break;
679  }
680 
681  /* Count this stream when we create first packet */
682  if (1 == stream->created)
683  created++;
684  }
685  }
686  if ((stream_db->index > 0) && created == 0) {
687  ODPH_ERR("Error: failed to create any input streams\n");
688  return -1;
689  }
690 
691  return created;
692 }
693 
694 odp_bool_t verify_stream_db_outputs(void)
695 {
696  odp_bool_t done = TRUE;
697  stream_db_entry_t *stream = NULL;
698  const char *env;
699 
700  env = getenv("ODP_IPSEC_STREAM_VERIFY_MDEQ");
701  /* For each stream look for output packets */
702  for (stream = stream_db->list; NULL != stream; stream = stream->next) {
703  int idx;
704  int count;
705  int ret;
706  odp_queue_t queue;
707  odp_event_t ev_tbl[LOOP_DEQ_COUNT];
708 
709  ret = odp_pktin_event_queue(stream->output.pktio, &queue, 1);
710  if (ret < 1) {
711  ODPH_ERR("Error: failed to get inqueue for %s\n",
712  stream->output.intf);
713  continue;
714  }
715 
716  for (;;) {
717  if (env) {
718  count = odp_queue_deq_multi(queue,
719  ev_tbl,
720  LOOP_DEQ_COUNT);
721  } else {
722  ev_tbl[0] = odp_queue_deq(queue);
723  count = (ev_tbl[0] != ODP_EVENT_INVALID) ?
724  1 : 0;
725  }
726  if (!count)
727  break;
728  for (idx = 0; idx < count; idx++) {
729  odp_bool_t good;
730  odp_packet_t pkt;
731 
732  pkt = odp_packet_from_event(ev_tbl[idx]);
733 
734  good = verify_ipv4_packet(stream, pkt);
735  if (good)
736  stream->verified++;
737  odp_packet_free(pkt);
738  }
739  }
740 
741  printf("Stream %d %d\n", stream->created, stream->verified);
742 
743  if (stream->created != stream->verified)
744  done = FALSE;
745  }
746  return done;
747 }
uint16_t odp_chksum_ones_comp16(const void *data, uint32_t data_len)
Ones' complement sum of 16-bit words.
#define ODP_PACKED
Defines type/struct to be packed.
odp_u16be_t odp_cpu_to_be_16(uint16_t cpu16)
Convert cpu native uint16_t to 16bit big endian.
odp_u64be_t odp_cpu_to_be_64(uint64_t cpu64)
Convert cpu native uint64_t to 64bit big endian.
uint16_t odp_be_to_cpu_16(odp_u16be_t be16)
Convert 16bit big endian to cpu native uint16_t.
uint64_t odp_be_to_cpu_64(odp_u64be_t be64)
Convert 64bit big endian to cpu native uint64_t.
odp_u32be_t odp_cpu_to_be_32(uint32_t cpu32)
Convert cpu native uint32_t to 32bit big endian.
uint64_t odp_u64be_t
unsigned 64bit big endian
uint32_t odp_be_to_cpu_32(odp_u32be_t be32)
Convert 32bit big endian to cpu native uint32_t.
odp_auth_alg_t
Crypto API authentication algorithm.
@ ODP_CIPHER_ALG_3DES_CBC
Triple DES with cipher block chaining.
@ ODP_CIPHER_ALG_NULL
No cipher algorithm specified.
@ ODP_AUTH_ALG_NULL
No authentication algorithm specified.
@ ODP_AUTH_ALG_MD5_HMAC
HMAC-MD5.
@ ODP_AUTH_ALG_SHA1_HMAC
HMAC-SHA-1.
@ ODP_AUTH_ALG_SHA256_HMAC
HMAC-SHA-256.
#define ODP_EVENT_INVALID
Invalid event.
int odp_pktio_mac_addr(odp_pktio_t pktio, void *mac_addr, int size)
Get the default MAC address of a packet IO interface.
odp_pktio_t odp_pktio_lookup(const char *name)
Return a packet IO handle for an already open device.
int odp_pktout_queue(odp_pktio_t pktio, odp_pktout_queue_t queues[], int num)
Direct packet output queues.
int odp_pktin_event_queue(odp_pktio_t pktio, odp_queue_t queues[], int num)
Event queues for packet input.
int odp_pktout_send(odp_pktout_queue_t queue, const odp_packet_t packets[], int num)
Send packets directly to an interface output queue.
int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset)
Set layer 3 start offset.
void * odp_packet_data(odp_packet_t pkt)
Packet data pointer.
int odp_packet_l4_offset_set(odp_packet_t pkt, uint32_t offset)
Set layer 4 start offset.
void odp_packet_has_eth_set(odp_packet_t pkt, int val)
Set flag for Ethernet header.
odp_packet_t odp_packet_alloc(odp_pool_t pool, uint32_t len)
Allocate a packet from a packet pool.
int odp_packet_l2_offset_set(odp_packet_t pkt, uint32_t offset)
Set layer 2 start offset.
odp_packet_t odp_packet_from_event(odp_event_t ev)
Get packet handle from event.
void odp_packet_free(odp_packet_t pkt)
Free packet.
#define ODP_PACKET_INVALID
Invalid packet.
void * odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len)
Layer 3 start pointer.
void * odp_packet_pull_tail(odp_packet_t pkt, uint32_t len)
Pull in packet tail.
void odp_packet_has_ipv4_set(odp_packet_t pkt, int val)
Set flag for IPv4.
odp_pool_t odp_pool_lookup(const char *name)
Find a pool by name.
int odp_pool_info(odp_pool_t pool, odp_pool_info_t *info)
Retrieve information about a pool.
#define ODP_POOL_INVALID
Invalid pool.
odp_event_t odp_queue_deq(odp_queue_t queue)
Dequeue an event from a queue.
int odp_queue_deq_multi(odp_queue_t queue, odp_event_t events[], int num)
Dequeue multiple events from a queue.
odp_shm_t odp_shm_lookup(const char *name)
Lookup for a block of shared memory.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
#define ODP_SHM_INVALID
Invalid shared memory block.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align, uint32_t flags)
Reserve a contiguous block of shared memory.
bool odp_bool_t
Boolean type.
The OpenDataPlane API.
Pool information struct Used to get information about a pool.
odp_pool_param_t params
Copy of pool parameters.
uint32_t seg_len
Minimum number of packet data bytes that can be stored in the first segment of a newly allocated pack...
struct odp_pool_param_t::@126 pkt
Parameters for packet pools.