Пример #1
0
/*
 * 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);
}
Пример #2
0
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);
}
Пример #3
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);
}
Пример #4
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);
}
Пример #5
0
/**
 * 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);
}
Пример #7
0
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");
}
Пример #8
0
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);
}
Пример #9
0
/*
 * 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;
	}
}
Пример #10
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");
}
Пример #11
0
/**
 * 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;
}
Пример #12
0
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);
}
Пример #13
0
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));
	}
}
Пример #14
0
/*
 * 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);
	}
}
Пример #15
0
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;
}
Пример #17
0
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);
}
Пример #18
0
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);
}
Пример #19
0
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
}
Пример #20
0
/**
 * 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;
}
Пример #21
0
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);
}
Пример #22
0
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));
	}
}
Пример #23
0
/**
 * 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;
}
Пример #24
0
/**
 * 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;
}
Пример #25
0
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;
}
Пример #26
0
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;
}
Пример #27
0
/**
 * 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(&eth->src, &port_out);

		/* Update for address table if necessary */
		if (ret < 0 || port_out != port_in)
			mac_table_put(&eth->src, port_in);

		/* Lookup destination MAC address */
		ret = mac_table_get(&eth->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++;
	}
}
Пример #28
0
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;
}
Пример #29
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 *)(&ethhdr->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);
	}
}
Пример #30
0
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;
}