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#ifndef TEST_TLE_UDP_STREAM_H_
17#define TEST_TLE_UDP_STREAM_H_
18#include <iostream>
19#include <algorithm>
20#include <string>
21#include <arpa/inet.h>
22#include <netinet/in.h>
23#include <netinet/ip6.h>
24#include <gtest/gtest.h>
25#include <gmock/gmock.h>
26#include <rte_errno.h>
27
28#include <tle_udp.h>
29#include <tle_event.h>
30
31#include "test_common.h"
32
33#define MAX_STREAMS 0xFFFF
34#define MAX_STREAM_RBUFS 0x100
35#define MAX_STREAM_SBUFS 0x100
36#define RX_OFFLOAD 0x100
37#define TX_OFFLOAD 0x100
38
39using namespace std;
40
41struct tle_ctx_param ctx_prm_tmpl = {
42	.socket_id = SOCKET_ID_ANY,
43	.proto = TLE_PROTO_UDP,
44	.max_streams = MAX_STREAMS,
45	.max_stream_rbufs = MAX_STREAM_RBUFS,
46	.max_stream_sbufs = MAX_STREAM_SBUFS
47};
48
49struct tle_dev_param dev_prm_tmpl = {
50	.rx_offload = RX_OFFLOAD,
51	.tx_offload = TX_OFFLOAD
52};
53
54class test_tle_udp_stream: public ::testing::Test {
55public:
56	void setup_dev_prm(struct tle_dev_param *,
57			char const *, char const *);
58	struct tle_ctx *setup_ctx(struct tle_ctx_param *prm);
59	struct tle_dev *setup_dev(struct tle_ctx *ctx,
60			struct tle_dev_param *dev_prm);
61	struct tle_evq *setup_event();
62
63	virtual void SetUp(void)
64	{
65		char const *ipv4_laddr = "192.0.0.1";
66		char const *ipv4_raddr = "10.0.0.1";
67		char const *ipv6 = "fe80::21e:67ff:fec2:2568";
68		struct tle_ctx_param cprm;
69		port = 10000;
70
71		ctx = nullptr;
72		dev = nullptr;
73		stream = nullptr;
74		/* Setup Context */
75		cprm = ctx_prm_tmpl;
76		cprm.max_streams = 0xA;
77		cprm.lookup4 = dummy_lookup4;
78		cprm.lookup6 = dummy_lookup6;
79		ctx = setup_ctx(&cprm);
80		ASSERT_NE(ctx, nullptr);
81
82		/* Setup Dev */
83		memset(&dev_prm, 0, sizeof(dev_prm));
84		setup_dev_prm(&dev_prm, ipv4_laddr, ipv6);
85		dev = setup_dev(ctx, &dev_prm);
86		ASSERT_NE(dev, nullptr);
87
88		/* Stream Param & Event param */
89		memset(&stream_prm, 0, sizeof(struct tle_udp_stream_param));
90
91		ip4_addr = (struct sockaddr_in *) &stream_prm.local_addr;
92		ip4_addr->sin_family = AF_INET;
93		ip4_addr->sin_port = htons(port);
94		ip4_addr->sin_addr.s_addr = inet_addr(ipv4_laddr);
95
96		ip4_addr = (struct sockaddr_in *) &stream_prm.remote_addr;
97		ip4_addr->sin_family = AF_INET;
98		ip4_addr->sin_port = htons(port);
99		ip4_addr->sin_addr.s_addr = inet_addr(ipv4_raddr);
100
101		stream_prm.recv_ev = tle_event_alloc(setup_event(), nullptr);
102		stream_prm.send_ev = tle_event_alloc(setup_event(), nullptr);
103	}
104
105	virtual void TearDown(void)
106	{
107		ret = 0;
108		for (auto s : streams)
109			tle_udp_stream_close(s);
110
111		tle_del_dev(dev);
112		tle_ctx_destroy(ctx);
113	}
114
115	int ret;
116	int port;
117	struct tle_ctx *ctx;
118	struct tle_dev *dev;
119	struct tle_stream *stream;
120	struct tle_ctx_param ctx_prm;
121	struct tle_dev_param dev_prm;
122	struct tle_udp_stream_param stream_prm;
123	struct sockaddr_in *ip4_addr;
124
125	vector<tle_stream *> streams;
126};
127
128struct tle_evq *
129test_tle_udp_stream::setup_event()
130{
131	int32_t socket_id;
132	uint32_t max_events;
133	struct tle_evq_param evq_params;
134	struct tle_evq *evq;
135
136	socket_id = SOCKET_ID_ANY;
137	max_events = 10;
138	rte_errno = 0;
139	memset(&evq_params, 0, sizeof(struct tle_evq_param));
140	evq_params.socket_id = socket_id;
141	evq_params.max_events = max_events;
142	evq = tle_evq_create(&evq_params);
143	return evq;
144}
145
146struct tle_ctx
147*test_tle_udp_stream::setup_ctx(struct tle_ctx_param *prm)
148{
149	struct tle_ctx *ctx;
150
151	ctx = tle_ctx_create(prm);
152
153	return ctx;
154}
155
156struct tle_dev
157*test_tle_udp_stream::setup_dev(struct tle_ctx *ctx,
158	struct tle_dev_param *dev_prm)
159{
160	struct tle_dev *dev;
161
162	dev = tle_add_dev(ctx, dev_prm);
163
164	return dev;
165}
166
167void
168test_tle_udp_stream::setup_dev_prm(struct tle_dev_param *dev_prm,
169	char const *ipv4, char const *ipv6)
170{
171	inet_pton(AF_INET, ipv4, &dev_prm->local_addr4);
172	inet_pton(AF_INET6, ipv6, &dev_prm->local_addr6);
173
174}
175
176/* Fixture for max number of streams on single ctx + multiple devices */
177class test_tle_udp_stream_max: public ::test_tle_udp_stream {
178public:
179
180	virtual void SetUp(void)
181	{
182		/* Create enough devices and streams to exceed
183		 * MAX_STREAMS on ctx
184		 */
185		nb_devs = 10;
186		nb_streams = 6554;
187
188		in_addr_t src;
189		string ssrc;
190
191		memset(&ctx_prm, 0, sizeof(ctx_prm));
192		ctx_prm = ctx_prm_tmpl;
193		ctx_prm.lookup4 = dummy_lookup4;
194		ctx_prm.lookup6 = dummy_lookup6;
195		ctx = setup_ctx(&ctx_prm);
196		ASSERT_NE(ctx, (void *)NULL);
197
198		memset(&dev_prm, 0, sizeof(dev_prm));
199		setup_dev_prm(&dev_prm, base_l_ipv4, base_l_ipv6);
200
201		memset(&stream_prm, 0, sizeof(struct tle_udp_stream_param));
202		stream_prm.recv_ev = tle_event_alloc(setup_event(), nullptr);
203		stream_prm.send_ev = tle_event_alloc(setup_event(), nullptr);
204
205		for (i = 0; i < nb_devs; i++) {
206			ssrc = inet_ntoa(dev_prm.local_addr4);
207
208			dev = setup_dev(ctx, &dev_prm);
209			ASSERT_NE(dev, (void *)NULL);
210			devs.push_back(dev);
211
212			/* Modify base IP addresses for next loops */
213			src = dev_prm.local_addr4.s_addr;
214			src += 1;
215			dev_prm.local_addr4.s_addr = src;
216		}
217	}
218
219	virtual void TearDown(void)
220	{
221		for (auto s : streams)
222			tle_udp_stream_close(s);
223
224		for (auto d : devs)
225			tle_del_dev(d);
226
227		tle_ctx_destroy(ctx);
228	}
229
230	int i;
231	int nb_devs;
232	int nb_streams;
233	char const *base_l_ipv4 = "10.0.0.1";
234	char const *base_r_ipv4 = "190.0.0.1";
235	char const *base_l_ipv6 = "2000::1";
236	vector<tle_dev *> devs;
237	vector<tle_stream *> streams;
238};
239
240#endif /* TEST_TLE_UDP_STREAM_H_ */
241