test_common.cpp revision aa97dd1c
1aa97dd1cSKonstantin Ananyev/*
2aa97dd1cSKonstantin Ananyev * Copyright (c) 2016  Intel Corporation.
3aa97dd1cSKonstantin Ananyev * Licensed under the Apache License, Version 2.0 (the "License");
4aa97dd1cSKonstantin Ananyev * you may not use this file except in compliance with the License.
5aa97dd1cSKonstantin Ananyev * You may obtain a copy of the License at:
6aa97dd1cSKonstantin Ananyev *
7aa97dd1cSKonstantin Ananyev *     http://www.apache.org/licenses/LICENSE-2.0
8aa97dd1cSKonstantin Ananyev *
9aa97dd1cSKonstantin Ananyev * Unless required by applicable law or agreed to in writing, software
10aa97dd1cSKonstantin Ananyev * distributed under the License is distributed on an "AS IS" BASIS,
11aa97dd1cSKonstantin Ananyev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12aa97dd1cSKonstantin Ananyev * See the License for the specific language governing permissions and
13aa97dd1cSKonstantin Ananyev * limitations under the License.
14aa97dd1cSKonstantin Ananyev */
15aa97dd1cSKonstantin Ananyev
16aa97dd1cSKonstantin Ananyev#include "test_common.h"
17aa97dd1cSKonstantin Ananyev
18aa97dd1cSKonstantin Ananyevint
19aa97dd1cSKonstantin Ananyevport_init(uint8_t port, struct rte_mempool *mbuf_pool)
20aa97dd1cSKonstantin Ananyev{
21aa97dd1cSKonstantin Ananyev	struct rte_eth_conf port_conf;
22aa97dd1cSKonstantin Ananyev	const uint16_t rx_rings = 1, tx_rings = 1;
23aa97dd1cSKonstantin Ananyev	uint16_t q;
24aa97dd1cSKonstantin Ananyev	int retval;
25aa97dd1cSKonstantin Ananyev	int socket_id;
26aa97dd1cSKonstantin Ananyev
27aa97dd1cSKonstantin Ananyev	if (port >= rte_eth_dev_count())
28aa97dd1cSKonstantin Ananyev		return -1;
29aa97dd1cSKonstantin Ananyev
30aa97dd1cSKonstantin Ananyev	socket_id = rte_eth_dev_socket_id(port);
31aa97dd1cSKonstantin Ananyev
32aa97dd1cSKonstantin Ananyev	memset(&port_conf, 0, sizeof(struct rte_eth_conf));
33aa97dd1cSKonstantin Ananyev	port_conf.rxmode.max_rx_pkt_len = ETHER_MAX_LEN;
34aa97dd1cSKonstantin Ananyev
35aa97dd1cSKonstantin Ananyev	/* Configure the Ethernet device. */
36aa97dd1cSKonstantin Ananyev	retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
37aa97dd1cSKonstantin Ananyev	if (retval != 0)
38aa97dd1cSKonstantin Ananyev		return retval;
39aa97dd1cSKonstantin Ananyev
40aa97dd1cSKonstantin Ananyev	/* Allocate and set up 1 RX queue per Ethernet port. */
41aa97dd1cSKonstantin Ananyev	for (q = 0; q < rx_rings; q++) {
42aa97dd1cSKonstantin Ananyev		retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
43aa97dd1cSKonstantin Ananyev				socket_id, NULL, mbuf_pool);
44aa97dd1cSKonstantin Ananyev		if (retval < 0)
45aa97dd1cSKonstantin Ananyev			return retval;
46aa97dd1cSKonstantin Ananyev	}
47aa97dd1cSKonstantin Ananyev
48aa97dd1cSKonstantin Ananyev	/* Allocate and set up 1 TX queue per Ethernet port. */
49aa97dd1cSKonstantin Ananyev	for (q = 0; q < tx_rings; q++) {
50aa97dd1cSKonstantin Ananyev		retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
51aa97dd1cSKonstantin Ananyev				socket_id, NULL);
52aa97dd1cSKonstantin Ananyev		if (retval < 0)
53aa97dd1cSKonstantin Ananyev			return retval;
54aa97dd1cSKonstantin Ananyev	}
55aa97dd1cSKonstantin Ananyev
56aa97dd1cSKonstantin Ananyev	/* Start the Ethernet port. */
57aa97dd1cSKonstantin Ananyev	retval = rte_eth_dev_start(port);
58aa97dd1cSKonstantin Ananyev	if (retval < 0)
59aa97dd1cSKonstantin Ananyev		return retval;
60aa97dd1cSKonstantin Ananyev
61aa97dd1cSKonstantin Ananyev	/* Enable RX in promiscuous mode for the Ethernet device. */
62aa97dd1cSKonstantin Ananyev	rte_eth_promiscuous_enable(port);
63aa97dd1cSKonstantin Ananyev
64aa97dd1cSKonstantin Ananyev	return 0;
65aa97dd1cSKonstantin Ananyev}
66aa97dd1cSKonstantin Ananyev
67aa97dd1cSKonstantin Ananyev/* TODO: Shameless rip of examples/udpfwd/pkt.c below. Sorry Would like to
68aa97dd1cSKonstantin Ananyev * move these funcions to separate lib so all future created apps could
69aa97dd1cSKonstantin Ananyev * re-use that code.
70aa97dd1cSKonstantin Ananyev */
71aa97dd1cSKonstantin Ananyevvoid
72aa97dd1cSKonstantin Ananyevfill_pkt_hdr_len(struct rte_mbuf *m, uint32_t l2, uint32_t l3, uint32_t l4)
73aa97dd1cSKonstantin Ananyev{
74aa97dd1cSKonstantin Ananyev	m->l2_len = l2;
75aa97dd1cSKonstantin Ananyev	m->l3_len = l3;
76aa97dd1cSKonstantin Ananyev	m->l4_len = l4;
77aa97dd1cSKonstantin Ananyev	m->tso_segsz = 0;
78aa97dd1cSKonstantin Ananyev	m->outer_l2_len = 0;
79aa97dd1cSKonstantin Ananyev	m->outer_l3_len = 0;
80aa97dd1cSKonstantin Ananyev}
81aa97dd1cSKonstantin Ananyev
82aa97dd1cSKonstantin Ananyevint
83aa97dd1cSKonstantin Ananyevis_ipv4_frag(const struct ipv4_hdr *iph)
84aa97dd1cSKonstantin Ananyev{
85aa97dd1cSKonstantin Ananyev	const uint16_t mask = rte_cpu_to_be_16(~IPV4_HDR_DF_FLAG);
86aa97dd1cSKonstantin Ananyev
87aa97dd1cSKonstantin Ananyev	return ((mask & iph->fragment_offset) != 0);
88aa97dd1cSKonstantin Ananyev}
89aa97dd1cSKonstantin Ananyev
90aa97dd1cSKonstantin Ananyevvoid
91aa97dd1cSKonstantin Ananyevfill_ipv4_hdr_len(struct rte_mbuf *m, uint32_t l2, uint32_t proto,
92aa97dd1cSKonstantin Ananyev	uint32_t frag)
93aa97dd1cSKonstantin Ananyev{
94aa97dd1cSKonstantin Ananyev	const struct ipv4_hdr *iph;
95aa97dd1cSKonstantin Ananyev	int32_t dlen, len;
96aa97dd1cSKonstantin Ananyev
97aa97dd1cSKonstantin Ananyev	dlen = rte_pktmbuf_data_len(m);
98aa97dd1cSKonstantin Ananyev	dlen -= l2 + sizeof(struct udp_hdr);
99aa97dd1cSKonstantin Ananyev
100aa97dd1cSKonstantin Ananyev	iph = rte_pktmbuf_mtod_offset(m, const struct ipv4_hdr *, l2);
101aa97dd1cSKonstantin Ananyev	len = (iph->version_ihl & IPV4_HDR_IHL_MASK) * IPV4_IHL_MULTIPLIER;
102aa97dd1cSKonstantin Ananyev
103aa97dd1cSKonstantin Ananyev	if (frag != 0 && is_ipv4_frag(iph)) {
104aa97dd1cSKonstantin Ananyev		m->packet_type &= ~RTE_PTYPE_L4_MASK;
105aa97dd1cSKonstantin Ananyev		m->packet_type |= RTE_PTYPE_L4_FRAG;
106aa97dd1cSKonstantin Ananyev	}
107aa97dd1cSKonstantin Ananyev
108aa97dd1cSKonstantin Ananyev	if (len > dlen || (proto <= IPPROTO_MAX && iph->next_proto_id != proto))
109aa97dd1cSKonstantin Ananyev		m->packet_type = RTE_PTYPE_UNKNOWN;
110aa97dd1cSKonstantin Ananyev	else
111aa97dd1cSKonstantin Ananyev		fill_pkt_hdr_len(m, l2, len, sizeof(struct udp_hdr));
112aa97dd1cSKonstantin Ananyev}
113aa97dd1cSKonstantin Ananyev
114aa97dd1cSKonstantin Ananyevint
115aa97dd1cSKonstantin Ananyevipv6x_hdr(uint32_t proto)
116aa97dd1cSKonstantin Ananyev{
117aa97dd1cSKonstantin Ananyev	return (proto == IPPROTO_HOPOPTS ||
118aa97dd1cSKonstantin Ananyev		proto == IPPROTO_ROUTING ||
119aa97dd1cSKonstantin Ananyev		proto == IPPROTO_FRAGMENT ||
120aa97dd1cSKonstantin Ananyev		proto == IPPROTO_AH ||
121aa97dd1cSKonstantin Ananyev		proto == IPPROTO_NONE ||
122aa97dd1cSKonstantin Ananyev		proto == IPPROTO_DSTOPTS);
123aa97dd1cSKonstantin Ananyev}
124aa97dd1cSKonstantin Ananyev
125aa97dd1cSKonstantin Ananyevuint16_t
126aa97dd1cSKonstantin Ananyevipv4x_cksum(const void *iph, size_t len)
127aa97dd1cSKonstantin Ananyev{
128aa97dd1cSKonstantin Ananyev        uint16_t cksum;
129aa97dd1cSKonstantin Ananyev
130aa97dd1cSKonstantin Ananyev        cksum = rte_raw_cksum(iph, len);
131aa97dd1cSKonstantin Ananyev        return (cksum == 0xffff) ? cksum : ~cksum;
132aa97dd1cSKonstantin Ananyev}
133aa97dd1cSKonstantin Ananyev
134aa97dd1cSKonstantin Ananyevvoid
135aa97dd1cSKonstantin Ananyevfill_ipv6x_hdr_len(struct rte_mbuf *m, uint32_t l2, uint32_t nproto,
136aa97dd1cSKonstantin Ananyev	uint32_t fproto)
137aa97dd1cSKonstantin Ananyev{
138aa97dd1cSKonstantin Ananyev	const struct ip6_ext *ipx;
139aa97dd1cSKonstantin Ananyev	int32_t dlen, len, ofs;
140aa97dd1cSKonstantin Ananyev
141aa97dd1cSKonstantin Ananyev	len = sizeof(struct ipv6_hdr);
142aa97dd1cSKonstantin Ananyev
143aa97dd1cSKonstantin Ananyev	dlen = rte_pktmbuf_data_len(m);
144aa97dd1cSKonstantin Ananyev	dlen -= l2 + sizeof(struct udp_hdr);
145aa97dd1cSKonstantin Ananyev
146aa97dd1cSKonstantin Ananyev	ofs = l2 + len;
147aa97dd1cSKonstantin Ananyev	ipx = rte_pktmbuf_mtod_offset(m, const struct ip6_ext *, ofs);
148aa97dd1cSKonstantin Ananyev
149aa97dd1cSKonstantin Ananyev	while (ofs > 0 && len < dlen) {
150aa97dd1cSKonstantin Ananyev
151aa97dd1cSKonstantin Ananyev		switch (nproto) {
152aa97dd1cSKonstantin Ananyev		case IPPROTO_HOPOPTS:
153aa97dd1cSKonstantin Ananyev		case IPPROTO_ROUTING:
154aa97dd1cSKonstantin Ananyev		case IPPROTO_DSTOPTS:
155aa97dd1cSKonstantin Ananyev			ofs = (ipx->ip6e_len + 1) << 3;
156aa97dd1cSKonstantin Ananyev			break;
157aa97dd1cSKonstantin Ananyev		case IPPROTO_AH:
158aa97dd1cSKonstantin Ananyev			ofs = (ipx->ip6e_len + 2) << 2;
159aa97dd1cSKonstantin Ananyev			break;
160aa97dd1cSKonstantin Ananyev		case IPPROTO_FRAGMENT:
161aa97dd1cSKonstantin Ananyev			/*
162aa97dd1cSKonstantin Ananyev			 * tso_segsz is not used by RX, so suse it as temporary
163aa97dd1cSKonstantin Ananyev			 * buffer to store the fragment offset.
164aa97dd1cSKonstantin Ananyev			 */
165aa97dd1cSKonstantin Ananyev			m->tso_segsz = ofs;
166aa97dd1cSKonstantin Ananyev			ofs = sizeof(struct ip6_frag);
167aa97dd1cSKonstantin Ananyev			m->packet_type &= ~RTE_PTYPE_L4_MASK;
168aa97dd1cSKonstantin Ananyev			m->packet_type |= RTE_PTYPE_L4_FRAG;
169aa97dd1cSKonstantin Ananyev			break;
170aa97dd1cSKonstantin Ananyev		default:
171aa97dd1cSKonstantin Ananyev			ofs = 0;
172aa97dd1cSKonstantin Ananyev		}
173aa97dd1cSKonstantin Ananyev
174aa97dd1cSKonstantin Ananyev		if (ofs > 0) {
175aa97dd1cSKonstantin Ananyev			nproto = ipx->ip6e_nxt;
176aa97dd1cSKonstantin Ananyev			len += ofs;
177aa97dd1cSKonstantin Ananyev			ipx += ofs / sizeof(*ipx);
178aa97dd1cSKonstantin Ananyev		}
179aa97dd1cSKonstantin Ananyev	}
180aa97dd1cSKonstantin Ananyev
181aa97dd1cSKonstantin Ananyev	/* undercognised or invalid packet. */
182aa97dd1cSKonstantin Ananyev	if ((ofs == 0 && nproto != fproto) || len > dlen)
183aa97dd1cSKonstantin Ananyev		m->packet_type = RTE_PTYPE_UNKNOWN;
184aa97dd1cSKonstantin Ananyev	else
185aa97dd1cSKonstantin Ananyev		fill_pkt_hdr_len(m, l2, len, sizeof(struct udp_hdr));
186aa97dd1cSKonstantin Ananyev}
187aa97dd1cSKonstantin Ananyev
188aa97dd1cSKonstantin Ananyevvoid
189aa97dd1cSKonstantin Ananyevfill_ipv6_hdr_len(struct rte_mbuf *m, uint32_t l2, uint32_t fproto)
190aa97dd1cSKonstantin Ananyev{
191aa97dd1cSKonstantin Ananyev	const struct ipv6_hdr *iph;
192aa97dd1cSKonstantin Ananyev
193aa97dd1cSKonstantin Ananyev	iph = rte_pktmbuf_mtod_offset(m, const struct ipv6_hdr *,
194aa97dd1cSKonstantin Ananyev		sizeof(struct ether_hdr));
195aa97dd1cSKonstantin Ananyev
196aa97dd1cSKonstantin Ananyev	if (iph->proto == fproto)
197aa97dd1cSKonstantin Ananyev		fill_pkt_hdr_len(m, l2, sizeof(struct ipv6_hdr),
198aa97dd1cSKonstantin Ananyev			sizeof(struct udp_hdr));
199aa97dd1cSKonstantin Ananyev	else if (ipv6x_hdr(iph->proto) != 0)
200aa97dd1cSKonstantin Ananyev		fill_ipv6x_hdr_len(m, l2, iph->proto, fproto);
201aa97dd1cSKonstantin Ananyev}
202aa97dd1cSKonstantin Ananyev
203aa97dd1cSKonstantin Ananyevvoid
204aa97dd1cSKonstantin Ananyevfill_eth_hdr_len(struct rte_mbuf *m)
205aa97dd1cSKonstantin Ananyev{
206aa97dd1cSKonstantin Ananyev	uint32_t dlen, l2;
207aa97dd1cSKonstantin Ananyev	uint16_t etp;
208aa97dd1cSKonstantin Ananyev	const struct ether_hdr *eth;
209aa97dd1cSKonstantin Ananyev
210aa97dd1cSKonstantin Ananyev	dlen = rte_pktmbuf_data_len(m);
211aa97dd1cSKonstantin Ananyev
212aa97dd1cSKonstantin Ananyev	/* check that first segment is at least 42B long. */
213aa97dd1cSKonstantin Ananyev	if (dlen < sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
214aa97dd1cSKonstantin Ananyev			sizeof(struct udp_hdr)) {
215aa97dd1cSKonstantin Ananyev		m->packet_type = RTE_PTYPE_UNKNOWN;
216aa97dd1cSKonstantin Ananyev		return;
217aa97dd1cSKonstantin Ananyev	}
218aa97dd1cSKonstantin Ananyev
219aa97dd1cSKonstantin Ananyev	l2 = sizeof(*eth);
220aa97dd1cSKonstantin Ananyev
221aa97dd1cSKonstantin Ananyev	eth = rte_pktmbuf_mtod(m, const struct ether_hdr *);
222aa97dd1cSKonstantin Ananyev	etp = eth->ether_type;
223aa97dd1cSKonstantin Ananyev	if (etp == rte_be_to_cpu_16(ETHER_TYPE_VLAN))
224aa97dd1cSKonstantin Ananyev		l2 += sizeof(struct vlan_hdr);
225aa97dd1cSKonstantin Ananyev
226aa97dd1cSKonstantin Ananyev	if (etp == rte_be_to_cpu_16(ETHER_TYPE_IPv4)) {
227aa97dd1cSKonstantin Ananyev		m->packet_type = RTE_PTYPE_L4_UDP |
228aa97dd1cSKonstantin Ananyev			RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
229aa97dd1cSKonstantin Ananyev			RTE_PTYPE_L2_ETHER;
230aa97dd1cSKonstantin Ananyev		fill_ipv4_hdr_len(m, l2, IPPROTO_UDP, 1);
231aa97dd1cSKonstantin Ananyev	} else if (etp == rte_be_to_cpu_16(ETHER_TYPE_IPv6) &&
232aa97dd1cSKonstantin Ananyev			dlen >= l2 + sizeof(struct ipv6_hdr) +
233aa97dd1cSKonstantin Ananyev			sizeof(struct udp_hdr)) {
234aa97dd1cSKonstantin Ananyev		m->packet_type = RTE_PTYPE_L4_UDP |
235aa97dd1cSKonstantin Ananyev			RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
236aa97dd1cSKonstantin Ananyev			RTE_PTYPE_L2_ETHER;
237aa97dd1cSKonstantin Ananyev			fill_ipv6_hdr_len(m, l2, IPPROTO_UDP);
238aa97dd1cSKonstantin Ananyev	} else
239aa97dd1cSKonstantin Ananyev		m->packet_type = RTE_PTYPE_UNKNOWN;
240aa97dd1cSKonstantin Ananyev}
241aa97dd1cSKonstantin Ananyev
242aa97dd1cSKonstantin Ananyev/*
243aa97dd1cSKonstantin Ananyev * generic, assumes HW doesn't recognise any packet type.
244aa97dd1cSKonstantin Ananyev */
245aa97dd1cSKonstantin Ananyevuint16_t
246aa97dd1cSKonstantin Ananyevtypen_rx_callback(uint8_t port, __rte_unused uint16_t queue,
247aa97dd1cSKonstantin Ananyev	struct rte_mbuf *pkt[], uint16_t nb_pkts,
248aa97dd1cSKonstantin Ananyev	__rte_unused uint16_t max_pkts, void *user_param)
249aa97dd1cSKonstantin Ananyev{
250aa97dd1cSKonstantin Ananyev	uint32_t j;
251aa97dd1cSKonstantin Ananyev
252aa97dd1cSKonstantin Ananyev	for (j = 0; j != nb_pkts; j++) {
253aa97dd1cSKonstantin Ananyev		fill_eth_hdr_len(pkt[j]);
254aa97dd1cSKonstantin Ananyev
255aa97dd1cSKonstantin Ananyev	}
256aa97dd1cSKonstantin Ananyev
257aa97dd1cSKonstantin Ananyev	return nb_pkts;
258aa97dd1cSKonstantin Ananyev}
259aa97dd1cSKonstantin Ananyev
260aa97dd1cSKonstantin Ananyevint
261aa97dd1cSKonstantin Ananyevdummy_lookup4(void *opaque, const struct in_addr *addr, struct tle_dest *res)
262aa97dd1cSKonstantin Ananyev{
263aa97dd1cSKonstantin Ananyev	RTE_SET_USED(opaque);
264aa97dd1cSKonstantin Ananyev	RTE_SET_USED(addr);
265aa97dd1cSKonstantin Ananyev	RTE_SET_USED(res);
266aa97dd1cSKonstantin Ananyev	return -ENOENT;
267aa97dd1cSKonstantin Ananyev}
268aa97dd1cSKonstantin Ananyev
269aa97dd1cSKonstantin Ananyevint
270aa97dd1cSKonstantin Ananyevdummy_lookup6(void *opaque, const struct in6_addr *addr, struct tle_dest *res)
271aa97dd1cSKonstantin Ananyev{
272aa97dd1cSKonstantin Ananyev	RTE_SET_USED(opaque);
273aa97dd1cSKonstantin Ananyev	RTE_SET_USED(addr);
274aa97dd1cSKonstantin Ananyev	RTE_SET_USED(res);
275aa97dd1cSKonstantin Ananyev	return -ENOENT;
276aa97dd1cSKonstantin Ananyev}