test_tle_udp_stream_gen.cpp revision aa97dd1c
1/*
2 * Copyright (c) 2016  Intel Corporation.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "test_tle_udp_stream_gen.h"
17
18TEST_P(tle_rx_enobufs, enobufs_test)
19{
20	int j, pkt_cnt = 0, enobufs_cnt = 0;
21	uint16_t nb_rx, nb_rx_bulk;
22	struct rte_mbuf *m[BURST_SIZE];
23	struct rte_mbuf *rp[BURST_SIZE];
24	int rc[BURST_SIZE];
25
26	/* Receive packets until we reach end on pcap file*/
27	do {
28		memset(rc, 0, sizeof(int) * BURST_SIZE);
29		nb_rx = rte_eth_rx_burst(portid, 0, m, BURST_SIZE);
30		pkt_cnt += nb_rx;
31		for(auto &d: tp.devs){
32			nb_rx_bulk = tle_udp_rx_bulk(d.ptr, m, rp, rc, nb_rx);
33			for(j = 0; j < BURST_SIZE; j++) {
34				if(rc[j] == ENOBUFS) {
35					enobufs_cnt++;
36				}
37			}
38			d.act_pkts_bulk_rx += nb_rx_bulk;
39		}
40	} while (nb_rx > 0);
41
42	/*
43	 * Verify results - number of rx packets per dev and stream
44	 * and packets dropped due to ENOBUFS
45	 */
46
47	for(auto &d: tp.devs) {
48		EXPECT_EQ(d.act_pkts_bulk_rx, d.exp_pkts_bulk_rx);
49		EXPECT_EQ(enobufs_cnt, pkt_cnt - d.act_pkts_bulk_rx);
50	}
51}
52/*
53 * TODO: Obviously this way of defining test scenarios is terrible.
54 * Need to move to JSON files in future and parse from external file.
55 * Currently first commented out entry is an example of what values should be
56 * inserted into certain fields
57 * */
58INSTANTIATE_TEST_CASE_P(enobufs_test, tle_rx_enobufs, testing::Values(
59/* test_str example */
60/* {
61	"Description",
62	Devices configs below
63	{
64		{"Dev local IPv4", "Dev local IPv6",
65			RX_OFFLOAD, TX_OFFLOAD,
66			Exp. nb. of rx pkts on device,
67			Exp. nb. of tx pkts on device,
68			Exp. nb. of total ENOENT pkts on device,
69		},
70	},
71	Streams config on device below
72	{
73		{local port, remote port, "local ip", "remote ip",
74		exp. nb. of rx. pkts, exp. nb. of tx. pkts},
75	},
76	Pkts to generate with scapy to pcap file
77	{
78		{"Src IP", "Dst IP",
79		Src port, Dst port,
80		nb of pkts,
81		l3 chksum, l4 chksum, fragment?},
82	}
83}, */
84test_str
85{
86	"IPv4 - 1 dev 1 stream, only correct pkts",
87	{
88		{"10.0.0.1", "2001::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD,
89				CTX_MAX_RBUFS - 1, 0, 0}
90	},
91	{
92		{AF_INET, 10001, 10002, "10.0.0.1", "10.0.0.2", 0, 0},
93	},
94	{
95		{AF_INET, "10.0.0.2", "10.0.0.1", 10002, 10001, 1000, 0, 0, 0},
96	}
97},
98test_str
99{
100	"IPv4 - 1 dev 1 stream, only correct pkts",
101	{
102		{"10.0.0.1", "2001::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD,
103				CTX_MAX_RBUFS - 1, 0, 0, 0}
104	},
105	{
106		{AF_INET6, 10001, 10002, "2001::1000", "2001::2000", 0, 0},
107	},
108	{
109		{AF_INET6, "2001::2000", "2001::1000", 10002, 10001, 1000, 0, 0, 0},
110	}
111}
112));
113
114TEST_P(tle_rx_test, test)
115{
116	int j;
117	uint16_t nb_rx, nb_rx_bulk, nb_str_rx;
118	struct rte_mbuf *m[BURST_SIZE];
119	struct rte_mbuf *n[BURST_SIZE];
120	struct rte_mbuf *rp[BURST_SIZE];
121	int rc[BURST_SIZE];
122
123	/* Receive packets until we reach end on pcap file*/
124	do {
125		nb_rx = rte_eth_rx_burst(portid, 0, m, BURST_SIZE);
126		for(auto &d: tp.devs) {
127			memset(rc, 0, sizeof(int) * BURST_SIZE);
128			nb_rx_bulk = tle_udp_rx_bulk(d.ptr, m, rp, rc, nb_rx);
129			d.act_pkts_bulk_rx += nb_rx_bulk;
130			for(j = 0; j < BURST_SIZE; j++) {
131				if(rc[j] == ENOENT)
132					d.act_pkts_enoent += 1;
133			}
134		}
135
136		for(auto &s: tp.streams) {
137			nb_str_rx = tle_udp_stream_recv(s.ptr, n, BURST_SIZE);
138			s.act_pkts_rx += nb_str_rx;
139		}
140	} while (nb_rx > 0);
141
142
143	/*
144	 * Verify results - number of rx packets per dev and stream.
145	 */
146	for(auto &d: tp.devs) {
147		EXPECT_EQ(d.act_pkts_bulk_rx, d.exp_pkts_bulk_rx);
148		EXPECT_EQ(d.act_pkts_enoent, d.exp_pkts_enoent);
149	}
150
151	for(auto &s: tp.streams) {
152		EXPECT_EQ(s.act_pkts_rx, s.exp_pkts_rx);
153	}
154}
155INSTANTIATE_TEST_CASE_P(rx_recv, tle_rx_test, testing::Values(
156test_str
157{
158	"IPv4 - 1 dev 1 stream, only correct pkts",
159	{
160		{"10.0.0.1", "2001::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 10, 0, 0},
161	},
162	{
163		{AF_INET, 10001, 10002, "10.0.0.1", "10.0.0.2", 10, 0},
164	},
165	{
166		{AF_INET, "10.0.0.2", "10.0.0.1", 10002, 10001, 10, 0, 0, 0},
167	}
168},
169
170test_str
171{
172	"IPv4 - 1 dev 1 stream, only incorrect pkts",
173	{
174		{"10.0.0.1", "2001::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 0, 0, 40},
175	},
176	{
177		{AF_INET, 10001, 10002, "10.0.0.1", "10.0.0.2", 0, 0},
178	},
179	{
180		{AF_INET, "20.0.0.2", "10.0.0.1", 10002, 10001, 10, 0, 0, 0},
181		{AF_INET, "10.0.0.2", "20.0.0.1", 10002, 10001, 10, 0, 0, 0},
182		{AF_INET, "10.0.0.2", "10.0.0.1", 20002, 10001, 10, 0, 0, 0},
183		{AF_INET, "10.0.0.2", "10.0.0.1", 10002, 20001, 10, 0, 0, 0},
184	}
185},
186
187test_str
188{
189	"IPv4 - 1 dev with 1 stream, only correct pkts but incorrect chksum",
190	{
191		{"10.0.0.1", "2001::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 30, 0, 0}
192	},
193	{
194		{AF_INET, 10001, 10002, "10.0.0.1", "10.0.0.2", 0, 0},
195	},
196	{
197		{AF_INET, "10.0.0.2", "10.0.0.1", 10002, 10001, 10, 1, 0, 0},
198		{AF_INET, "10.0.0.2", "10.0.0.1", 10002, 10001, 10, 0, 1, 0},
199		{AF_INET, "10.0.0.2", "10.0.0.1", 10002, 10001, 10, 1, 1, 0},
200	}
201},
202
203test_str
204{
205	"IPv6 - 1 dev with 1 stream, only correct pkts",
206	{
207		{"10.0.0.1", "2001::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 10, 0, 0}
208	},
209	{
210		{AF_INET6, 10001, 10002, "2001::1000", "2001::2000", 10, 0},
211	},
212	{
213		{AF_INET6, "2001::2000", "2001::1000", 10002, 10001, 10, 0, 0, 0},
214	}
215},
216
217test_str
218{
219	"IPv6 - 1 dev with 1 stream, only incorrect pkts",
220	{
221		{"10.0.0.1", "2001::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 0, 0, 40},
222	},
223	{
224		{AF_INET6, 10001, 10002, "2001::1000", "2001::2000", 0, 0},
225	},
226	{
227		{AF_INET6, "3001::2000", "2001::1000", 10002, 10001, 10, 0, 0, 0},
228		{AF_INET6, "2001::3000", "2001::1000", 10002, 10001, 10, 0, 0, 0},
229		{AF_INET6, "2001::2000", "2001::1000", 30002, 10001, 10, 0, 0, 0},
230		{AF_INET6, "2001::2000", "2001::1000", 10002, 30001, 10, 0, 0, 0},
231	}
232},
233
234test_str
235{
236	"IPv6 - 1 dev with 1 stream, only correct pkts but incorrect chksum",
237	/*
238	 * Note: one of streams will be received as IPv6 does not have
239	 * checksum field by default.
240	 */
241	{
242		{"10.0.0.1", "2001::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 30, 0, 0}
243	},
244	{
245		{AF_INET6, 10001, 10002, "2001::1000", "2001::2000", 10, 0},
246	},
247	{
248		{AF_INET6, "2001::2000", "2001::1000", 10002, 10001, 10, 1, 0, 0},
249		{AF_INET6, "2001::2000", "2001::1000", 10002, 10001, 10, 0, 1, 0},
250		{AF_INET6, "2001::2000", "2001::1000", 10002, 10001, 10, 1, 1, 0},
251	}
252},
253
254test_str
255{
256	/* Multiple streams, multiple correct pkt streams, mixed IPv4 & IPv6;
257	 * 3 dev, 3 stream per dev, only correct pkts */
258	"Mixed IPv4+IPv6; Multiple devs with multiple correct streams",
259	{
260		{"10.0.0.1", "2001::1000",RX_NO_OFFLOAD, TX_NO_OFFLOAD, 300, 0, 600},
261		{"20.0.0.1", "2002::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 300, 0, 600},
262		{"30.0.0.1", "2003::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 300, 0, 600},
263	},
264	{
265		{AF_INET, 10001, 10011, "10.0.0.1", "10.0.0.2", 100, 0},
266		{AF_INET, 10002, 10012, "10.0.0.1", "10.0.0.3", 100, 0},
267		{AF_INET6, 10003, 10013, "2001::1000", "2001::4000", 100, 0},
268		{AF_INET, 20001, 20011, "20.0.0.1", "20.0.0.2", 100, 0},
269		{AF_INET6, 20002, 20012, "2002::1000", "2002::3000", 100, 0},
270		{AF_INET6, 20003, 20013, "2002::1000", "2002::4000", 100, 0},
271		{AF_INET, 20001, 20011, "30.0.0.1", "30.0.0.2", 100, 0},
272		{AF_INET6, 20002, 20012, "2003::1000", "2003::3000", 100, 0},
273		{AF_INET6, 20003, 20013, "2003::1000", "2003::4000", 100, 0}
274	},
275	{
276		{AF_INET, "10.0.0.2", "10.0.0.1", 10011, 10001, 100, 0, 0, 0},
277		{AF_INET, "10.0.0.3", "10.0.0.1", 10012, 10002, 100, 0, 0, 0},
278		{AF_INET, "20.0.0.2", "20.0.0.1", 20011, 20001, 100, 0, 0, 0},
279		{AF_INET, "30.0.0.2", "30.0.0.1", 20011, 20001, 100, 0, 0, 0},
280		{AF_INET6, "2001::4000", "2001::1000", 10013, 10003, 100, 0, 0, 0},
281		{AF_INET6, "2002::3000", "2002::1000", 20012, 20002, 100, 0, 0, 0},
282		{AF_INET6, "2002::4000", "2002::1000", 20013, 20003, 100, 0, 0, 0},
283		{AF_INET6, "2003::3000", "2003::1000", 20012, 20002, 100, 0, 0, 0},
284		{AF_INET6, "2003::4000", "2003::1000", 20013, 20003, 100, 0, 0, 0},
285	}
286}
287));
288
289TEST_P(tle_tx_test, tx_send)
290{
291	int i, j, s, pkts_to_send;
292	uint16_t nb_tx, nb_tx_bulk, nb_str_tx;
293	struct rte_mbuf *m[BURST_SIZE];
294	struct rte_mbuf *n[BURST_SIZE];
295	int rc[BURST_SIZE];
296	struct sockaddr_storage dest;
297	uint8_t *plaintext;
298	unsigned plaintext_len;
299	unsigned plaintext_pad_len;
300	char text[]="DEADBEEF";
301
302	for(auto &sg: tp.gen_streams) {
303
304		/* Find from which stream we will be sending - save the pointer and
305		 * index number for later TX counter validation */
306		for(s = 0; s < tp.streams.size(); s++) {
307			auto tmp = tp.streams[s];
308			if(sg.dst_ip.compare(tmp.l_ip) == 0 && sg.dst_port == tmp.l_port) {
309				stream = tmp.ptr;
310				break;
311			}
312		}
313
314		/* Prepare sockaddr for sending */
315		memset(&dest, 0, sizeof(dest));
316		if (sg.family == AF_INET) {
317			((sockaddr_in *) &dest)->sin_family = AF_INET;
318			((sockaddr_in *) &dest)->sin_port = htons(sg.src_port);
319			inet_pton(AF_INET, sg.src_ip.c_str(),
320					&((sockaddr_in *) &dest)->sin_addr);
321		} else if (sg.family == AF_INET6) {
322			((sockaddr_in6 *) &dest)->sin6_family = AF_INET6;
323			((sockaddr_in6 *) &dest)->sin6_port = htons(sg.src_port);
324			inet_pton(AF_INET6, sg.src_ip.c_str(),
325					&((sockaddr_in6 *) &dest)->sin6_addr);
326		}
327
328		nb_str_tx = 0;
329		/* Send all packets to stream*/
330		for(i = 0; i < sg.nb_pkts; i += nb_str_tx) {
331			pkts_to_send = (sg.nb_pkts - i < BURST_SIZE) ?
332					(sg.nb_pkts - i) : BURST_SIZE;
333
334			/* Allocate Mbufs */
335			for(j = 0; j < pkts_to_send; j++) {
336				m[j] = rte_pktmbuf_alloc(mbuf_pool);
337				ASSERT_NE(m[j], nullptr);
338
339				memset(rte_pktmbuf_mtod(m[j], uint8_t *), 0,
340					       rte_pktmbuf_tailroom(m[j]));
341				plaintext = (uint8_t *)rte_pktmbuf_append(m[j],
342							sizeof(text));
343				memcpy(rte_pktmbuf_mtod(m[j], uint8_t *), &text, sizeof(text));
344			}
345
346			nb_str_tx = tle_udp_stream_send(stream, m, pkts_to_send,
347					reinterpret_cast<struct sockaddr*>(&dest));
348			ASSERT_GE(nb_str_tx, 0);
349			if(nb_str_tx == 0) {
350				for(j = 0; j < pkts_to_send; j++) {
351					rte_pktmbuf_free(m[j]);
352				}
353				nb_str_tx = pkts_to_send;
354				continue;
355			}
356			tp.streams[s].act_pkts_tx += nb_str_tx;
357		}
358	}
359
360	/* Send out packets from devices */
361	for(auto &d: tp.devs) {
362		nb_tx_bulk = 0;
363		do {
364			nb_tx_bulk = tle_udp_tx_bulk(d.ptr, n, BURST_SIZE);
365			ASSERT_GE(nb_str_tx, 0);
366			d.act_pkts_bulk_tx += nb_tx_bulk;
367			nb_tx = rte_eth_tx_burst(portid, 0, n, nb_tx_bulk);
368			ASSERT_GE(nb_str_tx, 0);
369		} while (nb_tx_bulk > 0);
370	}
371
372	/*
373	 * Verify results - number of rx packets per dev and stream.
374	 */
375	for(auto &d: tp.devs) {
376		EXPECT_EQ(d.act_pkts_bulk_tx, d.exp_pkts_bulk_tx);
377		EXPECT_EQ(d.act_pkts_enoent, d.exp_pkts_enoent);
378	}
379
380	for(auto &s: tp.streams) {
381		EXPECT_EQ(s.act_pkts_tx, s.exp_pkts_tx);
382	}
383}
384
385INSTANTIATE_TEST_CASE_P(test, tle_tx_test, testing::Values(
386test_str
387{
388	"IPv4 - 1 dev 1 stream, only correct pkts",
389	{
390		{"10.0.0.1", "2001::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 0, 100, 0},
391	},
392	{
393		{AF_INET, 10001, 10002, "10.0.0.1", "10.0.0.2", 0, 100},
394	},
395	{
396		{AF_INET, "10.0.0.2", "10.0.0.1", 10002, 10001, 100, 0, 0, 0},
397	}
398},
399test_str
400{
401	"IPv6 - 1 dev 1 stream, only correct pkts",
402	{
403		{"10.0.0.1", "2001::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 0, 100, 0},
404	},
405	{
406		{AF_INET6, 10001, 10002, "2001::1000", "2001::2000", 0, 100},
407	},
408	{
409		{AF_INET6, "2001::2000", "2001::1000", 10002, 10001, 100, 0, 0, 0},
410	}
411},
412test_str
413{
414	/* Multiple streams, mixed IPv4 & IPv6; */
415	"Mixed IPv4+IPv6; Multiple devs with multiple correct streams",
416	{
417		{"10.0.0.1", "2001::1000",RX_NO_OFFLOAD, TX_NO_OFFLOAD, 0, 300, 0},
418		{"20.0.0.1", "2002::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 0, 300, 0},
419		{"30.0.0.1", "2003::1000", RX_NO_OFFLOAD, TX_NO_OFFLOAD, 0, 300, 0},
420	},
421	{
422		{AF_INET, 10001, 10011, "10.0.0.1", "10.0.0.2", 0, 100},
423		{AF_INET, 10002, 10012, "10.0.0.1", "10.0.0.3", 0, 100},
424		{AF_INET6, 10003, 10013, "2001::1000", "2001::4000", 0, 100},
425		{AF_INET, 20001, 20011, "20.0.0.1", "20.0.0.2", 0, 100},
426		{AF_INET6, 20002, 20012, "2002::1000", "2002::3000", 0, 100},
427		{AF_INET6, 20003, 20013, "2002::1000", "2002::4000", 0, 100},
428		{AF_INET, 20001, 20011, "30.0.0.1", "30.0.0.2", 0, 100},
429		{AF_INET6, 20002, 20012, "2003::1000", "2003::3000", 0, 100},
430		{AF_INET6, 20003, 20013, "2003::1000", "2003::4000", 0, 100}
431	},
432	{
433		{AF_INET, "10.0.0.2", "10.0.0.1", 10011, 10001, 100, 0, 0, 0},
434		{AF_INET, "10.0.0.3", "10.0.0.1", 10012, 10002, 100, 0, 0, 0},
435		{AF_INET, "20.0.0.2", "20.0.0.1", 20011, 20001, 100, 0, 0, 0},
436		{AF_INET, "30.0.0.2", "30.0.0.1", 20011, 20001, 100, 0, 0, 0},
437		{AF_INET6, "2001::4000", "2001::1000", 10013, 10003, 100, 0, 0, 0},
438		{AF_INET6, "2002::3000", "2002::1000", 20012, 20002, 100, 0, 0, 0},
439		{AF_INET6, "2002::4000", "2002::1000", 20013, 20003, 100, 0, 0, 0},
440		{AF_INET6, "2003::3000", "2003::1000", 20012, 20002, 100, 0, 0, 0},
441		{AF_INET6, "2003::4000", "2003::1000", 20013, 20003, 100, 0, 0, 0},
442	}
443}
444));
445