/* * Append address and data, and optionally, control (ancillary) data to the * receive queue of a socket. If present, m0 must include a packet header * with total length. Returns 0 if no space in sockbuf or insufficient * mbufs. */ int ofp_sbappendaddr_locked(struct sockbuf *sb, odp_packet_t pkt, odp_packet_t control) { SOCKBUF_LOCK_ASSERT(sb); if (control != ODP_PACKET_INVALID) odp_packet_free(control); sb->sb_mb[sb->sb_put++] = pkt; if (sb->sb_put >= SOCKBUF_LEN) sb->sb_put = 0; if (sb->sb_put == sb->sb_get) { sb->sb_put--; if (sb->sb_put < 0) sb->sb_put = SOCKBUF_LEN-1; OFP_ERR("Buffers full, sb_get=%d max_num=%d", sb->sb_get, SOCKBUF_LEN); return 0; } sballoc(sb, pkt); return (1); }
void pktio_test_send_on_ronly(void) { odp_pktio_t pktio; odp_packet_t pkt; int ret; pktio = create_pktio(0, ODP_PKTIN_MODE_RECV, ODP_PKTOUT_MODE_DISABLED); if (pktio == ODP_PKTIO_INVALID) { CU_FAIL("failed to open pktio"); return; } ret = odp_pktio_start(pktio); CU_ASSERT_FATAL(ret == 0); pkt = odp_packet_alloc(default_pkt_pool, packet_len); CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID) pktio_init_packet(pkt); ret = odp_pktio_send(pktio, &pkt, 1); CU_ASSERT(ret < 0); if (ret <= 0) odp_packet_free(pkt); ret = odp_pktio_stop(pktio); CU_ASSERT_FATAL(ret == 0); ret = odp_pktio_close(pktio); CU_ASSERT_FATAL(ret == 0); }
void pktio_test_recv_on_wonly(void) { odp_pktio_t pktio; odp_packet_t pkt; int ret; pktio = create_pktio(0, ODP_PKTIN_MODE_DISABLED, ODP_PKTOUT_MODE_SEND); if (pktio == ODP_PKTIO_INVALID) { CU_FAIL("failed to open pktio"); return; } ret = odp_pktio_start(pktio); CU_ASSERT_FATAL(ret == 0); ret = odp_pktio_recv(pktio, &pkt, 1); CU_ASSERT(ret < 0); if (ret > 0) odp_packet_free(pkt); ret = odp_pktio_stop(pktio); CU_ASSERT_FATAL(ret == 0); ret = odp_pktio_close(pktio); CU_ASSERT_FATAL(ret == 0); }
static void test_queue(void) { struct ofp_ifqueue ifq; struct ifq_entry e; ifq.ifq_tail = NULL; ifq.ifq_len = 0; e.next = NULL; odp_packet_t m = odp_packet_alloc(ofp_packet_pool, 0); IF_ENQUEUE(&ifq, m) while (0); CU_ASSERT_PTR_NOT_NULL(ifq.ifq_head); CU_ASSERT_PTR_EQUAL(ifq.ifq_head, ifq.ifq_tail); CU_ASSERT_PTR_NULL(ifq.ifq_tail->next); CU_ASSERT_EQUAL(ifq.ifq_len, 1); ifq.ifq_head = ifq.ifq_tail = &e; IF_ENQUEUE(&ifq, m) while (0); CU_ASSERT_PTR_NOT_NULL(ifq.ifq_head); CU_ASSERT_PTR_NOT_NULL(ifq.ifq_tail); CU_ASSERT_PTR_NOT_EQUAL(ifq.ifq_head, ifq.ifq_tail); CU_ASSERT_PTR_EQUAL(ifq.ifq_head->next, ifq.ifq_tail); CU_ASSERT_PTR_NULL(ifq.ifq_tail->next); CU_ASSERT_EQUAL(ifq.ifq_len, 2); odp_packet_free(m); }
/** * Packet IO worker thread using bursts from/to IO resources * * @param arg thread arguments of type 'thread_args_t *' */ static void *pktio_ifburst_thread(void *arg) { int thr; thread_args_t *thr_args; int pkts, pkts_ok; odp_packet_t pkt_tbl[MAX_PKT_BURST]; int src_idx, dst_idx; odp_pktio_t pktio_src, pktio_dst; thr = odp_thread_id(); thr_args = arg; stats_t *stats = calloc(1, sizeof(stats_t)); *thr_args->stats = stats; src_idx = thr_args->src_idx; dst_idx = (src_idx % 2 == 0) ? src_idx+1 : src_idx-1; pktio_src = gbl_args->pktios[src_idx]; pktio_dst = gbl_args->pktios[dst_idx]; printf("[%02i] srcif:%s dstif:%s spktio:%02" PRIu64 " dpktio:%02" PRIu64 " BURST mode\n", thr, gbl_args->appl.if_names[src_idx], gbl_args->appl.if_names[dst_idx], odp_pktio_to_u64(pktio_src), odp_pktio_to_u64(pktio_dst)); odp_barrier_wait(&barrier); /* Loop packets */ while (!exit_threads) { pkts = odp_pktio_recv(pktio_src, pkt_tbl, MAX_PKT_BURST); if (pkts <= 0) continue; /* Drop packets with errors */ pkts_ok = drop_err_pkts(pkt_tbl, pkts); if (pkts_ok > 0) { int sent = odp_pktio_send(pktio_dst, pkt_tbl, pkts_ok); sent = sent > 0 ? sent : 0; if (odp_unlikely(sent < pkts_ok)) { stats->drops += pkts_ok - sent; do odp_packet_free(pkt_tbl[sent]); while (++sent < pkts_ok); } } if (odp_unlikely(pkts_ok != pkts)) stats->drops += pkts - pkts_ok; if (pkts_ok == 0) continue; stats->packets += pkts_ok; } free(stats); return NULL; }
void test_pktio_pmr_match_set_cos(void) { uint32_t addr = 0; uint32_t mask; odph_ipv4hdr_t *ip; odph_udphdr_t *udp; odp_packet_t pkt; odp_queue_t queue; uint32_t seq; pkt = create_packet(false); seq = cls_pkt_get_seq(pkt); ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask); ip->src_addr = odp_cpu_to_be_32(addr); ip->chksum = 0; ip->chksum = odp_cpu_to_be_16(odph_ipv4_csum_update(pkt)); udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); udp->src_port = odp_cpu_to_be_16(CLS_PMR_SET_SPORT); enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); CU_ASSERT(queue == queue_list[CLS_PMR_SET]); CU_ASSERT(seq == cls_pkt_get_seq(pkt)); odp_packet_free(pkt); }
static void test_ofp_packet_input_to_sp(void) { odp_packet_t pkt; odp_event_t ev; int res; my_test_val = TEST_FORWARD_HOOK; /* Call ofp_packet_input using a pkt with destination ip * that does NOT match the local ip on ifnet and NO route is found. * The packet is forwarded to slow path queue. */ if (create_odp_packet_ip4(&pkt, test_frame, sizeof(test_frame), 0, 0)) { CU_FAIL("Fail to create packet"); return; } res = ofp_packet_input(pkt, interface_queue[port], ofp_eth_vlan_processing); CU_ASSERT_EQUAL(res, OFP_PKT_PROCESSED); CU_ASSERT_NOT_EQUAL(ev = odp_queue_deq(ifnet->spq_def), ODP_EVENT_INVALID); CU_ASSERT_EQUAL(odp_queue_deq(ifnet->spq_def), ODP_EVENT_INVALID); CU_ASSERT_EQUAL(odp_queue_deq(ifnet->outq_def), ODP_EVENT_INVALID); if (memcmp(odp_packet_data(odp_packet_from_event(ev)), in_pkt_data, sizeof(test_frame))) CU_FAIL("corrupt data sent to slow path"); odp_packet_free(odp_packet_from_event(ev)); CU_PASS("ofp_packet_input_to_sp"); }
static void send_arp_request(struct ofp_ifnet *dev, uint32_t gw) { char buf[sizeof(struct ofp_ether_vlan_header) + sizeof(struct ofp_arphdr)]; struct ofp_arphdr *arp; struct ofp_ether_header *e1 = (struct ofp_ether_header *)buf; struct ofp_ether_vlan_header *e2 = (struct ofp_ether_vlan_header *)buf; size_t size; odp_packet_t pkt; memset(buf, 0, sizeof(buf)); memset(e1->ether_dhost, 0xff, OFP_ETHER_ADDR_LEN); memcpy(e1->ether_shost, dev->mac, OFP_ETHER_ADDR_LEN); if (ETH_WITH_VLAN(dev)) { arp = (struct ofp_arphdr *) (e2 + 1); e2->evl_encap_proto = odp_cpu_to_be_16(OFP_ETHERTYPE_VLAN); e2->evl_tag = odp_cpu_to_be_16(dev->vlan); e2->evl_proto = odp_cpu_to_be_16(OFP_ETHERTYPE_ARP); size = sizeof(*arp) + sizeof(*e2); } else { arp = (struct ofp_arphdr *) (e1 + 1); e1->ether_type = odp_cpu_to_be_16(OFP_ETHERTYPE_ARP); size = sizeof(*arp) + sizeof(*e1); } arp->hrd = odp_cpu_to_be_16(OFP_ARPHDR_ETHER); arp->pro = odp_cpu_to_be_16(OFP_ETHERTYPE_IP); arp->hln = OFP_ETHER_ADDR_LEN; arp->pln = sizeof(struct ofp_in_addr); arp->op = odp_cpu_to_be_16(OFP_ARPOP_REQUEST); memcpy(arp->eth_src, e1->ether_shost, OFP_ETHER_ADDR_LEN); arp->ip_src = dev->ip_addr; memcpy(arp->eth_dst, e1->ether_dhost, OFP_ETHER_ADDR_LEN); arp->ip_dst = gw; pkt = ofp_packet_alloc(size); if (pkt == ODP_PACKET_INVALID) { OFP_ERR("ofp_packet_alloc failed"); return; } memcpy(odp_packet_data(pkt), buf, size); if (odp_unlikely(ofp_if_type(dev) == OFP_IFT_VXLAN)) { ofp_vxlan_send_arp_request(pkt, dev); return; } odp_packet_has_eth_set(pkt, 1); odp_packet_has_arp_set(pkt, 1); odp_packet_l2_offset_set(pkt, 0); odp_packet_l3_offset_set(pkt, size - sizeof(struct ofp_arphdr)); if (send_pkt_out(dev, pkt) == OFP_PKT_DROP) odp_packet_free(pkt); }
/* * Free all mbufs in a sockbuf. Check that all resources are reclaimed. */ static void sbflush_internal(struct sockbuf *sb) { while (sb->sb_get != sb->sb_put) { odp_packet_free(sb->sb_mb[sb->sb_get]); if (++sb->sb_get >= SOCKBUF_LEN) sb->sb_get = 0; } }
static void test_ofp_packet_input_send_arp(void) { odp_packet_t pkt; odp_event_t ev; int res; /* Call ofp_packet_input using a pkt with destination ip * that does NOT match the local ip on ifnet and a route is found. * No ARP is found for gateway IP so an ARP req is sent. * Function returns OFP_PKT_DROP and packet can be reused.*/ my_test_val = TEST_FORWARD_HOOK; test_ofp_add_route(port, vrf, vlan, dst_ipaddr, 24, 4, dst_ipaddr + 1); if (create_odp_packet_ip4(&pkt, test_frame, sizeof(test_frame), dst_ipaddr, 0)) { CU_FAIL("Fail to create packet"); return; } res = ofp_packet_input(pkt, interface_queue[port], ofp_eth_vlan_processing); CU_ASSERT_EQUAL(res, OFP_PKT_PROCESSED); odp_packet_free(pkt); CU_ASSERT_NOT_EQUAL(ev = odp_queue_deq(ifnet->outq_def), ODP_EVENT_INVALID); CU_ASSERT_EQUAL(odp_queue_deq(ifnet->outq_def), ODP_EVENT_INVALID); #ifdef SP CU_ASSERT_EQUAL(odp_queue_deq(ifnet->spq_def), ODP_EVENT_INVALID); #endif /* SP */ pkt = odp_packet_from_event(ev); CU_ASSERT_NOT_EQUAL(pkt, ODP_PACKET_INVALID); CU_ASSERT_EQUAL(odp_packet_has_arp(pkt), 1); CU_ASSERT_EQUAL(odp_packet_has_vlan(pkt), 0); CU_ASSERT_EQUAL(odp_packet_len(pkt), sizeof(struct ofp_arphdr) + sizeof(struct ofp_ether_header)); odp_packet_free(odp_packet_from_event(ev)); ofp_arp_init_tables(); /* to clean saved packet */ CU_PASS("ofp_packet_input_send_arp"); }
/** * 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; }
static inline void enqueue_loop_interface(odp_packet_t pkt) { odp_event_t ev; odp_queue_t defqueue = odp_pktio_outq_getdef(pktio_loop); ev = odp_packet_to_event(pkt); if (!(CU_ASSERT(odp_queue_enq(defqueue, ev) == 0))) odp_packet_free(pkt); }
static void cleanup_pkt_queue(odp_queue_t pkt_queue) { odp_event_t evt; while (1) { evt = odp_queue_deq(pkt_queue); if (evt == ODP_EVENT_INVALID) break; odp_packet_free(odp_packet_from_event(evt)); } }
/* * Drop a record off the front of a sockbuf and move the next record to the * front. */ void ofp_sbdroprecord_locked(struct sockbuf *sb) { odp_packet_t pkt; SOCKBUF_LOCK_ASSERT(sb); pkt = ofp_sockbuf_remove_first(sb); if (pkt != ODP_PACKET_INVALID) { sbfree(sb, pkt); odp_packet_free(pkt); } }
odp_bool_t verify_stream_db_outputs(void) { odp_bool_t done = TRUE; stream_db_entry_t *stream = NULL; const char *env; env = getenv("ODP_IPSEC_STREAM_VERIFY_MDEQ"); /* For each stream look for output packets */ for (stream = stream_db->list; NULL != stream; stream = stream->next) { int idx; int count; odp_queue_t queue; odp_event_t ev_tbl[LOOP_DEQ_COUNT]; queue = query_loopback_db_outq(stream->output.loop); if (ODP_QUEUE_INVALID == queue) continue; for (;;) { if (env) { count = odp_queue_deq_multi(queue, ev_tbl, LOOP_DEQ_COUNT); } else { ev_tbl[0] = odp_queue_deq(queue); count = (ev_tbl[0] != ODP_EVENT_INVALID) ? 1 : 0; } if (!count) break; for (idx = 0; idx < count; idx++) { odp_bool_t good; odp_packet_t pkt; pkt = odp_packet_from_event(ev_tbl[idx]); good = verify_ipv4_packet(stream, pkt); if (good) stream->verified++; odp_packet_free(pkt); } } printf("Stream %d %d\n", stream->created, stream->verified); if (stream->created != stream->verified) done = FALSE; } return done; }
static void *pkt_io_recv(void *arg) { odp_pktio_t pktio; odp_packet_t pkt, pkt_tbl[OFP_PKT_BURST_SIZE]; int pkt_idx, pkt_cnt; struct pktio_thr_arg *thr_args; ofp_pkt_processing_func pkt_func; thr_args = arg; pkt_func = thr_args->pkt_func; if (odp_init_local(ODP_THREAD_WORKER)) { OFP_ERR("Error: ODP local init failed.\n"); return NULL; } if (ofp_init_local()) { OFP_ERR("Error: OFP local init failed.\n"); return NULL; } pktio = ofp_port_pktio_get(thr_args->port); OFP_DBG("PKT-IO receive starting on port: %d, pktio-id: %"PRIX64"\n", thr_args->port, odp_pktio_to_u64(pktio)); while (1) { pkt_cnt = odp_pktio_recv(pktio, pkt_tbl, OFP_PKT_BURST_SIZE); for (pkt_idx = 0; pkt_idx < pkt_cnt; pkt_idx++) { pkt = pkt_tbl[pkt_idx]; if (odp_unlikely(odp_packet_has_error(pkt))) { OFP_DBG("Packet with error dropped.\n"); odp_packet_free(pkt); continue; } ofp_packet_input(pkt, ODP_QUEUE_INVALID, pkt_func); } #ifdef OFP_SEND_PKT_BURST ofp_send_pending_pkt_burst(); #endif /*OFP_SEND_PKT_BURST*/ } /* Never reached */ return NULL; }
void test_pmr_cos(void) { odp_packet_t pkt; odph_udphdr_t *udp; odp_queue_t queue; uint32_t seq; pkt = create_packet(false); seq = cls_pkt_get_seq(pkt); udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT); enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); CU_ASSERT(queue == queue_list[CLS_PMR]); CU_ASSERT(seq == cls_pkt_get_seq(pkt)); odp_packet_free(pkt); }
void test_pktio_default_cos(void) { odp_packet_t pkt; odp_queue_t queue; uint32_t seq; /* create a default packet */ pkt = create_packet(false); seq = cls_pkt_get_seq(pkt); enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); /* Default packet should be received in default queue */ CU_ASSERT(queue == queue_list[CLS_DEFAULT]); CU_ASSERT(seq == cls_pkt_get_seq(pkt)); odp_packet_free(pkt); }
static void test_ofp_packet_input_gre_orig_pkt_to_sp(void) { odp_packet_t pkt; int res; #ifdef SP odp_event_t ev; #endif my_test_val = TEST_LOCAL_HOOK_GRE_APP; /* Call ofp_packet_input using a GRE pkt with destination ip * that matches the local ip on ifnet, tunnel not found, * packet offered to GRE hook, returns continue. * Full packet sent to slowpath */ ifnet->ip_addr = local_ip; if (create_odp_packet_ip4(&pkt, gre_frame, sizeof(gre_frame), local_ip, tun_rem_ip + 1)) { CU_FAIL("Fail to create packet"); return; } res = ofp_packet_input(pkt, interface_queue[port], ofp_eth_vlan_processing); #ifdef SP CU_ASSERT_EQUAL(res, OFP_PKT_PROCESSED); CU_ASSERT_NOT_EQUAL_FATAL(ev = odp_queue_deq(ifnet->spq_def), ODP_EVENT_INVALID); CU_ASSERT_EQUAL(odp_queue_deq(ifnet->spq_def), ODP_EVENT_INVALID); CU_ASSERT_EQUAL(odp_queue_deq(ifnet->outq_def), ODP_EVENT_INVALID); if (memcmp(odp_packet_data(odp_packet_from_event(ev)), in_pkt_data, sizeof(gre_frame))) CU_FAIL("corrupt data sent to slow path"); odp_packet_free(odp_packet_from_event(ev)); ifnet->ip_addr = 0; CU_PASS("ofp_packet_input_gre_orig_pkt_to_sp"); #else CU_ASSERT_EQUAL(res, OFP_PKT_DROP); CU_ASSERT_EQUAL(odp_queue_deq(ifnet->outq_def), ODP_EVENT_INVALID); #endif }
/** * Drop packets which input parsing marked as containing errors. * * Frees packets with error and modifies pkt_tbl[] to only contain packets with * no detected errors. * * @param pkt_tbl Array of packets * @param num Number of packets in pkt_tbl[] * * @return Number of packets dropped */ static int drop_err_pkts(odp_packet_t pkt_tbl[], unsigned num) { odp_packet_t pkt; unsigned dropped = 0; unsigned i, j; for (i = 0, j = 0; i < num; ++i) { pkt = pkt_tbl[i]; if (odp_unlikely(odp_packet_has_error(pkt))) { odp_packet_free(pkt); /* Drop */ dropped++; } else if (odp_unlikely(i != j++)) { pkt_tbl[j-1] = pkt; } } return dropped; }
void test_pktio_error_cos(void) { odp_queue_t queue; odp_packet_t pkt; /*Create an error packet */ pkt = create_packet(false); odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); /* Incorrect IpV4 version */ ip->ver_ihl = 8 << 4 | ODPH_IPV4HDR_IHL_MIN; ip->chksum = 0; enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); /* Error packet should be received in error queue */ CU_ASSERT(queue == queue_list[CLS_ERROR]); odp_packet_free(pkt); }
void odp_event_free(odp_event_t event) { switch (odp_event_type(event)) { case ODP_EVENT_BUFFER: odp_buffer_free(odp_buffer_from_event(event)); break; case ODP_EVENT_PACKET: odp_packet_free(odp_packet_from_event(event)); break; case ODP_EVENT_TIMEOUT: odp_timeout_free(odp_timeout_from_event(event)); break; case ODP_EVENT_CRYPTO_COMPL: odp_crypto_compl_free(odp_crypto_compl_from_event(event)); break; default: ODP_ABORT("Invalid event type: %d\n", odp_event_type(event)); } }
/** * Packet IO worker thread using ODP queues * * @param arg thread arguments of type 'thread_args_t *' */ static void *pktio_queue_thread(void *arg) { int thr; odp_queue_t outq_def; odp_packet_t pkt; odp_event_t ev; thread_args_t *thr_args = arg; stats_t *stats = calloc(1, sizeof(stats_t)); *thr_args->stats = stats; thr = odp_thread_id(); printf("[%02i] QUEUE mode\n", thr); odp_barrier_wait(&barrier); /* Loop packets */ while (!exit_threads) { /* 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(drop_err_pkts(&pkt, 1) == 0)) { stats->drops += 1; continue; } outq_def = lookup_dest_q(pkt); /* Enqueue the packet for output */ if (odp_queue_enq(outq_def, ev)) { printf(" [%i] Queue enqueue failed.\n", thr); odp_packet_free(pkt); continue; } stats->packets += 1; } free(stats); return NULL; }
/** * Drop packets which input parsing marked as containing errors. * * Frees packets with error and modifies pkt_tbl[] to only contain packets with * no detected errors. * * @param pkt_tbl Array of packet * @param len Length of pkt_tbl[] * * @return Number of packets with no detected error */ static int drop_err_pkts(odp_packet_t pkt_tbl[], unsigned len) { odp_packet_t pkt; unsigned pkt_cnt = len; unsigned i, j; for (i = 0, j = 0; i < len; ++i) { pkt = pkt_tbl[i]; if (odp_unlikely(odp_packet_error(pkt))) { odp_packet_free(pkt); /* Drop */ pkt_cnt--; } else if (odp_unlikely(i != j++)) { pkt_tbl[j-1] = pkt; } } return pkt_cnt; }
static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx, uint32_t seq, uint64_t ns) { odp_time_t wait_time, end; odp_event_t ev; odp_packet_t pkt; uint64_t wait; wait = odp_schedule_wait_time(ns); wait_time = odp_time_local_from_ns(ns); end = odp_time_sum(odp_time_local(), wait_time); do { pkt = ODP_PACKET_INVALID; if (pktio_rx->in_mode == ODP_PKTIN_MODE_RECV) { odp_pktio_recv(pktio_rx->id, &pkt, 1); } else { if (pktio_rx->in_mode == ODP_PKTIN_MODE_POLL) ev = queue_deq_wait_time(pktio_rx->inq, ns); else ev = odp_schedule(NULL, wait); if (ev != ODP_EVENT_INVALID) { if (odp_event_type(ev) == ODP_EVENT_PACKET) pkt = odp_packet_from_event(ev); else odp_event_free(ev); } } if (pkt != ODP_PACKET_INVALID) { if (pktio_pkt_seq(pkt) == seq) return pkt; odp_packet_free(pkt); } } while (odp_time_cmp(end, odp_time_local()) > 0); CU_FAIL("failed to receive transmitted packet"); return ODP_PACKET_INVALID; }
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; }
/** * Forward packets to correct output buffers * * Packets, whose destination MAC address is already known from previously * received packets, are forwarded to the matching switch ports. Packets * destined to unknown addresses are broadcasted to all switch ports (except * the ingress port). * * @param pkt_tbl Array of packets * @param num Number of packets in the array * @param thr_arg Thread arguments * @param port_in Input port index */ static inline void forward_packets(odp_packet_t pkt_tbl[], unsigned num, thread_args_t *thr_arg, uint8_t port_in) { odp_packet_t pkt; odph_ethhdr_t *eth; unsigned i; unsigned buf_id; int ret; uint8_t port_out = 0; for (i = 0; i < num; i++) { pkt = pkt_tbl[i]; if (!odp_packet_has_eth(pkt)) { odp_packet_free(pkt); continue; } eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); /* Lookup source MAC address */ ret = mac_table_get(ð->src, &port_out); /* Update for address table if necessary */ if (ret < 0 || port_out != port_in) mac_table_put(ð->src, port_in); /* Lookup destination MAC address */ ret = mac_table_get(ð->dst, &port_out); if (ret < 0) { /* If address was not found, broadcast packet */ broadcast_packet(pkt, thr_arg, port_in); continue; } buf_id = thr_arg->tx_pktio[port_out].buf.len; thr_arg->tx_pktio[port_out].buf.pkt[buf_id] = pkt; thr_arg->tx_pktio[port_out].buf.len++; } }
static int send_recv(odp_packet_t packet, int send_nb, int expt_nb) { static int test_id = 0; printf("send_recv %d\n", test_id++); odp_pktio_t pktio; odp_queue_t outq_def; odp_packet_t pkt_tbl[MAX_PKT_BURST]; pktio = odp_pktio_lookup(pktio_valid_name); if (pktio == ODP_PKTIO_INVALID) { printf("Error: lookup of pktio %s failed\n", pktio_valid_name); return 1; } outq_def = odp_pktio_outq_getdef(pktio); if (outq_def == ODP_QUEUE_INVALID) { printf("Error: def output-Q query\n"); return 1; } int i; for ( i = 0; i < send_nb; ++i ) { odp_queue_enq(outq_def, (odp_event_t)packet); } int ret = 0; int start = __k1_read_dsu_timestamp(); while ( ret >= 0 && ret < expt_nb && ( __k1_read_dsu_timestamp() - start ) < 10 * __bsp_frequency ) { int n_pkt = odp_pktio_recv(pktio, pkt_tbl, MAX_PKT_BURST); ret += n_pkt; if (n_pkt > 0) odp_packet_free_multi(pkt_tbl, n_pkt); } test_assert_ret(ret == expt_nb); odp_packet_free(packet); printf("send_recv %d OK\n", test_id); return 0; }
void test_cos_with_l2_priority(void) { odp_packet_t pkt; odph_ethhdr_t *ethhdr; odph_vlanhdr_t *vlan; odp_queue_t queue; uint32_t seq; uint8_t i; for (i = 0; i < CLS_L2_QOS_MAX; i++) { pkt = create_packet(true); seq = cls_pkt_get_seq(pkt); ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); vlan = (odph_vlanhdr_t *)(ðhdr->type); vlan->tci = odp_cpu_to_be_16(i << 13); enqueue_loop_interface(pkt); pkt = receive_packet(&queue, ODP_TIME_SEC); CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]); CU_ASSERT(seq == cls_pkt_get_seq(pkt)); odp_packet_free(pkt); } }
static void *pkt_io_recv(void *arg) { odp_pktin_queue_t pktin; odp_packet_t pkt, pkt_tbl[PKT_BURST_SIZE]; int pkt_idx, pkt_cnt; struct pktio_thr_arg *thr_args; ofp_pkt_processing_func pkt_func; thr_args = arg; pkt_func = thr_args->pkt_func; pktin = thr_args->pktin; if (ofp_init_local()) { OFP_ERR("Error: OFP local init failed.\n"); return NULL; } OFP_DBG("PKT-IO receive starting on cpu: %d", odp_cpu_id()); while (1) { pkt_cnt = odp_pktin_recv(pktin, pkt_tbl, PKT_BURST_SIZE); for (pkt_idx = 0; pkt_idx < pkt_cnt; pkt_idx++) { pkt = pkt_tbl[pkt_idx]; if (odp_unlikely(odp_packet_has_error(pkt))) { OFP_DBG("Packet with error dropped.\n"); odp_packet_free(pkt); continue; } ofp_packet_input(pkt, ODP_QUEUE_INVALID, pkt_func); } ofp_send_pending_pkt(); } /* Never reached */ return NULL; }