1e18a033bSKonstantin Ananyev/*
2e18a033bSKonstantin Ananyev * Copyright (c) 2017  Intel Corporation.
3e18a033bSKonstantin Ananyev * All rights reserved.
4e18a033bSKonstantin Ananyev *
5e18a033bSKonstantin Ananyev * Redistribution and use in source and binary forms, with or without
6e18a033bSKonstantin Ananyev * modification, are permitted provided that the following conditions
7e18a033bSKonstantin Ananyev * are met:
8e18a033bSKonstantin Ananyev * 1. Redistributions of source code must retain the above copyright
9e18a033bSKonstantin Ananyev *    notice, this list of conditions and the following disclaimer.
10e18a033bSKonstantin Ananyev * 2. Redistributions in binary form must reproduce the above copyright
11e18a033bSKonstantin Ananyev *    notice, this list of conditions and the following disclaimer in the
12e18a033bSKonstantin Ananyev *    documentation and/or other materials provided with the distribution.
13e18a033bSKonstantin Ananyev *
14e18a033bSKonstantin Ananyev * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15e18a033bSKonstantin Ananyev * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16e18a033bSKonstantin Ananyev * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17e18a033bSKonstantin Ananyev * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18e18a033bSKonstantin Ananyev * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19e18a033bSKonstantin Ananyev * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20e18a033bSKonstantin Ananyev * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21e18a033bSKonstantin Ananyev * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22e18a033bSKonstantin Ananyev * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23e18a033bSKonstantin Ananyev * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24e18a033bSKonstantin Ananyev * SUCH DAMAGE.
25e18a033bSKonstantin Ananyev */
26e18a033bSKonstantin Ananyev
27e18a033bSKonstantin Ananyev#include <ngx_config.h>
28e18a033bSKonstantin Ananyev#include <ngx_core.h>
29e18a033bSKonstantin Ananyev
30e18a033bSKonstantin Ananyev#include <ngx_tldk.h>
31e18a033bSKonstantin Ananyev
32e18a033bSKonstantin Ananyevunion parse_val {
33e18a033bSKonstantin Ananyev	uint64_t u64;
34e18a033bSKonstantin Ananyev	struct {
35e18a033bSKonstantin Ananyev		uint16_t family;
36e18a033bSKonstantin Ananyev		 union {
37e18a033bSKonstantin Ananyev			struct in_addr addr4;
38e18a033bSKonstantin Ananyev			struct in6_addr addr6;
39e18a033bSKonstantin Ananyev		};
40e18a033bSKonstantin Ananyev	} in;
41e18a033bSKonstantin Ananyev	struct ether_addr mac;
42e18a033bSKonstantin Ananyev	rte_cpuset_t cpuset;
43e18a033bSKonstantin Ananyev};
44e18a033bSKonstantin Ananyev
45e18a033bSKonstantin Ananyevstruct key_handler {
46e18a033bSKonstantin Ananyev	const char *name;
47e18a033bSKonstantin Ananyev	int (*func)(const char *, void *);
48e18a033bSKonstantin Ananyev};
49e18a033bSKonstantin Ananyev
50e18a033bSKonstantin Ananyevstatic int
51e18a033bSKonstantin Ananyevparse_uint_val(const char *val, void *prm)
52e18a033bSKonstantin Ananyev{
53e18a033bSKonstantin Ananyev	union parse_val *rv;
54e18a033bSKonstantin Ananyev	unsigned long v;
55e18a033bSKonstantin Ananyev	char *end;
56e18a033bSKonstantin Ananyev
57e18a033bSKonstantin Ananyev	rv = prm;
58e18a033bSKonstantin Ananyev	errno = 0;
59e18a033bSKonstantin Ananyev	v = strtoul(val, &end, 0);
60e18a033bSKonstantin Ananyev	if (errno != 0 || end[0] != 0 || v > UINT32_MAX)
61e18a033bSKonstantin Ananyev		return -EINVAL;
62e18a033bSKonstantin Ananyev
63e18a033bSKonstantin Ananyev	rv->u64 = v;
64e18a033bSKonstantin Ananyev	return 0;
65e18a033bSKonstantin Ananyev}
66e18a033bSKonstantin Ananyev
67e18a033bSKonstantin Ananyevstatic int
68e18a033bSKonstantin Ananyevparse_ipv4_val(const char *val, void *prm)
69e18a033bSKonstantin Ananyev{
70e18a033bSKonstantin Ananyev	union parse_val *rv;
71e18a033bSKonstantin Ananyev
72e18a033bSKonstantin Ananyev	rv = prm;
73e18a033bSKonstantin Ananyev	if (inet_pton(AF_INET, val, &rv->in.addr4) != 1)
74e18a033bSKonstantin Ananyev		return -EINVAL;
75e18a033bSKonstantin Ananyev	rv->in.family = AF_INET;
76e18a033bSKonstantin Ananyev	return 0;
77e18a033bSKonstantin Ananyev}
78e18a033bSKonstantin Ananyev
79e18a033bSKonstantin Ananyevstatic int
80e18a033bSKonstantin Ananyevparse_ipv6_val(const char *val, void *prm)
81e18a033bSKonstantin Ananyev{
82e18a033bSKonstantin Ananyev	union parse_val *rv;
83e18a033bSKonstantin Ananyev
84e18a033bSKonstantin Ananyev	rv = prm;
85e18a033bSKonstantin Ananyev	if (inet_pton(AF_INET6, val, &rv->in.addr6) != 1)
86e18a033bSKonstantin Ananyev		return -EINVAL;
87e18a033bSKonstantin Ananyev	rv->in.family = AF_INET6;
88e18a033bSKonstantin Ananyev	return 0;
89e18a033bSKonstantin Ananyev}
90e18a033bSKonstantin Ananyev
91e18a033bSKonstantin Ananyevstatic int
92e18a033bSKonstantin Ananyevparse_ip_val(const char *val, void *prm)
93e18a033bSKonstantin Ananyev{
94e18a033bSKonstantin Ananyev	if (parse_ipv6_val(val, prm) != 0 &&
95e18a033bSKonstantin Ananyev			parse_ipv4_val(val, prm) != 0)
96e18a033bSKonstantin Ananyev		return -EINVAL;
97e18a033bSKonstantin Ananyev	return 0;
98e18a033bSKonstantin Ananyev}
99e18a033bSKonstantin Ananyev
100e18a033bSKonstantin Ananyev#define PARSE_UINT8x16(s, v, l)	                          \
101e18a033bSKonstantin Ananyevdo {                                                      \
102e18a033bSKonstantin Ananyev	char *end;                                        \
103e18a033bSKonstantin Ananyev	unsigned long t;                                  \
104e18a033bSKonstantin Ananyev	errno = 0;                                        \
105e18a033bSKonstantin Ananyev	t = strtoul((s), &end, 16);                       \
106e18a033bSKonstantin Ananyev	if (errno != 0 || end[0] != (l) || t > UINT8_MAX) \
107e18a033bSKonstantin Ananyev		return -EINVAL;                           \
108e18a033bSKonstantin Ananyev	(s) = end + 1;                                    \
109e18a033bSKonstantin Ananyev	(v) = t;                                          \
110e18a033bSKonstantin Ananyev} while (0)
111e18a033bSKonstantin Ananyev
112e18a033bSKonstantin Ananyevstatic int
113e18a033bSKonstantin Ananyevparse_mac_val(const char *val, void *prm)
114e18a033bSKonstantin Ananyev{
115e18a033bSKonstantin Ananyev	union parse_val *rv;
116e18a033bSKonstantin Ananyev	const char *s;
117e18a033bSKonstantin Ananyev
118e18a033bSKonstantin Ananyev	rv = prm;
119e18a033bSKonstantin Ananyev	s = val;
120e18a033bSKonstantin Ananyev
121e18a033bSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[0], ':');
122e18a033bSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[1], ':');
123e18a033bSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[2], ':');
124e18a033bSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[3], ':');
125e18a033bSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[4], ':');
126e18a033bSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[5], 0);
127e18a033bSKonstantin Ananyev	return 0;
128e18a033bSKonstantin Ananyev}
129e18a033bSKonstantin Ananyev
130e18a033bSKonstantin Ananyevstatic char *
131e18a033bSKonstantin Ananyevtldk_port_parse(ngx_conf_t *cf, struct tldk_port_conf *prt)
132e18a033bSKonstantin Ananyev{
133e18a033bSKonstantin Ananyev	uint32_t i, j;
134e18a033bSKonstantin Ananyev	ngx_str_t *v;
135e18a033bSKonstantin Ananyev
136e18a033bSKonstantin Ananyev	static const struct key_handler kh[] = {
137e18a033bSKonstantin Ananyev		{
138e18a033bSKonstantin Ananyev			.name = "port",
139e18a033bSKonstantin Ananyev			.func = parse_uint_val,
140e18a033bSKonstantin Ananyev		},
141e18a033bSKonstantin Ananyev		{
142e18a033bSKonstantin Ananyev			.name = "mtu",
143e18a033bSKonstantin Ananyev			.func = parse_uint_val,
144e18a033bSKonstantin Ananyev		},
145e18a033bSKonstantin Ananyev		{
146e18a033bSKonstantin Ananyev			.name = "rx_offload",
147e18a033bSKonstantin Ananyev			.func = parse_uint_val,
148e18a033bSKonstantin Ananyev		},
149e18a033bSKonstantin Ananyev		{
150e18a033bSKonstantin Ananyev			.name = "tx_offload",
151e18a033bSKonstantin Ananyev			.func = parse_uint_val,
152e18a033bSKonstantin Ananyev		},
153e18a033bSKonstantin Ananyev		{
154e18a033bSKonstantin Ananyev			.name = "ipv4",
155e18a033bSKonstantin Ananyev			.func = parse_ipv4_val,
156e18a033bSKonstantin Ananyev		},
157e18a033bSKonstantin Ananyev		{
158e18a033bSKonstantin Ananyev			.name = "ipv6",
159e18a033bSKonstantin Ananyev			.func = parse_ipv6_val,
160e18a033bSKonstantin Ananyev		},
161e18a033bSKonstantin Ananyev	};
162e18a033bSKonstantin Ananyev
163e18a033bSKonstantin Ananyev	union parse_val pvl[RTE_DIM(kh)];
164e18a033bSKonstantin Ananyev
165e18a033bSKonstantin Ananyev	memset(pvl, 0, sizeof(pvl));
166e18a033bSKonstantin Ananyev	pvl[1].u64 = ETHER_MAX_LEN - ETHER_CRC_LEN;
167e18a033bSKonstantin Ananyev
168e18a033bSKonstantin Ananyev	if (cf->args->nelts % 2 != 0)
169e18a033bSKonstantin Ananyev		return NGX_CONF_ERROR;
170e18a033bSKonstantin Ananyev
171e18a033bSKonstantin Ananyev	v = cf->args->elts;
172e18a033bSKonstantin Ananyev	for (i = 0; i != cf->args->nelts; i += 2) {
173e18a033bSKonstantin Ananyev
174e18a033bSKonstantin Ananyev		for (j = 0; j != RTE_DIM(kh); j++) {
175e18a033bSKonstantin Ananyev			if (ngx_strcmp(v[i].data, kh[j].name) == 0) {
176e18a033bSKonstantin Ananyev				 if (kh[j].func((const char *)v[i + 1].data,
177e18a033bSKonstantin Ananyev						pvl + j) < 0)
178e18a033bSKonstantin Ananyev					return NGX_CONF_ERROR;
179e18a033bSKonstantin Ananyev				else
180e18a033bSKonstantin Ananyev					break;
181e18a033bSKonstantin Ananyev			}
182e18a033bSKonstantin Ananyev		}
183e18a033bSKonstantin Ananyev
184e18a033bSKonstantin Ananyev		/* unknow key */
185e18a033bSKonstantin Ananyev		if (j == RTE_DIM(kh))
186e18a033bSKonstantin Ananyev			return NGX_CONF_ERROR;
187e18a033bSKonstantin Ananyev	}
188e18a033bSKonstantin Ananyev
189e18a033bSKonstantin Ananyev	memset(prt, 0, sizeof(*prt));
190e18a033bSKonstantin Ananyev
191e18a033bSKonstantin Ananyev	prt->id = pvl[0].u64;
192e18a033bSKonstantin Ananyev	prt->mtu = pvl[1].u64;
193e18a033bSKonstantin Ananyev	prt->rx_offload = pvl[2].u64;
194e18a033bSKonstantin Ananyev	prt->tx_offload = pvl[3].u64;
195e18a033bSKonstantin Ananyev	prt->ipv4 = pvl[4].in.addr4.s_addr;
196e18a033bSKonstantin Ananyev	prt->ipv6 = pvl[5].in.addr6;
197e18a033bSKonstantin Ananyev
198e18a033bSKonstantin Ananyev	return NGX_CONF_OK;
199e18a033bSKonstantin Ananyev}
200e18a033bSKonstantin Ananyev
201e18a033bSKonstantin Ananyevstatic char *
202e18a033bSKonstantin Ananyevtldk_dev_parse(ngx_conf_t *cf, struct tldk_dev_conf *dev,
203e18a033bSKonstantin Ananyev		tldk_conf_t *tcf)
204e18a033bSKonstantin Ananyev{
205e18a033bSKonstantin Ananyev	uint32_t i, j;
206e18a033bSKonstantin Ananyev	ngx_str_t *v;
207e18a033bSKonstantin Ananyev
208e18a033bSKonstantin Ananyev	static const struct key_handler kh[] = {
209e18a033bSKonstantin Ananyev		{
210e18a033bSKonstantin Ananyev			.name = "dev",
211e18a033bSKonstantin Ananyev			.func = parse_uint_val,
212e18a033bSKonstantin Ananyev		},
213e18a033bSKonstantin Ananyev		{
214e18a033bSKonstantin Ananyev			.name = "port",
215e18a033bSKonstantin Ananyev			.func = parse_uint_val,
216e18a033bSKonstantin Ananyev		},
217e18a033bSKonstantin Ananyev		{
218e18a033bSKonstantin Ananyev			.name = "queue",
219e18a033bSKonstantin Ananyev			.func = parse_uint_val,
220e18a033bSKonstantin Ananyev		},
221e18a033bSKonstantin Ananyev	};
222e18a033bSKonstantin Ananyev
223e18a033bSKonstantin Ananyev	union parse_val pvl[RTE_DIM(kh)];
224e18a033bSKonstantin Ananyev
225e18a033bSKonstantin Ananyev	memset(pvl, 0, sizeof(pvl));
226e18a033bSKonstantin Ananyev
227e18a033bSKonstantin Ananyev	if (cf->args->nelts % 2 != 0)
228e18a033bSKonstantin Ananyev		return NGX_CONF_ERROR;
229e18a033bSKonstantin Ananyev
230e18a033bSKonstantin Ananyev	v = cf->args->elts;
231e18a033bSKonstantin Ananyev	for (i = 0; i != cf->args->nelts; i += 2) {
232e18a033bSKonstantin Ananyev
233e18a033bSKonstantin Ananyev		for (j = 0; j != RTE_DIM(kh); j++) {
234e18a033bSKonstantin Ananyev			if (ngx_strcmp(v[i].data, kh[j].name) == 0) {
235e18a033bSKonstantin Ananyev				 if (kh[j].func((const char *)v[i + 1].data,
236e18a033bSKonstantin Ananyev						pvl + j) < 0)
237e18a033bSKonstantin Ananyev					return NGX_CONF_ERROR;
238e18a033bSKonstantin Ananyev				else
239e18a033bSKonstantin Ananyev					break;
240e18a033bSKonstantin Ananyev			}
241e18a033bSKonstantin Ananyev		}
242e18a033bSKonstantin Ananyev
243e18a033bSKonstantin Ananyev		/* unknow key */
244e18a033bSKonstantin Ananyev		if (j == RTE_DIM(kh))
245e18a033bSKonstantin Ananyev			return NGX_CONF_ERROR;
246e18a033bSKonstantin Ananyev	}
247e18a033bSKonstantin Ananyev
248e18a033bSKonstantin Ananyev	memset(dev, 0, sizeof(*dev));
249e18a033bSKonstantin Ananyev
250e18a033bSKonstantin Ananyev	dev->id = pvl[0].u64;
251e18a033bSKonstantin Ananyev	dev->port = pvl[1].u64;
252e18a033bSKonstantin Ananyev	dev->queue = pvl[2].u64;
253e18a033bSKonstantin Ananyev
254e18a033bSKonstantin Ananyev	return NGX_CONF_OK;
255e18a033bSKonstantin Ananyev}
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyevstatic char *
258e18a033bSKonstantin Ananyevtldk_dest_parse(ngx_conf_t *cf, struct tldk_dest_conf *dst)
259e18a033bSKonstantin Ananyev{
260e18a033bSKonstantin Ananyev	uint32_t i, j;
261e18a033bSKonstantin Ananyev	ngx_str_t *v;
262e18a033bSKonstantin Ananyev
263e18a033bSKonstantin Ananyev	static const struct key_handler kh[] = {
264e18a033bSKonstantin Ananyev		{
265e18a033bSKonstantin Ananyev			.name = "dev",
266e18a033bSKonstantin Ananyev			.func = parse_uint_val,
267e18a033bSKonstantin Ananyev		},
268e18a033bSKonstantin Ananyev		{
269e18a033bSKonstantin Ananyev			.name = "mtu",
270e18a033bSKonstantin Ananyev			.func = parse_uint_val,
271e18a033bSKonstantin Ananyev		},
272e18a033bSKonstantin Ananyev		{
273e18a033bSKonstantin Ananyev			.name = "masklen",
274e18a033bSKonstantin Ananyev			.func = parse_uint_val,
275e18a033bSKonstantin Ananyev		},
276e18a033bSKonstantin Ananyev		{
277e18a033bSKonstantin Ananyev			.name = "addr",
278e18a033bSKonstantin Ananyev			.func = parse_ip_val,
279e18a033bSKonstantin Ananyev		},
280e18a033bSKonstantin Ananyev		{
281e18a033bSKonstantin Ananyev			.name = "mac",
282e18a033bSKonstantin Ananyev			.func = parse_mac_val,
283e18a033bSKonstantin Ananyev		},
284e18a033bSKonstantin Ananyev	};
285e18a033bSKonstantin Ananyev
286e18a033bSKonstantin Ananyev	union parse_val pvl[RTE_DIM(kh)];
287e18a033bSKonstantin Ananyev
288e18a033bSKonstantin Ananyev	memset(pvl, 0, sizeof(pvl));
289e18a033bSKonstantin Ananyev	pvl[1].u64 = ETHER_MAX_LEN - ETHER_CRC_LEN;
290e18a033bSKonstantin Ananyev
291e18a033bSKonstantin Ananyev	if (cf->args->nelts % 2 != 1 || cf->args->nelts == 1)
292e18a033bSKonstantin Ananyev		return NGX_CONF_ERROR;
293e18a033bSKonstantin Ananyev
294e18a033bSKonstantin Ananyev	v = cf->args->elts;
295e18a033bSKonstantin Ananyev	for (i = 1; i != cf->args->nelts; i += 2) {
296e18a033bSKonstantin Ananyev
297e18a033bSKonstantin Ananyev		for (j = 0; j != RTE_DIM(kh); j++) {
298e18a033bSKonstantin Ananyev			if (ngx_strcmp(v[i].data, kh[j].name) == 0) {
299e18a033bSKonstantin Ananyev				 if (kh[j].func((const char *)v[i + 1].data,
300e18a033bSKonstantin Ananyev						pvl + j) < 0)
301e18a033bSKonstantin Ananyev					return NGX_CONF_ERROR;
302e18a033bSKonstantin Ananyev				else
303e18a033bSKonstantin Ananyev					break;
304e18a033bSKonstantin Ananyev			}
305e18a033bSKonstantin Ananyev		}
306e18a033bSKonstantin Ananyev
307e18a033bSKonstantin Ananyev		/* unknow key */
308e18a033bSKonstantin Ananyev		if (j == RTE_DIM(kh))
309e18a033bSKonstantin Ananyev			return NGX_CONF_ERROR;
310e18a033bSKonstantin Ananyev	}
311e18a033bSKonstantin Ananyev
312e18a033bSKonstantin Ananyev	memset(dst, 0, sizeof(*dst));
313e18a033bSKonstantin Ananyev
314e18a033bSKonstantin Ananyev	dst->dev = pvl[0].u64;
315e18a033bSKonstantin Ananyev	dst->mtu = pvl[1].u64;
316e18a033bSKonstantin Ananyev	dst->prfx = pvl[2].u64;
317e18a033bSKonstantin Ananyev
318e18a033bSKonstantin Ananyev	dst->family = pvl[3].in.family;
319e18a033bSKonstantin Ananyev	if (pvl[3].in.family == AF_INET)
320e18a033bSKonstantin Ananyev		dst->ipv4 = pvl[3].in.addr4;
321e18a033bSKonstantin Ananyev	else
322e18a033bSKonstantin Ananyev		dst->ipv6 = pvl[3].in.addr6;
323e18a033bSKonstantin Ananyev
324e18a033bSKonstantin Ananyev	memcpy(&dst->mac, &pvl[4].mac, sizeof(dst->mac));
325e18a033bSKonstantin Ananyev
326e18a033bSKonstantin Ananyev	return NGX_CONF_OK;
327e18a033bSKonstantin Ananyev}
328e18a033bSKonstantin Ananyev
329e18a033bSKonstantin Ananyevchar *
330e18a033bSKonstantin Ananyevtldk_block_parse(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
331e18a033bSKonstantin Ananyev{
332e18a033bSKonstantin Ananyev	uint32_t i, len, n;
333e18a033bSKonstantin Ananyev	tldk_conf_t *tcf;
334e18a033bSKonstantin Ananyev	ngx_str_t *v;
335e18a033bSKonstantin Ananyev	char *rv, *s;
336e18a033bSKonstantin Ananyev	struct tldk_port_conf prt;
337e18a033bSKonstantin Ananyev
338e18a033bSKonstantin Ananyev	tcf = (tldk_conf_t *)((void **)conf)[0];
339e18a033bSKonstantin Ananyev	v = cf->args->elts;
340e18a033bSKonstantin Ananyev
341e18a033bSKonstantin Ananyev	if (ngx_strcmp(v[0].data, "eal_cmd") == 0) {
342e18a033bSKonstantin Ananyev
343e18a033bSKonstantin Ananyev		if (cf->args->nelts == 1 ||
344e18a033bSKonstantin Ananyev				cf->args->nelts > RTE_DIM(tcf->eal_argv))
345e18a033bSKonstantin Ananyev			return NGX_CONF_ERROR;
346e18a033bSKonstantin Ananyev
347e18a033bSKonstantin Ananyev		s = tcf->eal_cmd;
348e18a033bSKonstantin Ananyev		len = sizeof(tcf->eal_cmd);
349e18a033bSKonstantin Ananyev		for (i = 0; i != cf->args->nelts; i++) {
350e18a033bSKonstantin Ananyev			n = snprintf(s, len, "%s", v[i].data) + 1;
351e18a033bSKonstantin Ananyev			if (n > len)
352e18a033bSKonstantin Ananyev				return NGX_CONF_ERROR;
353e18a033bSKonstantin Ananyev			tcf->eal_argv[i] = s;
354e18a033bSKonstantin Ananyev			s += n;
355e18a033bSKonstantin Ananyev			len -= n;
356e18a033bSKonstantin Ananyev		}
357e18a033bSKonstantin Ananyev
358e18a033bSKonstantin Ananyev		tcf->eal_argc = i;
359e18a033bSKonstantin Ananyev		return NGX_CONF_OK;
360e18a033bSKonstantin Ananyev
361e18a033bSKonstantin Ananyev	} else if (ngx_strcmp(v[0].data, "port") == 0) {
362e18a033bSKonstantin Ananyev
363e18a033bSKonstantin Ananyev		rv = tldk_port_parse(cf, &prt);
364e18a033bSKonstantin Ananyev		if (rv == NGX_CONF_OK) {
365e18a033bSKonstantin Ananyev
366e18a033bSKonstantin Ananyev			/* too many ports */
367e18a033bSKonstantin Ananyev			if (tcf->nb_port >= RTE_DIM(tcf->port))
368e18a033bSKonstantin Ananyev				return NGX_CONF_ERROR;
369e18a033bSKonstantin Ananyev
370e18a033bSKonstantin Ananyev			/* copy stuff */
371e18a033bSKonstantin Ananyev			tcf->port[tcf->nb_port++] = prt;
372e18a033bSKonstantin Ananyev		}
373e18a033bSKonstantin Ananyev		return rv;
374e18a033bSKonstantin Ananyev	}
375e18a033bSKonstantin Ananyev
376e18a033bSKonstantin Ananyev	return NGX_CONF_ERROR;
377e18a033bSKonstantin Ananyev}
378e18a033bSKonstantin Ananyev
379e18a033bSKonstantin Ananyevchar *
380e18a033bSKonstantin Ananyevtldk_ctx_parse(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
381e18a033bSKonstantin Ananyev{
382e18a033bSKonstantin Ananyev	char *rv;
383e18a033bSKonstantin Ananyev	ngx_str_t *v;
384e18a033bSKonstantin Ananyev	tldk_conf_t *tcf;
385e18a033bSKonstantin Ananyev	struct tldk_ctx_conf *tcx;
386e18a033bSKonstantin Ananyev	union parse_val pvl;
387e18a033bSKonstantin Ananyev
388e18a033bSKonstantin Ananyev	tcf = (tldk_conf_t *)((void **)conf)[0];
389e18a033bSKonstantin Ananyev	tcx = tcf->ctx + tcf->nb_ctx;
390e18a033bSKonstantin Ananyev	v = cf->args->elts;
391e18a033bSKonstantin Ananyev
392e18a033bSKonstantin Ananyev	if (ngx_strcmp(v[0].data, "worker") == 0) {
393e18a033bSKonstantin Ananyev		if (cf->args->nelts != 2 ||
394e18a033bSKonstantin Ananyev				parse_uint_val((const char *)v[1].data,
395e18a033bSKonstantin Ananyev					&pvl) < 0)
396e18a033bSKonstantin Ananyev			return NGX_CONF_ERROR;
397e18a033bSKonstantin Ananyev		tcx->worker = pvl.u64;
398e18a033bSKonstantin Ananyev	} else if (ngx_strcmp(v[0].data, "lcore") == 0) {
399e18a033bSKonstantin Ananyev		if (cf->args->nelts != 2 ||
400e18a033bSKonstantin Ananyev				parse_uint_val((const char *)v[1].data,
401e18a033bSKonstantin Ananyev					&pvl) < 0)
402e18a033bSKonstantin Ananyev			return NGX_CONF_ERROR;
403e18a033bSKonstantin Ananyev		tcx->lcore = pvl.u64;
404e18a033bSKonstantin Ananyev	} else if (ngx_strcmp(v[0].data, "mbufs") == 0) {
405e18a033bSKonstantin Ananyev		if (cf->args->nelts != 2 ||
406e18a033bSKonstantin Ananyev				parse_uint_val((const char *)v[1].data,
407e18a033bSKonstantin Ananyev					&pvl) < 0)
408e18a033bSKonstantin Ananyev			return NGX_CONF_ERROR;
409e18a033bSKonstantin Ananyev		tcx->nb_mbuf = pvl.u64;
410e18a033bSKonstantin Ananyev	} else if (ngx_strcmp(v[0].data, "streams") == 0) {
411e18a033bSKonstantin Ananyev		if (cf->args->nelts != 2 ||
412e18a033bSKonstantin Ananyev				parse_uint_val((const char *)v[1].data,
413e18a033bSKonstantin Ananyev					&pvl) < 0)
414e18a033bSKonstantin Ananyev			return NGX_CONF_ERROR;
415e18a033bSKonstantin Ananyev		tcx->nb_stream = pvl.u64;
416b8f1ef2bSKonstantin Ananyev	} else if (ngx_strcmp(v[0].data, "min_free_streams") == 0) {
417b8f1ef2bSKonstantin Ananyev		if (cf->args->nelts != 2 ||
418b8f1ef2bSKonstantin Ananyev				parse_uint_val((const char *)v[1].data,
419b8f1ef2bSKonstantin Ananyev					&pvl) < 0)
420b8f1ef2bSKonstantin Ananyev			return NGX_CONF_ERROR;
421b8f1ef2bSKonstantin Ananyev		tcx->free_streams.nb_min = pvl.u64;
422