/** * Initialize loopback * * Initialize ODP queues to create our own idea of loopbacks, which allow * testing without physical interfaces. Interface name string will be of * the format "loopX" where X is the decimal number of the interface. * * @param intf Loopback interface name string */ #if 0 /* Temporarely disable loopback mode. Needs packet output event queues */ static void initialize_loop(char *intf) { int idx; odp_queue_t outq_def; odp_queue_t inq_def; char queue_name[ODP_QUEUE_NAME_LEN]; odp_queue_param_t qparam; uint8_t *mac; char mac_str[MAX_STRING]; /* Derive loopback interface index */ idx = loop_if_index(intf); if (idx < 0) { EXAMPLE_ERR("Error: loopback \"%s\" invalid\n", intf); exit(EXIT_FAILURE); } /* Create input queue */ odp_queue_param_init(&qparam); qparam.type = ODP_QUEUE_TYPE_SCHED; qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; qparam.sched.group = ODP_SCHED_GROUP_ALL; snprintf(queue_name, sizeof(queue_name), "%i-loop_inq_def", idx); queue_name[ODP_QUEUE_NAME_LEN - 1] = '\0'; inq_def = queue_create(queue_name, &qparam); if (ODP_QUEUE_INVALID == inq_def) { EXAMPLE_ERR("Error: input queue creation failed for %s\n", intf); exit(EXIT_FAILURE); } /* Create output queue */ snprintf(queue_name, sizeof(queue_name), "%i-loop_outq_def", idx); queue_name[ODP_QUEUE_NAME_LEN - 1] = '\0'; outq_def = queue_create(queue_name, NULL); if (ODP_QUEUE_INVALID == outq_def) { EXAMPLE_ERR("Error: output queue creation failed for %s\n", intf); exit(EXIT_FAILURE); } /* Initialize the loopback DB entry */ create_loopback_db_entry(idx, inq_def, outq_def, pkt_pool); mac = query_loopback_db_mac(idx); printf("Created loop:%02i, queue mode (ATOMIC queues)\n" " default loop%02i-INPUT queue:%" PRIu64 "\n" " default loop%02i-OUTPUT queue:%" PRIu64 "\n" " source mac address %s\n", idx, idx, odp_queue_to_u64(inq_def), idx, odp_queue_to_u64(outq_def), mac_addr_str(mac_str, mac)); /* Resolve any routes using this interface for output */ resolve_fwd_db(intf, outq_def, mac); }
/** * IPsec pre argument processing intialization */ static void ipsec_init_pre(void) { odp_queue_param_t qparam; odp_pool_param_t params; /* * Create queues * * - completion queue (should eventually be ORDERED) * - sequence number queue (must be ATOMIC) */ odp_queue_param_init(&qparam); qparam.type = ODP_QUEUE_TYPE_SCHED; qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; qparam.sched.group = ODP_SCHED_GROUP_ALL; completionq = queue_create("completion", &qparam); if (ODP_QUEUE_INVALID == completionq) { EXAMPLE_ERR("Error: completion queue creation failed\n"); exit(EXIT_FAILURE); } qparam.type = ODP_QUEUE_TYPE_SCHED; qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; qparam.sched.group = ODP_SCHED_GROUP_ALL; seqnumq = queue_create("seqnum", &qparam); if (ODP_QUEUE_INVALID == seqnumq) { EXAMPLE_ERR("Error: sequence number queue creation failed\n"); exit(EXIT_FAILURE); } /* Create output buffer pool */ odp_pool_param_init(¶ms); params.pkt.seg_len = SHM_OUT_POOL_BUF_SIZE; params.pkt.len = SHM_OUT_POOL_BUF_SIZE; params.pkt.num = SHM_PKT_POOL_BUF_COUNT; params.type = ODP_POOL_PACKET; out_pool = odp_pool_create("out_pool", ¶ms); if (ODP_POOL_INVALID == out_pool) { EXAMPLE_ERR("Error: message pool create failed.\n"); exit(EXIT_FAILURE); } /* Initialize our data bases */ init_sp_db(); init_sa_db(); init_tun_db(); init_ipsec_cache(); }
/** * @internal Worker thread * * @param ptr Pointer to test arguments * * @return Pointer to exit status */ static void *run_thread(void *ptr) { int thr; odp_pool_t msg_pool; test_globals_t *gbls; gbls = ptr; thr = odp_thread_id(); printf("Thread %i starts on cpu %i\n", thr, odp_cpu_id()); /* * Find the pool */ msg_pool = odp_pool_lookup("msg_pool"); if (msg_pool == ODP_POOL_INVALID) { EXAMPLE_ERR(" [%i] msg_pool not found\n", thr); return NULL; } odp_barrier_wait(&gbls->test_barrier); test_abs_timeouts(thr, gbls); printf("Thread %i exits\n", thr); fflush(NULL); return NULL; }
int main(int argc, char *argv[]) { odp_instance_t instance; odp_platform_init_t plat_idata; int ret; /* Parse and store the application arguments */ parse_args(argc, argv); memset(&plat_idata, 0, sizeof(odp_platform_init_t)); plat_idata.ipc_ns = ipc_name_space; if (odp_init_global(&instance, NULL, &plat_idata)) { EXAMPLE_ERR("Error: ODP global init failed.\n"); exit(EXIT_FAILURE); } /* Init this thread */ if (odp_init_local(instance, ODP_THREAD_CONTROL)) { EXAMPLE_ERR("Error: ODP local init failed.\n"); exit(EXIT_FAILURE); } ret = ipc_second_process(); if (odp_term_local()) { EXAMPLE_ERR("Error: odp_term_local() failed.\n"); exit(EXIT_FAILURE); } if (odp_term_global(instance)) { EXAMPLE_ERR("Error: odp_term_global() failed.\n"); exit(EXIT_FAILURE); } return ret; }
void init_ipsec_cache(void) { odp_shm_t shm; shm = odp_shm_reserve("shm_ipsec_cache", sizeof(ipsec_cache_t), ODP_CACHE_LINE_SIZE, 0); ipsec_cache = odp_shm_addr(shm); if (ipsec_cache == NULL) { EXAMPLE_ERR("Error: shared mem alloc failed.\n"); exit(EXIT_FAILURE); } memset(ipsec_cache, 0, sizeof(*ipsec_cache)); }
void init_stream_db(void) { odp_shm_t shm; shm = odp_shm_reserve("stream_db", sizeof(stream_db_t), ODP_CACHE_LINE_SIZE, 0); stream_db = odp_shm_addr(shm); if (stream_db == NULL) { EXAMPLE_ERR("Error: shared mem alloc failed.\n"); exit(EXIT_FAILURE); } memset(stream_db, 0, sizeof(*stream_db)); }
/** * IPsec post argument processing intialization * * Resolve SP DB with SA DB and create corresponding IPsec cache entries * * @param api_mode Mode to use when invoking per packet crypto API */ static void ipsec_init_post(crypto_api_mode_e api_mode) { sp_db_entry_t *entry; /* Attempt to find appropriate SA for each SP */ for (entry = sp_db->list; NULL != entry; entry = entry->next) { sa_db_entry_t *cipher_sa = NULL; sa_db_entry_t *auth_sa = NULL; tun_db_entry_t *tun = NULL; if (entry->esp) { cipher_sa = find_sa_db_entry(&entry->src_subnet, &entry->dst_subnet, 1); tun = find_tun_db_entry(cipher_sa->src_ip, cipher_sa->dst_ip); } if (entry->ah) { auth_sa = find_sa_db_entry(&entry->src_subnet, &entry->dst_subnet, 0); tun = find_tun_db_entry(auth_sa->src_ip, auth_sa->dst_ip); } if (cipher_sa || auth_sa) { if (create_ipsec_cache_entry(cipher_sa, auth_sa, tun, api_mode, entry->input, completionq, out_pool)) { EXAMPLE_ERR("Error: IPSec cache entry failed.\n" ); exit(EXIT_FAILURE); } } else { printf(" WARNING: SA not found for SP\n"); dump_sp_db_entry(entry); } } }
/** * Main receive function * * @param arg thread arguments of type 'thread_args_t *' */ static void *gen_recv_thread(void *arg) { int thr; odp_pktio_t pktio; thread_args_t *thr_args; odp_packet_t pkt; odp_event_t ev; thr = odp_thread_id(); thr_args = arg; pktio = odp_pktio_lookup(thr_args->pktio_dev); if (pktio == ODP_PKTIO_INVALID) { EXAMPLE_ERR(" [%02i] Error: lookup of pktio %s failed\n", thr, thr_args->pktio_dev); return NULL; } printf(" [%02i] created mode: RECEIVE\n", thr); for (;;) { if (args->appl.number != -1 && odp_atomic_load_u64(&counters.icmp) >= (unsigned int)args->appl.number) { break; } /* Use schedule to get buf from any input queue */ ev = odp_schedule(NULL, ODP_SCHED_WAIT); pkt = odp_packet_from_event(ev); /* Drop packets with errors */ if (odp_unlikely(odp_packet_has_error(pkt))) { odp_packet_free(pkt); continue; } print_pkts(thr, &pkt, 1); odp_packet_free(pkt); } return arg; }
int create_stream_db_inputs(void) { int created = 0; odp_pool_t pkt_pool; stream_db_entry_t *stream = NULL; /* Lookup the packet pool */ pkt_pool = odp_pool_lookup("packet_pool"); if (pkt_pool == ODP_POOL_INVALID) { EXAMPLE_ERR("Error: pkt_pool not found\n"); exit(EXIT_FAILURE); } /* For each stream create corresponding input packets */ for (stream = stream_db->list; NULL != stream; stream = stream->next) { int count; uint8_t *dmac = query_loopback_db_mac(stream->input.loop); odp_queue_t queue = query_loopback_db_inq(stream->input.loop); for (count = stream->count; count > 0; count--) { odp_packet_t pkt; pkt = create_ipv4_packet(stream, dmac, pkt_pool); if (ODP_PACKET_INVALID == pkt) { printf("Packet buffers exhausted\n"); break; } stream->created++; if (odp_queue_enq(queue, odp_packet_to_event(pkt))) { odp_packet_free(pkt); printf("Queue enqueue failed\n"); break; } /* Count this stream when we create first packet */ if (1 == stream->created) created++; } } return created; }
/** * Initialize interface * * Initialize ODP pktio and queues, query MAC address and update * forwarding database. * * @param intf Interface name string */ static void initialize_intf(char *intf) { odp_pktio_t pktio; odp_pktout_queue_t pktout; odp_queue_t inq; int ret; uint8_t src_mac[ODPH_ETHADDR_LEN]; char src_mac_str[MAX_STRING]; odp_pktio_param_t pktio_param; odp_pktin_queue_param_t pktin_param; odp_pktio_param_init(&pktio_param); if (getenv("ODP_IPSEC_USE_POLL_QUEUES")) pktio_param.in_mode = ODP_PKTIN_MODE_QUEUE; else pktio_param.in_mode = ODP_PKTIN_MODE_SCHED; /* * Open a packet IO instance for thread and get default output queue */ pktio = odp_pktio_open(intf, pkt_pool, &pktio_param); if (ODP_PKTIO_INVALID == pktio) { EXAMPLE_ERR("Error: pktio create failed for %s\n", intf); exit(EXIT_FAILURE); } odp_pktin_queue_param_init(&pktin_param); pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC; if (odp_pktin_queue_config(pktio, &pktin_param)) { EXAMPLE_ERR("Error: pktin config failed for %s\n", intf); exit(EXIT_FAILURE); } if (odp_pktout_queue_config(pktio, NULL)) { EXAMPLE_ERR("Error: pktout config failed for %s\n", intf); exit(EXIT_FAILURE); } if (odp_pktin_event_queue(pktio, &inq, 1) != 1) { EXAMPLE_ERR("Error: failed to get input queue for %s\n", intf); exit(EXIT_FAILURE); } if (odp_pktout_queue(pktio, &pktout, 1) != 1) { EXAMPLE_ERR("Error: failed to get pktout queue for %s\n", intf); exit(EXIT_FAILURE); } ret = odp_pktio_start(pktio); if (ret) { EXAMPLE_ERR("Error: unable to start %s\n", intf); exit(EXIT_FAILURE); } /* Read the source MAC address for this interface */ ret = odp_pktio_mac_addr(pktio, src_mac, sizeof(src_mac)); if (ret <= 0) { EXAMPLE_ERR("Error: failed during MAC address get for %s\n", intf); exit(EXIT_FAILURE); } printf("Created pktio:%02" PRIu64 ", queue mode (ATOMIC queues)\n" " default pktio%02" PRIu64 "-INPUT queue:%" PRIu64 "\n" " source mac address %s\n", odp_pktio_to_u64(pktio), odp_pktio_to_u64(pktio), odp_queue_to_u64(inq), mac_addr_str(src_mac_str, src_mac)); /* Resolve any routes using this interface for output */ resolve_fwd_db(intf, pktout, src_mac); }
static void *gen_send_thread(void *arg) { int thr; odp_pktio_t pktio; thread_args_t *thr_args; odp_queue_t outq_def; odp_packet_t pkt[PKT_BURST_SZ]; thr = odp_thread_id(); thr_args = arg; pktio = odp_pktio_lookup(thr_args->pktio_dev); if (pktio == ODP_PKTIO_INVALID) { EXAMPLE_ERR(" [%02i] Error: lookup of pktio %s failed\n", thr, thr_args->pktio_dev); return NULL; } outq_def = odp_pktio_outq_getdef(pktio); if (outq_def == ODP_QUEUE_INVALID) { EXAMPLE_ERR(" [%02i] Error: def output-Q query\n", thr); return NULL; } printf(" [%02i] created mode: SEND\n", thr); for (int i = 0; i < PKT_BURST_SZ; ++i) { if (args->appl.mode == APPL_MODE_UDP) pkt[i] = pack_udp_pkt(thr_args->pool); else if (args->appl.mode == APPL_MODE_PING) pkt[i] = pack_icmp_pkt(thr_args->pool); else pkt[i] = ODP_PACKET_INVALID; if (!odp_packet_is_valid(pkt[i])) { EXAMPLE_ERR(" [%2i] alloc_single failed\n", thr); return NULL; } } for (;;) { int err; err = odp_queue_enq_multi(outq_def, (odp_event_t*)pkt, PKT_BURST_SZ); if (err != PKT_BURST_SZ) { /* EXAMPLE_ERR(" [%02i] send pkt err!\n", thr); */ /* return NULL; */ } static uint64_t toto = 0; if (args->appl.interval != 0) { printf(" [%02i] send pkt no:%"PRIu64" seq %"PRIu64"\n", thr, odp_atomic_load_u64(&counters.seq), toto++); usleep(args->appl.interval); /* millisleep(args->appl.interval, */ /* thr_args->tp, */ /* thr_args->tim, */ /* thr_args->tq, */ /* thr_args->tmo_ev); */ } } printf("Done\n"); _exit(0); /* receive number of reply pks until timeout */ if (args->appl.mode == APPL_MODE_PING && args->appl.number > 0) { while (args->appl.timeout >= 0) { if (odp_atomic_load_u64(&counters.icmp) >= (unsigned int)args->appl.number) break; millisleep(DEFAULT_PKT_INTERVAL, thr_args->tp, thr_args->tim, thr_args->tq, thr_args->tmo_ev); args->appl.timeout--; } } return arg; }
/** * Initialize interface * * Initialize ODP pktio and queues, query MAC address and update * forwarding database. * * @param intf Interface name string */ static void initialize_intf(char *intf) { odp_pktio_t pktio; odp_queue_t outq_def; odp_queue_t inq_def; char inq_name[ODP_QUEUE_NAME_LEN]; odp_queue_param_t qparam; int ret; uint8_t src_mac[ODPH_ETHADDR_LEN]; char src_mac_str[MAX_STRING]; odp_pktio_param_t pktio_param; odp_pktio_param_init(&pktio_param); if (getenv("ODP_IPSEC_USE_POLL_QUEUES")) pktio_param.in_mode = ODP_PKTIN_MODE_QUEUE; else pktio_param.in_mode = ODP_PKTIN_MODE_SCHED; /* * Open a packet IO instance for thread and get default output queue */ pktio = odp_pktio_open(intf, pkt_pool, &pktio_param); if (ODP_PKTIO_INVALID == pktio) { EXAMPLE_ERR("Error: pktio create failed for %s\n", intf); exit(EXIT_FAILURE); } outq_def = odp_pktio_outq_getdef(pktio); /* * Create and set the default INPUT queue associated with the 'pktio' * resource */ odp_queue_param_init(&qparam); qparam.type = ODP_QUEUE_TYPE_PKTIN; qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; qparam.sched.group = ODP_SCHED_GROUP_ALL; snprintf(inq_name, sizeof(inq_name), "%" PRIu64 "-pktio_inq_def", odp_pktio_to_u64(pktio)); inq_name[ODP_QUEUE_NAME_LEN - 1] = '\0'; inq_def = queue_create(inq_name, &qparam); if (ODP_QUEUE_INVALID == inq_def) { EXAMPLE_ERR("Error: pktio queue creation failed for %s\n", intf); exit(EXIT_FAILURE); } ret = odp_pktio_inq_setdef(pktio, inq_def); if (ret) { EXAMPLE_ERR("Error: default input-Q setup for %s\n", intf); exit(EXIT_FAILURE); } ret = odp_pktio_start(pktio); if (ret) { EXAMPLE_ERR("Error: unable to start %s\n", intf); exit(EXIT_FAILURE); } /* Read the source MAC address for this interface */ ret = odp_pktio_mac_addr(pktio, src_mac, sizeof(src_mac)); if (ret <= 0) { EXAMPLE_ERR("Error: failed during MAC address get for %s\n", intf); exit(EXIT_FAILURE); } printf("Created pktio:%02" PRIu64 ", queue mode (ATOMIC queues)\n" " default pktio%02" PRIu64 "-INPUT queue:%" PRIu64 "\n" " source mac address %s\n", odp_pktio_to_u64(pktio), odp_pktio_to_u64(pktio), odp_queue_to_u64(inq_def), mac_addr_str(src_mac_str, src_mac)); /* Resolve any routes using this interface for output */ resolve_fwd_db(intf, outq_def, src_mac); }
int create_stream_db_entry(char *input) { int pos = 0; char *local; char *str; char *save; char *token; stream_db_entry_t *entry = &stream_db->array[stream_db->index]; /* Verify we have a good entry */ if (MAX_DB <= stream_db->index) return -1; /* Make a local copy */ local = malloc(strlen(input) + 1); if (NULL == local) return -1; strcpy(local, input); /* Setup for using "strtok_r" to search input string */ str = local; save = NULL; /* Parse tokens separated by ':' */ while (NULL != (token = strtok_r(str, ":", &save))) { str = NULL; /* reset str for subsequent strtok_r calls */ /* Parse token based on its position */ switch (pos) { case 0: parse_ipv4_string(token, &entry->src_ip, NULL); break; case 1: parse_ipv4_string(token, &entry->dst_ip, NULL); break; case 2: entry->input.loop = loop_if_index(token); if (entry->input.loop < 0) { EXAMPLE_ERR("Error: stream must have input" " loop\n"); exit(EXIT_FAILURE); } break; case 3: entry->output.loop = loop_if_index(token); break; case 4: entry->count = atoi(token); break; case 5: entry->length = atoi(token); if (entry->length < sizeof(stream_pkt_hdr_t)) entry->length = 0; else entry->length -= sizeof(stream_pkt_hdr_t); break; default: printf("ERROR: extra token \"%s\" at position %d\n", token, pos); break; } /* Advance to next position */ pos++; } /* Verify we parsed exactly the number of tokens we expected */ if (6 != pos) { printf("ERROR: \"%s\" contains %d tokens, expected 6\n", input, pos); free(local); return -1; } /* Add stream to the list */ entry->id = stream_db->index++; entry->next = stream_db->list; stream_db->list = entry; free(local); return 0; }
static int ipc_second_process(void) { odp_pktio_t ipc_pktio; odp_pool_param_t params; odp_pool_t pool; odp_packet_t pkt_tbl[MAX_PKT_BURST]; odp_packet_t alloc_pkt; int pkts; int ret; int i; odp_time_t start_cycle; odp_time_t cycle; odp_time_t diff; odp_time_t wait; uint64_t stat_pkts = 0; odp_pktin_queue_t pktin; /* Create packet pool */ memset(¶ms, 0, sizeof(params)); params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; params.pkt.len = SHM_PKT_POOL_BUF_SIZE; params.pkt.num = SHM_PKT_POOL_SIZE; params.type = ODP_POOL_PACKET; pool = odp_pool_create("packet_pool2", ¶ms); if (pool == ODP_POOL_INVALID) { EXAMPLE_ERR("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } ipc_pktio = create_pktio(pool); wait = odp_time_local_from_ns(run_time_sec * ODP_TIME_SEC_IN_NS); start_cycle = odp_time_local(); if (odp_pktin_queue(ipc_pktio, &pktin, 1) != 1) { EXAMPLE_ERR("no input queue\n"); return -1; } /* start ipc pktio, i.e. wait until other process connects */ for (;;) { /* 1. exit loop if time specified */ if (run_time_sec) { cycle = odp_time_local(); diff = odp_time_diff(cycle, start_cycle); if (odp_time_cmp(wait, diff) < 0) { printf("timeout exit, run_time_sec %d\n", run_time_sec); goto not_started; } } ret = odp_pktio_start(ipc_pktio); if (!ret) break; } for (;;) { /* exit loop if time specified */ if (run_time_sec) { cycle = odp_time_local(); diff = odp_time_diff(cycle, start_cycle); if (odp_time_cmp(wait, diff) < 0) { EXAMPLE_DBG("exit after %d seconds\n", run_time_sec); break; } } /* recv some packets and change MAGIC to MAGIC_2 */ pkts = odp_pktin_recv(pktin, pkt_tbl, MAX_PKT_BURST); if (pkts <= 0) continue; for (i = 0; i < pkts; i++) { odp_packet_t pkt = pkt_tbl[i]; pkt_head_t head; size_t off; off = odp_packet_l4_offset(pkt); if (off == ODP_PACKET_OFFSET_INVALID) EXAMPLE_ABORT("invalid l4 offset\n"); off += ODPH_UDPHDR_LEN; ret = odp_packet_copy_to_mem(pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable copy out head data"); if (head.magic != TEST_SEQ_MAGIC) EXAMPLE_ABORT("Wrong head magic!"); /* Modify magic number in packet */ head.magic = TEST_SEQ_MAGIC_2; ret = odp_packet_copy_from_mem(pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable to copy in head data"); } /* send all packets back */ ret = ipc_odp_packet_send_or_free(ipc_pktio, pkt_tbl, pkts); if (ret < 0) EXAMPLE_ABORT("can not send packets\n"); stat_pkts += ret; /* alloc packet from local pool, set magic to ALLOC_MAGIC, * and send it.*/ alloc_pkt = odp_packet_alloc(pool, SHM_PKT_POOL_BUF_SIZE); if (alloc_pkt != ODP_PACKET_INVALID) { pkt_head_t head; size_t off; odp_packet_l4_offset_set(alloc_pkt, 30); head.magic = TEST_ALLOC_MAGIC; off = odp_packet_l4_offset(alloc_pkt); off += ODPH_UDPHDR_LEN; ret = odp_packet_copy_from_mem(alloc_pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable to copy in head data"); pkt_tbl[0] = alloc_pkt; ret = ipc_odp_packet_send_or_free(ipc_pktio, pkt_tbl, 1); if (ret < 0) EXAMPLE_ABORT("can not send packets\n"); stat_pkts += 1; } } /* cleanup and exit */ ret = odp_pktio_stop(ipc_pktio); if (ret) { EXAMPLE_DBG("ipc2: odp_pktio_stop error %d\n", ret); return -1; } not_started: ret = odp_pktio_close(ipc_pktio); if (ret) { EXAMPLE_DBG("ipc2: odp_pktio_close error %d\n", ret); return -1; } ret = odp_pool_destroy(pool); if (ret) EXAMPLE_DBG("ipc2: pool_destroy error %d\n", ret); return stat_pkts > 1000 ? 0 : -1; }
/** @private test timeout */ static void test_abs_timeouts(int thr, test_globals_t *gbls) { uint64_t period; uint64_t period_ns; odp_queue_t queue; uint64_t tick; struct test_timer *ttp; odp_timeout_t tmo; uint32_t num_workers = gbls->num_workers; EXAMPLE_DBG(" [%i] test_timeouts\n", thr); queue = odp_queue_lookup("timer_queue"); period_ns = gbls->args.period_us * ODP_TIME_USEC; period = odp_timer_ns_to_tick(gbls->tp, period_ns); EXAMPLE_DBG(" [%i] period %d ticks, %d ns\n", thr, period, period_ns); EXAMPLE_DBG(" [%i] current tick %d\n", thr, odp_timer_current_tick(gbls->tp)); ttp = &gbls->tt[thr]; ttp->tim = odp_timer_alloc(gbls->tp, queue, ttp); if (ttp->tim == ODP_TIMER_INVALID) { EXAMPLE_ERR("Failed to allocate timer\n"); return; } tmo = odp_timeout_alloc(gbls->pool); if (tmo == ODP_TIMEOUT_INVALID) { EXAMPLE_ERR("Failed to allocate timeout\n"); return; } ttp->ev = odp_timeout_to_event(tmo); tick = odp_timer_current_tick(gbls->tp); while (1) { int wait = 0; odp_event_t ev; odp_timer_set_t rc; if (ttp) { tick += period; rc = odp_timer_set_abs(ttp->tim, tick, &ttp->ev); if (odp_unlikely(rc != ODP_TIMER_SUCCESS)) /* Too early or too late timeout requested */ EXAMPLE_ABORT("odp_timer_set_abs() failed: %s\n", timerset2str(rc)); } /* Get the next expired timeout. * We invoke the scheduler in a loop with a timeout because * we are not guaranteed to receive any more timeouts. The * scheduler isn't guaranteeing fairness when scheduling * buffers to threads. * Use 1.5 second timeout for scheduler */ uint64_t sched_tmo = odp_schedule_wait_time(1500000000ULL); do { ev = odp_schedule(&queue, sched_tmo); /* Check if odp_schedule() timed out, possibly there * are no remaining timeouts to receive */ if ((++wait > WAIT_NUM) && (odp_atomic_load_u32(&gbls->remain) < num_workers)) EXAMPLE_ABORT("At least one TMO was lost\n"); } while (ev == ODP_EVENT_INVALID && (int)odp_atomic_load_u32(&gbls->remain) > 0); if (ev == ODP_EVENT_INVALID) break; /* No more timeouts */ if (odp_event_type(ev) != ODP_EVENT_TIMEOUT) /* Not a default timeout event */ EXAMPLE_ABORT("Unexpected event type (%u) received\n", odp_event_type(ev)); odp_timeout_t tmo = odp_timeout_from_event(ev); tick = odp_timeout_tick(tmo); ttp = odp_timeout_user_ptr(tmo); ttp->ev = ev; if (!odp_timeout_fresh(tmo)) /* Not the expected expiration tick, timer has * been reset or cancelled or freed */ EXAMPLE_ABORT("Unexpected timeout received (timer %x, tick %d)\n", ttp->tim, tick); EXAMPLE_DBG(" [%i] timeout, tick %d\n", thr, tick); uint32_t rx_num = odp_atomic_fetch_dec_u32(&gbls->remain); if (!rx_num) EXAMPLE_ABORT("Unexpected timeout received (timer %x, tick %d)\n", ttp->tim, tick); else if (rx_num > num_workers) continue; odp_timeout_free(odp_timeout_from_event(ttp->ev)); odp_timer_free(ttp->tim); ttp = NULL; } /* Remove any prescheduled events */ remove_prescheduled_events(); }
/** @private test timeout */ static void test_abs_timeouts(int thr, test_globals_t *gbls) { uint64_t period; uint64_t period_ns; odp_queue_t queue; uint64_t tick; struct test_timer *ttp; odp_timeout_t tmo; EXAMPLE_DBG(" [%i] test_timeouts\n", thr); queue = odp_queue_lookup("timer_queue"); period_ns = gbls->args.period_us*ODP_TIME_USEC; period = odp_timer_ns_to_tick(gbls->tp, period_ns); EXAMPLE_DBG(" [%i] period %"PRIu64" ticks, %"PRIu64" ns\n", thr, period, period_ns); EXAMPLE_DBG(" [%i] current tick %"PRIu64"\n", thr, odp_timer_current_tick(gbls->tp)); ttp = &gbls->tt[thr]; ttp->tim = odp_timer_alloc(gbls->tp, queue, ttp); if (ttp->tim == ODP_TIMER_INVALID) { EXAMPLE_ERR("Failed to allocate timer\n"); return; } tmo = odp_timeout_alloc(gbls->pool); if (tmo == ODP_TIMEOUT_INVALID) { EXAMPLE_ERR("Failed to allocate timeout\n"); return; } ttp->ev = odp_timeout_to_event(tmo); tick = odp_timer_current_tick(gbls->tp); while ((int)odp_atomic_load_u32(&gbls->remain) > 0) { odp_event_t ev; odp_timer_set_t rc; tick += period; rc = odp_timer_set_abs(ttp->tim, tick, &ttp->ev); if (odp_unlikely(rc != ODP_TIMER_SUCCESS)) { /* Too early or too late timeout requested */ EXAMPLE_ABORT("odp_timer_set_abs() failed: %s\n", timerset2str(rc)); } /* Get the next expired timeout. * We invoke the scheduler in a loop with a timeout because * we are not guaranteed to receive any more timeouts. The * scheduler isn't guaranteeing fairness when scheduling * buffers to threads. * Use 1.5 second timeout for scheduler */ uint64_t sched_tmo = odp_schedule_wait_time(1500000000ULL); do { ev = odp_schedule(&queue, sched_tmo); /* Check if odp_schedule() timed out, possibly there * are no remaining timeouts to receive */ } while (ev == ODP_EVENT_INVALID && (int)odp_atomic_load_u32(&gbls->remain) > 0); if (ev == ODP_EVENT_INVALID) break; /* No more timeouts */ if (odp_event_type(ev) != ODP_EVENT_TIMEOUT) { /* Not a default timeout event */ EXAMPLE_ABORT("Unexpected event type (%u) received\n", odp_event_type(ev)); } odp_timeout_t tmo = odp_timeout_from_event(ev); tick = odp_timeout_tick(tmo); ttp = odp_timeout_user_ptr(tmo); ttp->ev = ev; if (!odp_timeout_fresh(tmo)) { /* Not the expected expiration tick, timer has * been reset or cancelled or freed */ EXAMPLE_ABORT("Unexpected timeout received (timer %" PRIx32 ", tick %" PRIu64 ")\n", ttp->tim, tick); } EXAMPLE_DBG(" [%i] timeout, tick %"PRIu64"\n", thr, tick); odp_atomic_dec_u32(&gbls->remain); } /* Cancel and free last timer used */ (void)odp_timer_cancel(ttp->tim, &ttp->ev); if (ttp->ev != ODP_EVENT_INVALID) odp_timeout_free(odp_timeout_from_event(ttp->ev)); else EXAMPLE_ERR("Lost timeout event at timer cancel\n"); /* Since we have cancelled the timer, there is no timeout event to * return from odp_timer_free() */ (void)odp_timer_free(ttp->tim); /* Remove any prescheduled events */ remove_prescheduled_events(); }
/** * Test main function */ int main(int argc, char *argv[]) { odph_linux_pthread_t thread_tbl[MAX_WORKERS]; int num_workers; odp_queue_t queue; uint64_t cycles, ns; odp_queue_param_t param; odp_pool_param_t params; odp_timer_pool_param_t tparams; odp_timer_pool_info_t tpinfo; odp_cpumask_t cpumask; char cpumaskstr[ODP_CPUMASK_STR_SIZE]; odp_shm_t shm; test_globals_t *gbls; printf("\nODP timer example starts\n"); if (odp_init_global(NULL, NULL)) { printf("ODP global init failed.\n"); return -1; } /* Init this thread. */ if (odp_init_local()) { printf("ODP local init failed.\n"); return -1; } printf("\n"); printf("ODP system info\n"); printf("---------------\n"); printf("ODP API version: %s\n", odp_version_api_str()); printf("CPU model: %s\n", odp_sys_cpu_model_str()); printf("CPU freq (hz): %"PRIu64"\n", odp_sys_cpu_hz()); printf("Cache line size: %i\n", odp_sys_cache_line_size()); printf("Max CPU count: %i\n", odp_cpu_count()); printf("\n"); /* Reserve memory for test_globals_t from shared mem */ shm = odp_shm_reserve("shm_test_globals", sizeof(test_globals_t), ODP_CACHE_LINE_SIZE, 0); if (ODP_SHM_INVALID == shm) { EXAMPLE_ERR("Error: shared mem reserve failed.\n"); return -1; } gbls = odp_shm_addr(shm); if (NULL == gbls) { EXAMPLE_ERR("Error: shared mem alloc failed.\n"); return -1; } memset(gbls, 0, sizeof(test_globals_t)); parse_args(argc, argv, &gbls->args); memset(thread_tbl, 0, sizeof(thread_tbl)); /* Default to system CPU count unless user specified */ num_workers = MAX_WORKERS; if (gbls->args.cpu_count) num_workers = gbls->args.cpu_count; /* * By default CPU #0 runs Linux kernel background tasks. * Start mapping thread from CPU #1 */ num_workers = odph_linux_cpumask_default(&cpumask, num_workers); (void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr)); printf("num worker threads: %i\n", num_workers); printf("first CPU: %i\n", odp_cpumask_first(&cpumask)); printf("cpu mask: %s\n", cpumaskstr); printf("resolution: %i usec\n", gbls->args.resolution_us); printf("min timeout: %i usec\n", gbls->args.min_us); printf("max timeout: %i usec\n", gbls->args.max_us); printf("period: %i usec\n", gbls->args.period_us); printf("timeouts: %i\n", gbls->args.tmo_count); /* * Create pool for timeouts */ params.tmo.num = NUM_TMOS; params.type = ODP_POOL_TIMEOUT; gbls->pool = odp_pool_create("msg_pool", ODP_SHM_NULL, ¶ms); if (gbls->pool == ODP_POOL_INVALID) { EXAMPLE_ERR("Pool create failed.\n"); return -1; } tparams.res_ns = gbls->args.resolution_us*ODP_TIME_USEC; tparams.min_tmo = gbls->args.min_us*ODP_TIME_USEC; tparams.max_tmo = gbls->args.max_us*ODP_TIME_USEC; tparams.num_timers = num_workers; /* One timer per worker */ tparams.priv = 0; /* Shared */ tparams.clk_src = ODP_CLOCK_CPU; gbls->tp = odp_timer_pool_create("timer_pool", &tparams); if (gbls->tp == ODP_TIMER_POOL_INVALID) { EXAMPLE_ERR("Timer pool create failed.\n"); return -1; } odp_timer_pool_start(); odp_shm_print_all(); (void)odp_timer_pool_info(gbls->tp, &tpinfo); printf("Timer pool\n"); printf("----------\n"); printf(" name: %s\n", tpinfo.name); printf(" resolution: %"PRIu64" ns\n", tpinfo.param.res_ns); printf(" min tmo: %"PRIu64" ticks\n", tpinfo.param.min_tmo); printf(" max tmo: %"PRIu64" ticks\n", tpinfo.param.max_tmo); printf("\n"); /* * Create a queue for timer test */ memset(¶m, 0, sizeof(param)); param.sched.prio = ODP_SCHED_PRIO_DEFAULT; param.sched.sync = ODP_SCHED_SYNC_NONE; param.sched.group = ODP_SCHED_GROUP_DEFAULT; queue = odp_queue_create("timer_queue", ODP_QUEUE_TYPE_SCHED, ¶m); if (queue == ODP_QUEUE_INVALID) { EXAMPLE_ERR("Timer queue create failed.\n"); return -1; } printf("CPU freq %"PRIu64" Hz\n", odp_sys_cpu_hz()); printf("Cycles vs nanoseconds:\n"); ns = 0; cycles = odp_time_ns_to_cycles(ns); printf(" %12"PRIu64" ns -> %12"PRIu64" cycles\n", ns, cycles); printf(" %12"PRIu64" cycles -> %12"PRIu64" ns\n", cycles, odp_time_cycles_to_ns(cycles)); for (ns = 1; ns <= 100*ODP_TIME_SEC; ns *= 10) { cycles = odp_time_ns_to_cycles(ns); printf(" %12"PRIu64" ns -> %12"PRIu64" cycles\n", ns, cycles); printf(" %12"PRIu64" cycles -> %12"PRIu64" ns\n", cycles, odp_time_cycles_to_ns(cycles)); } printf("\n"); /* Initialize number of timeouts to receive */ odp_atomic_init_u32(&gbls->remain, gbls->args.tmo_count * num_workers); /* Barrier to sync test case execution */ odp_barrier_init(&gbls->test_barrier, num_workers); /* Create and launch worker threads */ odph_linux_pthread_create(thread_tbl, &cpumask, run_thread, gbls); /* Wait for worker threads to exit */ odph_linux_pthread_join(thread_tbl, num_workers); printf("ODP timer test complete\n\n"); return 0; }
/** * ODP packet example main function */ int main(int argc, char * argv[]) { odph_linux_pthread_t thread_tbl[MAX_WORKERS]; odp_pool_t pool; int num_workers; int i; odp_shm_t shm; odp_cpumask_t cpumask; char cpumaskstr[ODP_CPUMASK_STR_SIZE]; odp_pool_param_t params; odp_timer_pool_param_t tparams; odp_timer_pool_t tp; odp_pool_t tmop; /* Init ODP before calling anything else */ if (odp_init_global(NULL, NULL)) { EXAMPLE_ERR("Error: ODP global init failed.\n"); exit(EXIT_FAILURE); } if (odp_init_local(ODP_THREAD_CONTROL)) { EXAMPLE_ERR("Error: ODP local init failed.\n"); exit(EXIT_FAILURE); } my_sleep(1 + __k1_get_cluster_id() / 4); /* init counters */ odp_atomic_init_u64(&counters.seq, 0); odp_atomic_init_u64(&counters.ip, 0); odp_atomic_init_u64(&counters.udp, 0); odp_atomic_init_u64(&counters.icmp, 0); odp_atomic_init_u64(&counters.cnt, 0); /* Reserve memory for args from shared mem */ shm = odp_shm_reserve("shm_args", sizeof(args_t), ODP_CACHE_LINE_SIZE, 0); args = odp_shm_addr(shm); if (args == NULL) { EXAMPLE_ERR("Error: shared mem alloc failed.\n"); exit(EXIT_FAILURE); } memset(args, 0, sizeof(*args)); /* Parse and store the application arguments */ parse_args(argc, argv, &args->appl); /* Print both system and application information */ print_info(NO_PATH(argv[0]), &args->appl); /* Default to system CPU count unless user specified */ num_workers = MAX_WORKERS; if (args->appl.cpu_count) num_workers = args->appl.cpu_count; num_workers = odp_cpumask_default_worker(&cpumask, num_workers); if (args->appl.mask) { odp_cpumask_from_str(&cpumask, args->appl.mask); num_workers = odp_cpumask_count(&cpumask); } (void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr)); printf("num worker threads: %i\n", num_workers); printf("first CPU: %i\n", odp_cpumask_first(&cpumask)); printf("cpu mask: %s\n", cpumaskstr); /* ping mode need two workers */ if (args->appl.mode == APPL_MODE_PING) { if (num_workers < 2) { EXAMPLE_ERR("Need at least two worker threads\n"); exit(EXIT_FAILURE); } else { num_workers = 2; } } /* Create packet pool */ odp_pool_param_init(¶ms); params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; params.pkt.len = SHM_PKT_POOL_BUF_SIZE; params.pkt.num = SHM_PKT_POOL_SIZE/SHM_PKT_POOL_BUF_SIZE; params.type = ODP_POOL_PACKET; pool = odp_pool_create("packet_pool", ¶ms); if (pool == ODP_POOL_INVALID) { EXAMPLE_ERR("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } odp_pool_print(pool); /* Create timer pool */ tparams.res_ns = 1 * ODP_TIME_MSEC_IN_NS; tparams.min_tmo = 0; tparams.max_tmo = 10000 * ODP_TIME_SEC_IN_NS; tparams.num_timers = num_workers; /* One timer per worker */ tparams.priv = 0; /* Shared */ tparams.clk_src = ODP_CLOCK_CPU; tp = odp_timer_pool_create("timer_pool", &tparams); if (tp == ODP_TIMER_POOL_INVALID) { EXAMPLE_ERR("Timer pool create failed.\n"); exit(EXIT_FAILURE); } odp_timer_pool_start(); /* Create timeout pool */ memset(¶ms, 0, sizeof(params)); params.tmo.num = tparams.num_timers; /* One timeout per timer */ params.type = ODP_POOL_TIMEOUT; tmop = odp_pool_create("timeout_pool", ¶ms); if (pool == ODP_POOL_INVALID) { EXAMPLE_ERR("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } for (i = 0; i < args->appl.if_count; ++i) create_pktio(args->appl.if_names[i], pool); /* Create and init worker threads */ memset(thread_tbl, 0, sizeof(thread_tbl)); if (args->appl.mode == APPL_MODE_PING) { odp_cpumask_t cpu_mask; odp_queue_t tq; int cpu_first, cpu_next; odp_cpumask_zero(&cpu_mask); cpu_first = odp_cpumask_first(&cpumask); odp_cpumask_set(&cpu_mask, cpu_first); tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL); if (tq == ODP_QUEUE_INVALID) abort(); args->thread[1].pktio_dev = args->appl.if_names[0]; args->thread[1].pool = pool; args->thread[1].tp = tp; args->thread[1].tq = tq; args->thread[1].tim = odp_timer_alloc(tp, tq, NULL); if (args->thread[1].tim == ODP_TIMER_INVALID) abort(); args->thread[1].tmo_ev = odp_timeout_alloc(tmop); if (args->thread[1].tmo_ev == ODP_TIMEOUT_INVALID) abort(); args->thread[1].mode = args->appl.mode; odph_linux_pthread_create(&thread_tbl[1], &cpu_mask, gen_recv_thread, &args->thread[1], ODP_THREAD_WORKER); tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL); if (tq == ODP_QUEUE_INVALID) abort(); args->thread[0].pktio_dev = args->appl.if_names[0]; args->thread[0].pool = pool; args->thread[0].tp = tp; args->thread[0].tq = tq; args->thread[0].tim = odp_timer_alloc(tp, tq, NULL); if (args->thread[0].tim == ODP_TIMER_INVALID) abort(); args->thread[0].tmo_ev = odp_timeout_alloc(tmop); if (args->thread[0].tmo_ev == ODP_TIMEOUT_INVALID) abort(); args->thread[0].mode = args->appl.mode; cpu_next = odp_cpumask_next(&cpumask, cpu_first); odp_cpumask_zero(&cpu_mask); odp_cpumask_set(&cpu_mask, cpu_next); odph_linux_pthread_create(&thread_tbl[0], &cpu_mask, gen_send_thread, &args->thread[0], ODP_THREAD_WORKER); } else { int cpu = odp_cpumask_first(&cpumask); for (i = 0; i < num_workers; ++i) { odp_cpumask_t thd_mask; void *(*thr_run_func) (void *); int if_idx; odp_queue_t tq; if_idx = i % args->appl.if_count; args->thread[i].pktio_dev = args->appl.if_names[if_idx]; tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL); if (tq == ODP_QUEUE_INVALID) abort(); args->thread[i].pool = pool; args->thread[i].tp = tp; args->thread[i].tq = tq; args->thread[i].tim = odp_timer_alloc(tp, tq, NULL); if (args->thread[i].tim == ODP_TIMER_INVALID) abort(); args->thread[i].tmo_ev = odp_timeout_alloc(tmop); if (args->thread[i].tmo_ev == ODP_TIMEOUT_INVALID) abort(); args->thread[i].mode = args->appl.mode; if (args->appl.mode == APPL_MODE_UDP) { thr_run_func = gen_send_thread; } else if (args->appl.mode == APPL_MODE_RCV) { thr_run_func = gen_recv_thread; } else { EXAMPLE_ERR("ERR MODE\n"); exit(EXIT_FAILURE); } /* * Create threads one-by-one instead of all-at-once, * because each thread might get different arguments. * Calls odp_thread_create(cpu) for each thread */ odp_cpumask_zero(&thd_mask); odp_cpumask_set(&thd_mask, cpu); odph_linux_pthread_create(&thread_tbl[i], &thd_mask, thr_run_func, &args->thread[i], ODP_THREAD_WORKER); cpu = odp_cpumask_next(&cpumask, cpu); } } print_global_stats(num_workers); /* Master thread waits for other threads to exit */ odph_linux_pthread_join(thread_tbl, num_workers); free(args->appl.if_names); free(args->appl.if_str); printf("Exit\n\n"); return 0; }
/** * Parse and store the command line arguments * * @param argc argument count * @param argv[] argument vector * @param appl_args Store application arguments here */ static void parse_args(int argc, char *argv[], appl_args_t *appl_args) { int opt; int long_index; char *token; size_t len; odp_cpumask_t cpumask, cpumask_args, cpumask_and; int i, num_workers; static struct option longopts[] = { {"interface", required_argument, NULL, 'I'}, {"workers", required_argument, NULL, 'w'}, {"cpumask", required_argument, NULL, 'c'}, {"srcmac", required_argument, NULL, 'a'}, {"dstmac", required_argument, NULL, 'b'}, {"srcip", required_argument, NULL, 's'}, {"dstip", required_argument, NULL, 'd'}, {"packetsize", required_argument, NULL, 'p'}, {"mode", required_argument, NULL, 'm'}, {"count", required_argument, NULL, 'n'}, {"timeout", required_argument, NULL, 't'}, {"interval", required_argument, NULL, 'i'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; appl_args->mode = -1; /* Invalid, must be changed by parsing */ appl_args->number = -1; appl_args->payload = 56; appl_args->timeout = -1; int remove_header_size = 0; while (1) { opt = getopt_long(argc, argv, "+I:a:b:s:d:p:P:i:m:n:t:w:c:h", longopts, &long_index); if (opt == -1) break; /* No more options */ switch (opt) { case 'w': appl_args->cpu_count = atoi(optarg); break; case 'c': appl_args->mask = optarg; odp_cpumask_from_str(&cpumask_args, args->appl.mask); num_workers = odp_cpumask_default_worker(&cpumask, 0); odp_cpumask_and(&cpumask_and, &cpumask_args, &cpumask); if (odp_cpumask_count(&cpumask_and) < odp_cpumask_count(&cpumask_args)) { EXAMPLE_ERR("Wrong cpu mask, max cpu's:%d\n", num_workers); exit(EXIT_FAILURE); } break; /* parse packet-io interface names */ case 'I': len = strlen(optarg); if (len == 0) { usage(argv[0]); exit(EXIT_FAILURE); } len += 1; /* add room for '\0' */ appl_args->if_str = malloc(len); if (appl_args->if_str == NULL) { usage(argv[0]); exit(EXIT_FAILURE); } /* count the number of tokens separated by ',' */ strcpy(appl_args->if_str, optarg); for (token = strtok(appl_args->if_str, ","), i = 0; token != NULL; token = strtok(NULL, ","), i++) ; appl_args->if_count = i; if (appl_args->if_count == 0) { usage(argv[0]); exit(EXIT_FAILURE); } /* allocate storage for the if names */ appl_args->if_names = calloc(appl_args->if_count, sizeof(char *)); /* store the if names (reset names string) */ strcpy(appl_args->if_str, optarg); for (token = strtok(appl_args->if_str, ","), i = 0; token != NULL; token = strtok(NULL, ","), i++) { appl_args->if_names[i] = token; } break; case 'm': if (optarg[0] == 'u') { appl_args->mode = APPL_MODE_UDP; } else if (optarg[0] == 'p') { appl_args->mode = APPL_MODE_PING; } else if (optarg[0] == 'r') { appl_args->mode = APPL_MODE_RCV; } else { EXAMPLE_ERR("wrong mode!\n"); exit(EXIT_FAILURE); } break; case 'a': if (scan_mac(optarg, &appl_args->srcmac) != 1) { EXAMPLE_ERR("wrong src mac:%s\n", optarg); exit(EXIT_FAILURE); } break; case 'b': if (scan_mac(optarg, &appl_args->dstmac) != 1) { EXAMPLE_ERR("wrong dst mac:%s\n", optarg); exit(EXIT_FAILURE); } break; case 's': if (scan_ip(optarg, &appl_args->srcip) != 1) { EXAMPLE_ERR("wrong src ip:%s\n", optarg); exit(EXIT_FAILURE); } break; case 'd': if (scan_ip(optarg, &appl_args->dstip) != 1) { EXAMPLE_ERR("wrong dst ip:%s\n", optarg); exit(EXIT_FAILURE); } break; case 'p': appl_args->payload = atoi(optarg); break; case 'P': appl_args->payload = atoi(optarg); remove_header_size = 1; break; case 'n': appl_args->number = atoi(optarg); break; case 't': appl_args->timeout = atoi(optarg); break; case 'i': appl_args->interval = atoi(optarg); break; case 'h': usage(argv[0]); exit(EXIT_SUCCESS); break; default: break; } } if ( remove_header_size ) { int header_size = 0; switch (appl_args->mode) { case APPL_MODE_UDP: header_size = ODPH_UDPHDR_LEN + ODPH_IPV4HDR_LEN + ODPH_ETHHDR_LEN; break; case APPL_MODE_PING: header_size = ODPH_ICMPHDR_LEN + ODPH_IPV4HDR_LEN + ODPH_ETHHDR_LEN; break; case APPL_MODE_RCV: break; } appl_args->payload -= header_size; } printf("PAYLOAD = %i\n", appl_args->payload); if (appl_args->if_count == 0 || appl_args->mode == -1) { usage(argv[0]); exit(EXIT_FAILURE); } optind = 1; /* reset 'extern optind' from the getopt lib */ }