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 <assert.h>
28e18a033bSKonstantin Ananyev#include <netinet/ip6.h>
29e18a033bSKonstantin Ananyev
305c795f7bSKonstantin Ananyev#include <ngx_config.h>
315c795f7bSKonstantin Ananyev#include <ngx_core.h>
325c795f7bSKonstantin Ananyev
335c795f7bSKonstantin Ananyev#include "be.h"
34e18a033bSKonstantin Ananyev#include <rte_version.h>
35e18a033bSKonstantin Ananyev#include <rte_cycles.h>
36e18a033bSKonstantin Ananyev#include <rte_ethdev.h>
37e18a033bSKonstantin Ananyev#include <rte_errno.h>
38e18a033bSKonstantin Ananyev#include <rte_lpm6.h>
39e18a033bSKonstantin Ananyev#include <rte_lpm.h>
40e18a033bSKonstantin Ananyev#include <rte_ip.h>
41e18a033bSKonstantin Ananyev#include <rte_tcp.h>
42e18a033bSKonstantin Ananyev
43e18a033bSKonstantin Ananyev#include <tle_tcp.h>
44e18a033bSKonstantin Ananyev
455c795f7bSKonstantin Ananyev#if RTE_VERSION_NUM(17, 11, 0, 0) <= RTE_VERSION
465c795f7bSKonstantin Ananyevtypedef uint16_t dpdk_port_t;
475c795f7bSKonstantin Ananyev#else
485c795f7bSKonstantin Ananyevtypedef uint8_t dpdk_port_t;
495c795f7bSKonstantin Ananyev#endif
50e18a033bSKonstantin Ananyev
51e18a033bSKonstantin Ananyev#define RX_RING_SIZE    0x400
52e18a033bSKonstantin Ananyev#define TX_RING_SIZE    0x800
53e18a033bSKonstantin Ananyev#define MAX_RULES       0x100
54e18a033bSKonstantin Ananyev#define MAX_TBL8        0x800
55e18a033bSKonstantin Ananyev
56e18a033bSKonstantin Ananyev#define MPOOL_CACHE_SIZE        0x100
57e18a033bSKonstantin Ananyev#define MPOOL_NB_BUF            0x20000
58e18a033bSKonstantin Ananyev
59e18a033bSKonstantin Ananyev#define FRAG_MBUF_BUF_SIZE      (RTE_PKTMBUF_HEADROOM + TLE_DST_MAX_HDR)
60e18a033bSKonstantin Ananyev
61e18a033bSKonstantin Ananyev#define RX_CSUM_OFFLOAD (DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM)
62e18a033bSKonstantin Ananyev
63e18a033bSKonstantin Ananyev#define TCP_MAX_PROCESS 0x20
64e18a033bSKonstantin Ananyev
65e18a033bSKonstantin Ananyevstatic const struct rte_eth_conf port_conf_default = {
66e18a033bSKonstantin Ananyev	.rxmode = {
67cecfc87fSJianfeng Tan		.offloads = DEV_RX_OFFLOAD_VLAN_STRIP,
68e18a033bSKonstantin Ananyev	},
69e18a033bSKonstantin Ananyev};
70e18a033bSKonstantin Ananyev
71e18a033bSKonstantin Ananyevstruct ptype2cb {
72e18a033bSKonstantin Ananyev	uint32_t mask;
73e18a033bSKonstantin Ananyev	const char *name;
74e18a033bSKonstantin Ananyev	rte_rx_callback_fn fn;
75e18a033bSKonstantin Ananyev};
76e18a033bSKonstantin Ananyev
77e18a033bSKonstantin Ananyevenum {
78e18a033bSKonstantin Ananyev	ETHER_PTYPE = 0x1,
79e18a033bSKonstantin Ananyev	IPV4_PTYPE = 0x2,
80e18a033bSKonstantin Ananyev	IPV4_EXT_PTYPE = 0x4,
81e18a033bSKonstantin Ananyev	IPV6_PTYPE = 0x8,
82e18a033bSKonstantin Ananyev	IPV6_EXT_PTYPE = 0x10,
83e18a033bSKonstantin Ananyev	TCP_PTYPE = 0x20,
84e18a033bSKonstantin Ananyev	UDP_PTYPE = 0x40,
85e18a033bSKonstantin Ananyev};
86e18a033bSKonstantin Ananyev
87e18a033bSKonstantin Ananyevint
88e18a033bSKonstantin Ananyevbe_lcore_lpm_init(struct tldk_ctx *tcx, uint32_t sid,
89e18a033bSKonstantin Ananyev		const struct tldk_ctx_conf *cf)
90e18a033bSKonstantin Ananyev{
91e18a033bSKonstantin Ananyev	ngx_uint_t worker = cf->worker;
92e18a033bSKonstantin Ananyev	uint32_t lcore = cf->lcore;
93e18a033bSKonstantin Ananyev	char str[RTE_LPM_NAMESIZE];
94e18a033bSKonstantin Ananyev
95e18a033bSKonstantin Ananyev	const struct rte_lpm_config lpm4_cfg = {
96e18a033bSKonstantin Ananyev		.max_rules = MAX_RULES,
97e18a033bSKonstantin Ananyev		.number_tbl8s = MAX_TBL8,
98e18a033bSKonstantin Ananyev	};
99e18a033bSKonstantin Ananyev
100e18a033bSKonstantin Ananyev	const struct rte_lpm6_config lpm6_cfg = {
101e18a033bSKonstantin Ananyev		.max_rules = MAX_RULES,
102e18a033bSKonstantin Ananyev		.number_tbl8s = MAX_TBL8,
103e18a033bSKonstantin Ananyev	};
104e18a033bSKonstantin Ananyev
105e18a033bSKonstantin Ananyev	snprintf(str, sizeof(str), "LPM4%lu-%u\n", worker, lcore);
106e18a033bSKonstantin Ananyev	tcx->lpm4 = rte_lpm_create(str, sid, &lpm4_cfg);
107e18a033bSKonstantin Ananyev	RTE_LOG(NOTICE, USER1, "%s(worker=%lu, lcore=%u): lpm4=%p;\n",
108e18a033bSKonstantin Ananyev		__func__, worker, lcore, tcx->lpm4);
109e18a033bSKonstantin Ananyev	if (tcx->lpm4 == NULL)
110e18a033bSKonstantin Ananyev		return -ENOMEM;
111e18a033bSKonstantin Ananyev
112e18a033bSKonstantin Ananyev	snprintf(str, sizeof(str), "LPM6%lu-%u\n", worker, lcore);
113e18a033bSKonstantin Ananyev	tcx->lpm6 = rte_lpm6_create(str, sid, &lpm6_cfg);
114e18a033bSKonstantin Ananyev	RTE_LOG(NOTICE, USER1, "%s(worker=%lu, lcore=%u): lpm6=%p;\n",
115e18a033bSKonstantin Ananyev		__func__, worker, lcore, tcx->lpm6);
116e18a033bSKonstantin Ananyev	if (tcx->lpm6 == NULL) {
117e18a033bSKonstantin Ananyev		rte_lpm_free(tcx->lpm4);
118e18a033bSKonstantin Ananyev		return -ENOMEM;
119e18a033bSKonstantin Ananyev	}
120e18a033bSKonstantin Ananyev
121e18a033bSKonstantin Ananyev	return 0;
122e18a033bSKonstantin Ananyev}
123e18a033bSKonstantin Ananyev
124e18a033bSKonstantin Ananyevint
125e18a033bSKonstantin Ananyevbe_lpm4_dst_lookup(void *data, const struct in_addr *addr,
126e18a033bSKonstantin Ananyev		struct tle_dest *res)
127e18a033bSKonstantin Ananyev{
128e18a033bSKonstantin Ananyev	int32_t rc;
129e18a033bSKonstantin Ananyev	uint32_t idx;
130e18a033bSKonstantin Ananyev	struct tldk_ctx *tcx;
131e18a033bSKonstantin Ananyev	struct tle_dest *dst;
132e18a033bSKonstantin Ananyev
133e18a033bSKonstantin Ananyev	tcx = data;
134e18a033bSKonstantin Ananyev	rc = rte_lpm_lookup(tcx->lpm4, rte_be_to_cpu_32(addr->s_addr), &idx);
135e18a033bSKonstantin Ananyev	if (rc == 0) {
136e18a033bSKonstantin Ananyev		dst = &tcx->dst4[idx];
137e18a033bSKonstantin Ananyev		memcpy(res, dst, dst->l2_len + dst->l3_len +
138e18a033bSKonstantin Ananyev				offsetof(struct tle_dest, hdr));
139e18a033bSKonstantin Ananyev	}
140e18a033bSKonstantin Ananyev
141e18a033bSKonstantin Ananyev	return rc;
142e18a033bSKonstantin Ananyev}
143e18a033bSKonstantin Ananyev
144e18a033bSKonstantin Ananyevint
145e18a033bSKonstantin Ananyevbe_lpm6_dst_lookup(void *data, const struct in6_addr *addr,
146e18a033bSKonstantin Ananyev	struct tle_dest *res)
147e18a033bSKonstantin Ananyev{
148e18a033bSKonstantin Ananyev	int32_t rc;
149e18a033bSKonstantin Ananyev	struct tldk_ctx *tcx;
150e18a033bSKonstantin Ananyev	struct tle_dest *dst;
151e18a033bSKonstantin Ananyev	uintptr_t p;
152e18a033bSKonstantin Ananyev#if RTE_VERSION_NUM(17, 5, 0, 0) <= RTE_VERSION
153e18a033bSKonstantin Ananyev	uint32_t idx;
154e18a033bSKonstantin Ananyev#else
155e18a033bSKonstantin Ananyev	uint8_t idx;
156e18a033bSKonstantin Ananyev#endif
157e18a033bSKonstantin Ananyev
158e18a033bSKonstantin Ananyev	tcx = data;
159e18a033bSKonstantin Ananyev	p = (uintptr_t)addr->s6_addr;
160e18a033bSKonstantin Ananyev	rc = rte_lpm6_lookup(tcx->lpm6, (uint8_t *)p, &idx);
161e18a033bSKonstantin Ananyev	if (rc == 0) {
162e18a033bSKonstantin Ananyev		dst = &tcx->dst6[idx];
163e18a033bSKonstantin Ananyev		memcpy(res, dst, dst->l2_len + dst->l3_len +
164e18a033bSKonstantin Ananyev				offsetof(struct tle_dest, hdr));
165e18a033bSKonstantin Ananyev	}
166e18a033bSKonstantin Ananyev
167e18a033bSKonstantin Ananyev	return rc;
168e18a033bSKonstantin Ananyev}
169e18a033bSKonstantin Ananyev
170e18a033bSKonstantin Ananyev/*
171e18a033bSKonstantin Ananyev * Initialise DPDK port.
172e18a033bSKonstantin Ananyev */
173e18a033bSKonstantin Ananyevstatic int
174e18a033bSKonstantin Ananyevport_init(const struct tldk_port_conf *pcf)
175e18a033bSKonstantin Ananyev{
176e18a033bSKonstantin Ananyev	int32_t rc;
177e18a033bSKonstantin Ananyev	struct rte_eth_conf port_conf;
178e18a033bSKonstantin Ananyev	struct rte_eth_dev_info dev_info;
179e18a033bSKonstantin Ananyev
180e18a033bSKonstantin Ananyev	rte_eth_dev_info_get(pcf->id, &dev_info);
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev	if ((dev_info.rx_offload_capa & pcf->rx_offload) != pcf->rx_offload) {
183e18a033bSKonstantin Ananyev		RTE_LOG(ERR, USER1,
184e18a033bSKonstantin Ananyev			"port#%u supported/requested RX offloads don't match, "
1855c795f7bSKonstantin Ananyev			"supported: %#" PRIx64 ", requested: %#" PRIx64 ";\n",
1865c795f7bSKonstantin Ananyev			pcf->id, (uint64_t)dev_info.rx_offload_capa,
1875c795f7bSKonstantin Ananyev			pcf->rx_offload);
188e18a033bSKonstantin Ananyev		return NGX_ERROR;
189e18a033bSKonstantin Ananyev	}
190e18a033bSKonstantin Ananyev	if ((dev_info.tx_offload_capa & pcf->tx_offload) != pcf->tx_offload) {
191e18a033bSKonstantin Ananyev		RTE_LOG(ERR, USER1,
192e18a033bSKonstantin Ananyev			"port#%u supported/requested TX offloads don't match, "
1935c795f7bSKonstantin Ananyev			"supported: %#" PRIx64 ", requested: %#" PRIx64 ";\n",
1945c795f7bSKonstantin Ananyev			pcf->id, (uint64_t)dev_info.tx_offload_capa,
1955c795f7bSKonstantin Ananyev			pcf->tx_offload);
196e18a033bSKonstantin Ananyev		return NGX_ERROR;
197e18a033bSKonstantin Ananyev	}
198e18a033bSKonstantin Ananyev
199e18a033bSKonstantin Ananyev	port_conf = port_conf_default;
200e18a033bSKonstantin Ananyev
201e18a033bSKonstantin Ananyev	if ((pcf->rx_offload & RX_CSUM_OFFLOAD) != 0) {
202e18a033bSKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s(%u): enabling RX csum offload;\n",
203e18a033bSKonstantin Ananyev			__func__, pcf->id);
204cecfc87fSJianfeng Tan		port_conf.rxmode.offloads |= pcf->rx_offload & RX_CSUM_OFFLOAD;
205e18a033bSKonstantin Ananyev	}
206e18a033bSKonstantin Ananyev
207e18a033bSKonstantin Ananyev	port_conf.rxmode.max_rx_pkt_len = pcf->mtu + ETHER_CRC_LEN;
208e18a033bSKonstantin Ananyev	if (port_conf.rxmode.max_rx_pkt_len > ETHER_MAX_LEN)
209cecfc87fSJianfeng Tan		port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
210e18a033bSKonstantin Ananyev	port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
211e18a033bSKonstantin Ananyev	port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IP | ETH_RSS_TCP;
212cecfc87fSJianfeng Tan	port_conf.rx_adv_conf.rss_conf.rss_hf &=
213cecfc87fSJianfeng Tan		dev_info.flow_type_rss_offloads;
214cecfc87fSJianfeng Tan
215cecfc87fSJianfeng Tan	port_conf.txmode.offloads = pcf->tx_offload;
216e18a033bSKonstantin Ananyev
217e18a033bSKonstantin Ananyev	rc = rte_eth_dev_configure(pcf->id, pcf->nb_queues, pcf->nb_queues,
218e18a033bSKonstantin Ananyev			&port_conf);
219e18a033bSKonstantin Ananyev	RTE_LOG(NOTICE, USER1,
220e18a033bSKonstantin Ananyev		"%s: rte_eth_dev_configure(prt_id=%u, nb_rxq=%u, nb_txq=%u) "
221e18a033bSKonstantin Ananyev		"returns %d;\n", __func__, pcf->id, pcf->nb_queues,
222e18a033bSKonstantin Ananyev		pcf->nb_queues, rc);
223e18a033bSKonstantin Ananyev
224e18a033bSKonstantin Ananyev	if (rc != 0)
225e18a033bSKonstantin Ananyev		return NGX_ERROR;
226e18a033bSKonstantin Ananyev
227e18a033bSKonstantin Ananyev	return NGX_OK;
228e18a033bSKonstantin Ananyev}
229e18a033bSKonstantin Ananyev
230e18a033bSKonstantin Ananyev/*
231e18a033bSKonstantin Ananyev * Check that lcore is enabled, not master, and not in use already.
232e18a033bSKonstantin Ananyev */
233e18a033bSKonstantin Ananyevint
234e18a033bSKonstantin Ananyevbe_check_lcore(uint32_t lid)
235e18a033bSKonstantin Ananyev{
236e18a033bSKonstantin Ananyev	if (rte_lcore_is_enabled(lid) == 0) {
237e18a033bSKonstantin Ananyev		RTE_LOG(ERR, USER1, "lcore %u is not enabled\n", lid);
238e18a033bSKonstantin Ananyev		return -EINVAL;
239e18a033bSKonstantin Ananyev	}
240e18a033bSKonstantin Ananyev
241e18a033bSKonstantin Ananyev	if (rte_get_master_lcore() != lid &&
242e18a033bSKonstantin Ananyev		rte_eal_get_lcore_state(lid) == RUNNING) {
243e18a033bSKonstantin Ananyev		RTE_LOG(ERR, USER1, "lcore %u already running %p\n",
244e18a033bSKonstantin Ananyev			lid, lcore_config[lid].f);
245e18a033bSKonstantin Ananyev		return -EINVAL;
246e18a033bSKonstantin Ananyev	}
247e18a033bSKonstantin Ananyev
248e18a033bSKonstantin Ananyev	return 0;
249e18a033bSKonstantin Ananyev}
250e18a033bSKonstantin Ananyev
251e18a033bSKonstantin Ananyevint
252e18a033bSKonstantin Ananyevbe_mpool_init(struct tldk_ctx *tcx)
253e18a033bSKonstantin Ananyev{
254e18a033bSKonstantin Ananyev	int32_t rc;
255e18a033bSKonstantin Ananyev	uint32_t nmb, sid;
256e18a033bSKonstantin Ananyev	struct rte_mempool *mp;
257e18a033bSKonstantin Ananyev	char name[RTE_MEMPOOL_NAMESIZE];
258e18a033bSKonstantin Ananyev
259e18a033bSKonstantin Ananyev	ngx_uint_t worker = tcx->cf->worker;
260e18a033bSKonstantin Ananyev	uint32_t lcore = tcx->cf->lcore;
261e18a033bSKonstantin Ananyev
262e18a033bSKonstantin Ananyev	sid = rte_lcore_to_socket_id(tcx->cf->lcore);
263e18a033bSKonstantin Ananyev	nmb = (tcx->cf->nb_mbuf == 0) ? MPOOL_NB_BUF : tcx->cf->nb_mbuf;
264e18a033bSKonstantin Ananyev
265e18a033bSKonstantin Ananyev	snprintf(name, sizeof(name), "MP%lu-%u", worker, lcore);
266e18a033bSKonstantin Ananyev	mp = rte_pktmbuf_pool_create(name, nmb, MPOOL_CACHE_SIZE, 0,
267e18a033bSKonstantin Ananyev			RTE_MBUF_DEFAULT_BUF_SIZE, sid);
268e18a033bSKonstantin Ananyev	if (mp == NULL) {
269e18a033bSKonstantin Ananyev		rc = -rte_errno;
270e18a033bSKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s:Mempool creation failed for "
271e18a033bSKonstantin Ananyev			"ctx:wrk(%lu)-ctx:lcore(%u) with error code: %d\n",
272e18a033bSKonstantin Ananyev			__func__, worker, lcore, rc);
273e18a033bSKonstantin Ananyev		return rc;
274e18a033bSKonstantin Ananyev	}
275e18a033bSKonstantin Ananyev
276e18a033bSKonstantin Ananyev	tcx->mpool = mp;
277e18a033bSKonstantin Ananyev
278e18a033bSKonstantin Ananyev	snprintf(name, sizeof(name), "frag_MP%lu-%u",
279e18a033bSKonstantin Ananyev			worker, lcore);
280e18a033bSKonstantin Ananyev	mp = rte_pktmbuf_pool_create(name, nmb,
281e18a033bSKonstantin Ananyev			MPOOL_CACHE_SIZE, 0, FRAG_MBUF_BUF_SIZE, sid - 1);
282e18a033bSKonstantin Ananyev	if (mp == NULL) {
283e18a033bSKonstantin Ananyev		rc = -rte_errno;
284e18a033bSKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s:Frag mempool creation failed for "
285e18a033bSKonstantin Ananyev			"ctx:wrk(%lu)-ctx:lcore(%u) with error code: %d\n",
286e18a033bSKonstantin Ananyev			__func__, worker, lcore, rc);
287e18a033bSKonstantin Ananyev		return rc;
288e18a033bSKonstantin Ananyev	}
289e18a033bSKonstantin Ananyev
290e18a033bSKonstantin Ananyev	tcx->frag_mpool = mp;
291e18a033bSKonstantin Ananyev
292e18a033bSKonstantin Ananyev	return 0;
293e18a033bSKonstantin Ananyev}
294e18a033bSKonstantin Ananyev
295e18a033bSKonstantin Ananyevint
296e18a033bSKonstantin Ananyevbe_queue_init(struct tldk_ctx *tcx, const tldk_conf_t *cf)
297e18a033bSKonstantin Ananyev{
298e18a033bSKonstantin Ananyev	int32_t socket, rc;
299e18a033bSKonstantin Ananyev	uint16_t queue_id;
3005b873e3bSKonstantin Ananyev	uint32_t port_id, i, nb_rxd, nb_txd;
301e18a033bSKonstantin Ananyev	struct rte_eth_dev_info dev_info;
302e18a033bSKonstantin Ananyev	const struct tldk_ctx_conf *ctx;
303e18a033bSKonstantin Ananyev
304e18a033bSKonstantin Ananyev	ctx = tcx->cf;
305e18a033bSKonstantin Ananyev	for (i = 0; i < ctx->nb_dev; i++) {
306e18a033bSKonstantin Ananyev		port_id = ctx->dev[i].port;
307e18a033bSKonstantin Ananyev		queue_id = ctx->dev[i].queue;
308e18a033bSKonstantin Ananyev
309e18a033bSKonstantin Ananyev		rte_eth_dev_info_get(port_id, &dev_info);
3105b873e3bSKonstantin Ananyev
311e18a033bSKonstantin Ananyev		dev_info.default_rxconf.rx_drop_en = 1;
3125b873e3bSKonstantin Ananyev
3135b873e3bSKonstantin Ananyev		nb_rxd = RTE_MIN(RX_RING_SIZE, dev_info.rx_desc_lim.nb_max);
3145b873e3bSKonstantin Ananyev		nb_txd = RTE_MIN(TX_RING_SIZE, dev_info.tx_desc_lim.nb_max);
3155b873e3bSKonstantin Ananyev		dev_info.default_txconf.tx_free_thresh = nb_txd / 2;
316e18a033bSKonstantin Ananyev
317e18a033bSKonstantin Ananyev		socket = rte_eth_dev_socket_id(port_id);
318e18a033bSKonstantin Ananyev
3195b873e3bSKonstantin Ananyev		rc = rte_eth_rx_queue_setup(port_id, queue_id, nb_rxd,
320e18a033bSKonstantin Ananyev				socket, &dev_info.default_rxconf, tcx->mpool);
321e18a033bSKonstantin Ananyev		if (rc < 0) {
322e18a033bSKonstantin Ananyev			RTE_LOG(ERR, USER1,
323e18a033bSKonstantin Ananyev				"%s: rx queue=%u setup failed with error "
324e18a033bSKonstantin Ananyev				"code: %d\n", __func__, queue_id, rc);
325e18a033bSKonstantin Ananyev			return rc;
326e18a033bSKonstantin Ananyev		}
327e18a033bSKonstantin Ananyev
3285b873e3bSKonstantin Ananyev		rc = rte_eth_tx_queue_setup(port_id, queue_id, nb_txd,
329e18a033bSKonstantin Ananyev				socket, &dev_info.default_txconf);
330e18a033bSKonstantin Ananyev		if (rc < 0) {
331e18a033bSKonstantin Ananyev			RTE_LOG(ERR, USER1,
332e18a033bSKonstantin Ananyev				"%s: tx queue=%u setup failed with error "
333e18a033bSKonstantin Ananyev				"code: %d\n", __func__, queue_id, rc);
334e18a033bSKonstantin Ananyev			return rc;
335e18a033bSKonstantin Ananyev		}
336e18a033bSKonstantin Ananyev	}
337e18a033bSKonstantin Ananyev
338e18a033bSKonstantin Ananyev	return 0;
339e18a033bSKonstantin Ananyev}
340e18a033bSKonstantin Ananyev
341e18a033bSKonstantin Ananyev/*
342e18a033bSKonstantin Ananyev * Setup all enabled ports.
343e18a033bSKonstantin Ananyev */
344e18a033bSKonstantin Ananyevint
345e18a033bSKonstantin Ananyevbe_port_init(tldk_conf_t *cf)
346e18a033bSKonstantin Ananyev{
347e18a033bSKonstantin Ananyev	int32_t rc;
348e18a033bSKonstantin Ananyev	uint32_t i;
349e18a033bSKonstantin Ananyev	struct tldk_port_conf *dpf;
350e18a033bSKonstantin Ananyev
351e18a033bSKonstantin Ananyev	for (i = 0; i != cf->nb_port; i++) {
352e18a033bSKonstantin Ananyev		dpf = &cf->port[i];
353e18a033bSKonstantin Ananyev		rc = port_init(dpf);
354e18a033bSKonstantin Ananyev		if (rc != 0) {
355e18a033bSKonstantin Ananyev			RTE_LOG(ERR, USER1,
356e18a033bSKonstantin Ananyev				"%s: port=%u init failed with error code: %d\n",
357e18a033bSKonstantin Ananyev				__func__, dpf->id, rc);
358e18a033bSKonstantin Ananyev			return NGX_ERROR;
359e18a033bSKonstantin Ananyev		}
360e18a033bSKonstantin Ananyev		rte_eth_macaddr_get(dpf->id, &dpf->mac);
361e18a033bSKonstantin Ananyev		rte_eth_promiscuous_enable(dpf->id);
362e18a033bSKonstantin Ananyev	}
363e18a033bSKonstantin Ananyev
364e18a033bSKonstantin Ananyev	return NGX_OK;
365e18a033bSKonstantin Ananyev}
366e18a033bSKonstantin Ananyev
367e18a033bSKonstantin Ananyevstatic int
368e18a033bSKonstantin Ananyevbe_add_ipv4_route(struct tldk_ctx *tcx, const struct tldk_dest_conf *dcf,
369e18a033bSKonstantin Ananyev	uint8_t idx)
370e18a033bSKonstantin Ananyev{
371e18a033bSKonstantin Ananyev	int32_t rc;
372e18a033bSKonstantin Ananyev	uint32_t addr, depth;
373e18a033bSKonstantin Ananyev	char str[INET_ADDRSTRLEN];
374e18a033bSKonstantin Ananyev
375e18a033bSKonstantin Ananyev	depth = dcf->prfx;
376e18a033bSKonstantin Ananyev	addr = rte_be_to_cpu_32(dcf->ipv4.s_addr);
377e18a033bSKonstantin Ananyev
378e18a033bSKonstantin Ananyev	inet_ntop(AF_INET, &dcf->ipv4, str, sizeof(str));
379e18a033bSKonstantin Ananyev	rc = rte_lpm_add(tcx->lpm4, addr, depth, idx);
380e18a033bSKonstantin Ananyev	RTE_LOG(NOTICE, USER1, "%s(lcore=%u,dev_id=%u,dev=%p,"
381e18a033bSKonstantin Ananyev			"ipv4=%s/%u,mtu=%u,"
382e18a033bSKonstantin Ananyev			"mac=%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx) "
383e18a033bSKonstantin Ananyev			"returns %d;\n",
384e18a033bSKonstantin Ananyev			__func__, tcx->cf->lcore, dcf->dev, tcx->dst4[idx].dev,
385e18a033bSKonstantin Ananyev			str, depth, tcx->dst4[idx].mtu,
386e18a033bSKonstantin Ananyev			dcf->mac.addr_bytes[0], dcf->mac.addr_bytes[1],
387e18a033bSKonstantin Ananyev			dcf->mac.addr_bytes[2], dcf->mac.addr_bytes[3],
388e18a033bSKonstantin Ananyev			dcf->mac.addr_bytes[4], dcf->mac.addr_bytes[5],
389e18a033bSKonstantin Ananyev			rc);
390e18a033bSKonstantin Ananyev
391e18a033bSKonstantin Ananyev	return rc;
392e18a033bSKonstantin Ananyev}
393e18a033bSKonstantin Ananyev
394e18a033bSKonstantin Ananyevstatic int
395e18a033bSKonstantin Ananyevbe_add_ipv6_route(struct tldk_ctx *tcx, const struct tldk_dest_conf *dcf,
396e18a033bSKonstantin Ananyev	uint8_t idx)
397e18a033bSKonstantin Ananyev{
398e18a033bSKonstantin Ananyev	int32_t rc;
399e18a033bSKonstantin Ananyev	uint32_t depth;
400e18a033bSKonstantin Ananyev	char str[INET6_ADDRSTRLEN];
401e18a033bSKonstantin Ananyev
402e18a033bSKonstantin Ananyev	depth = dcf->prfx;
403e18a033bSKonstantin Ananyev
404e18a033bSKonstantin Ananyev	rc = rte_lpm6_add(tcx->lpm6, (uint8_t *)(uintptr_t)dcf->ipv6.s6_addr,
405e18a033bSKonstantin Ananyev			depth, idx);
406e18a033bSKonstantin Ananyev
407e18a033bSKonstantin Ananyev	inet_ntop(AF_INET6, &dcf->ipv6, str, sizeof(str));
408e18a033bSKonstantin Ananyev	RTE_LOG(NOTICE, USER1, "%s(lcore=%u,dev_id=%u,dev=%p,"
409e18a033bSKonstantin Ananyev		"ipv6=%s/%u,mtu=%u,"
410e18a033bSKonstantin Ananyev		"mac=%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx) "
411e18a033bSKonstantin Ananyev		"returns %d;\n",
412e18a033bSKonstantin Ananyev		__func__, tcx->cf->lcore, dcf->dev, tcx->dst6[idx].dev,
413e18a033bSKonstantin Ananyev		str, depth, tcx->dst4[idx].mtu,
414e18a033bSKonstantin Ananyev		dcf->mac.addr_bytes[0], dcf->mac.addr_bytes[1],
415e18a033bSKonstantin Ananyev		dcf->mac.addr_bytes[2], dcf->mac.addr_bytes[3],
416e18a033bSKonstantin Ananyev		dcf->mac.addr_bytes[4], dcf->mac.addr_bytes[5],
417e18a033bSKonstantin Ananyev		rc);
418e18a033bSKonstantin Ananyev
419e18a033bSKonstantin Ananyev	return rc;
420e18a033bSKonstantin Ananyev}
421e18a033bSKonstantin Ananyev
422e18a033bSKonstantin Ananyevstatic void
423e18a033bSKonstantin Ananyevfill_dst(struct tle_dest *dst, const struct tldk_dev *td,
424e18a033bSKonstantin Ananyev	const struct tldk_port_conf *pcf, const struct tldk_dest_conf *dest,
425e18a033bSKonstantin Ananyev	uint16_t l3_type, struct rte_mempool *mp)
426e18a033bSKonstantin Ananyev{
427e18a033bSKonstantin Ananyev	struct ether_hdr *eth;
428e18a033bSKonstantin Ananyev	struct ipv4_hdr *ip4h;
429e18a033bSKonstantin Ananyev	struct ipv6_hdr *ip6h;
430e18a033bSKonstantin Ananyev
431e18a033bSKonstantin Ananyev	dst->dev = td->dev;
432