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#ifndef TCP_H_
17aa97dd1cSKonstantin Ananyev#define TCP_H_
18aa97dd1cSKonstantin Ananyev
19aa97dd1cSKonstantin Ananyev#define	TCP_MAX_PROCESS	0x20
20aa97dd1cSKonstantin Ananyev
21aa97dd1cSKonstantin Ananyevstatic inline void
22aa97dd1cSKonstantin Ananyevnetfe_stream_term_tcp(struct netfe_lcore *fe, struct netfe_stream *fes)
23aa97dd1cSKonstantin Ananyev{
24aa97dd1cSKonstantin Ananyev	fes->s = NULL;
25aa97dd1cSKonstantin Ananyev	fes->fwds = NULL;
2621e7392fSKonstantin Ananyev	fes->posterr = 0;
27aa97dd1cSKonstantin Ananyev	memset(&fes->stat, 0, sizeof(fes->stat));
2821e7392fSKonstantin Ananyev	pkt_buf_empty(&fes->pbuf);
29aa97dd1cSKonstantin Ananyev	netfe_put_stream(fe, &fe->free, fes);
30aa97dd1cSKonstantin Ananyev}
31aa97dd1cSKonstantin Ananyev
32aa97dd1cSKonstantin Ananyevstatic inline void
33aa97dd1cSKonstantin Ananyevnetfe_stream_close_tcp(struct netfe_lcore *fe, struct netfe_stream *fes)
34aa97dd1cSKonstantin Ananyev{
35aa97dd1cSKonstantin Ananyev	tle_tcp_stream_close(fes->s);
36aa97dd1cSKonstantin Ananyev	netfe_stream_term_tcp(fe, fes);
37aa97dd1cSKonstantin Ananyev}
38aa97dd1cSKonstantin Ananyev
39aa97dd1cSKonstantin Ananyev/*
40aa97dd1cSKonstantin Ananyev * helper function: opens IPv4 and IPv6 streams for selected port.
41aa97dd1cSKonstantin Ananyev */
42aa97dd1cSKonstantin Ananyevstatic struct netfe_stream *
43aa97dd1cSKonstantin Ananyevnetfe_stream_open_tcp(struct netfe_lcore *fe, struct netfe_sprm *sprm,
44aa97dd1cSKonstantin Ananyev	uint32_t lcore, uint16_t op, uint32_t bidx, uint8_t server_mode)
45aa97dd1cSKonstantin Ananyev{
46aa97dd1cSKonstantin Ananyev	int32_t rc;
47aa97dd1cSKonstantin Ananyev	struct netfe_stream *fes;
48aa97dd1cSKonstantin Ananyev	struct sockaddr_in *l4;
49aa97dd1cSKonstantin Ananyev	struct sockaddr_in6 *l6;
50aa97dd1cSKonstantin Ananyev	uint16_t errport;
51aa97dd1cSKonstantin Ananyev	struct tle_tcp_stream_param tprm;
52aa97dd1cSKonstantin Ananyev
53aa97dd1cSKonstantin Ananyev	fes = netfe_get_stream(&fe->free);
54aa97dd1cSKonstantin Ananyev	if (fes == NULL) {
55aa97dd1cSKonstantin Ananyev		rte_errno = ENOBUFS;
56aa97dd1cSKonstantin Ananyev		return NULL;
57aa97dd1cSKonstantin Ananyev	}
58aa97dd1cSKonstantin Ananyev
59aa97dd1cSKonstantin Ananyev	if (server_mode != 0) {
60aa97dd1cSKonstantin Ananyev		tle_event_free(fes->rxev);
61aa97dd1cSKonstantin Ananyev		fes->rxev = tle_event_alloc(fe->syneq, fes);
62aa97dd1cSKonstantin Ananyev	}
63aa97dd1cSKonstantin Ananyev
64aa97dd1cSKonstantin Ananyev	if (fes->rxev == NULL) {
65aa97dd1cSKonstantin Ananyev		netfe_stream_close_tcp(fe, fes);
66aa97dd1cSKonstantin Ananyev		rte_errno = ENOMEM;
67aa97dd1cSKonstantin Ananyev		return NULL;
68aa97dd1cSKonstantin Ananyev	}
69aa97dd1cSKonstantin Ananyev
70aa97dd1cSKonstantin Ananyev	/* activate rx, tx and err events for the stream */
71aa97dd1cSKonstantin Ananyev	if (op == TXONLY || op == FWD) {
72aa97dd1cSKonstantin Ananyev		tle_event_active(fes->txev, TLE_SEV_DOWN);
73aa97dd1cSKonstantin Ananyev		fes->stat.txev[TLE_SEV_DOWN]++;
74aa97dd1cSKonstantin Ananyev	}
75aa97dd1cSKonstantin Ananyev
76aa97dd1cSKonstantin Ananyev	if (op != TXONLY || server_mode != 0) {
77aa97dd1cSKonstantin Ananyev		tle_event_active(fes->rxev, TLE_SEV_DOWN);
78aa97dd1cSKonstantin Ananyev		fes->stat.rxev[TLE_SEV_DOWN]++;
79aa97dd1cSKonstantin Ananyev	}
80aa97dd1cSKonstantin Ananyev	tle_event_active(fes->erev, TLE_SEV_DOWN);
81aa97dd1cSKonstantin Ananyev	fes->stat.erev[TLE_SEV_DOWN]++;
82aa97dd1cSKonstantin Ananyev
83aa97dd1cSKonstantin Ananyev	memset(&tprm, 0, sizeof(tprm));
84aa97dd1cSKonstantin Ananyev	tprm.addr.local = sprm->local_addr;
85aa97dd1cSKonstantin Ananyev	tprm.addr.remote = sprm->remote_addr;
86aa97dd1cSKonstantin Ananyev	tprm.cfg.err_ev = fes->erev;
87aa97dd1cSKonstantin Ananyev	tprm.cfg.recv_ev = fes->rxev;
88aa97dd1cSKonstantin Ananyev	if (op != FWD)
89aa97dd1cSKonstantin Ananyev		tprm.cfg.send_ev = fes->txev;
90aa97dd1cSKonstantin Ananyev
91aa97dd1cSKonstantin Ananyev	fes->s = tle_tcp_stream_open(becfg.cpu[bidx].ctx, &tprm);
92aa97dd1cSKonstantin Ananyev
93aa97dd1cSKonstantin Ananyev	if (fes->s == NULL) {
94aa97dd1cSKonstantin Ananyev		rc = rte_errno;
95aa97dd1cSKonstantin Ananyev		netfe_stream_close_tcp(fe, fes);
96aa97dd1cSKonstantin Ananyev		rte_errno = rc;
97aa97dd1cSKonstantin Ananyev
98aa97dd1cSKonstantin Ananyev		if (sprm->local_addr.ss_family == AF_INET) {
99aa97dd1cSKonstantin Ananyev			l4 = (struct sockaddr_in *) &sprm->local_addr;
100aa97dd1cSKonstantin Ananyev			errport = ntohs(l4->sin_port);
101aa97dd1cSKonstantin Ananyev		} else {
102aa97dd1cSKonstantin Ananyev			l6 = (struct sockaddr_in6 *) &sprm->local_addr;
103aa97dd1cSKonstantin Ananyev			errport = ntohs(l6->sin6_port);
104aa97dd1cSKonstantin Ananyev		}
105aa97dd1cSKonstantin Ananyev
106aa97dd1cSKonstantin Ananyev		RTE_LOG(ERR, USER1, "stream open failed for port %u with error "
107aa97dd1cSKonstantin Ananyev			"code=%u, bidx=%u, lc=%u\n",
108aa97dd1cSKonstantin Ananyev			errport, rc, bidx, becfg.cpu[bidx].id);
109aa97dd1cSKonstantin Ananyev		return NULL;
110aa97dd1cSKonstantin Ananyev	}
111aa97dd1cSKonstantin Ananyev
112aa97dd1cSKonstantin Ananyev	RTE_LOG(NOTICE, USER1,
113aa97dd1cSKonstantin Ananyev		"%s(%u)={s=%p, op=%hu, proto=%s, rxev=%p, txev=%p}, belc=%u\n",
114aa97dd1cSKonstantin Ananyev		__func__, lcore, fes->s, op, proto_name[becfg.proto],
115aa97dd1cSKonstantin Ananyev		fes->rxev, fes->txev, becfg.cpu[bidx].id);
116aa97dd1cSKonstantin Ananyev
117aa97dd1cSKonstantin Ananyev	fes->op = op;
118aa97dd1cSKonstantin Ananyev	fes->proto = becfg.proto;
119aa97dd1cSKonstantin Ananyev	fes->family = sprm->local_addr.ss_family;
120aa97dd1cSKonstantin Ananyev	fes->laddr = sprm->local_addr;
121aa97dd1cSKonstantin Ananyev	netfe_put_stream(fe, &fe->use, fes);
122aa97dd1cSKonstantin Ananyev
123aa97dd1cSKonstantin Ananyev	return fes;
124aa97dd1cSKonstantin Ananyev}
125aa97dd1cSKonstantin Ananyev
126aa97dd1cSKonstantin Ananyevstatic int
127aa97dd1cSKonstantin Ananyevnetfe_lcore_init_tcp(const struct netfe_lcore_prm *prm)
128aa97dd1cSKonstantin Ananyev{
129aa97dd1cSKonstantin Ananyev	size_t sz;
130aa97dd1cSKonstantin Ananyev	int32_t rc;
131aa97dd1cSKonstantin Ananyev	uint32_t i, lcore, snum;
132aa97dd1cSKonstantin Ananyev	struct netfe_lcore *fe;
133aa97dd1cSKonstantin Ananyev	struct tle_evq_param eprm;
134aa97dd1cSKonstantin Ananyev	struct netfe_stream *fes;
135aa97dd1cSKonstantin Ananyev	struct netfe_sprm *sprm;
136aa97dd1cSKonstantin Ananyev
137aa97dd1cSKonstantin Ananyev	lcore = rte_lcore_id();
138aa97dd1cSKonstantin Ananyev
139aa97dd1cSKonstantin Ananyev	snum = prm->max_streams;
140aa97dd1cSKonstantin Ananyev	RTE_LOG(NOTICE, USER1, "%s(lcore=%u, nb_streams=%u, max_streams=%u)\n",
141aa97dd1cSKonstantin Ananyev		__func__, lcore, prm->nb_streams, snum);
142aa97dd1cSKonstantin Ananyev
143aa97dd1cSKonstantin Ananyev	memset(&eprm, 0, sizeof(eprm));
144aa97dd1cSKonstantin Ananyev	eprm.socket_id = rte_lcore_to_socket_id(lcore);
145aa97dd1cSKonstantin Ananyev	eprm.max_events = snum;
146aa97dd1cSKonstantin Ananyev
147aa97dd1cSKonstantin Ananyev	sz = sizeof(*fe) + snum * sizeof(struct netfe_stream);
148aa97dd1cSKonstantin Ananyev	fe = rte_zmalloc_socket(NULL, sz, RTE_CACHE_LINE_SIZE,
149aa97dd1cSKonstantin Ananyev		rte_lcore_to_socket_id(lcore));
150aa97dd1cSKonstantin Ananyev
151aa97dd1cSKonstantin Ananyev	if (fe == NULL) {
152aa97dd1cSKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s:%d failed to allocate %zu bytes\n",
153aa97dd1cSKonstantin Ananyev			__func__, __LINE__, sz);
154aa97dd1cSKonstantin Ananyev		return -ENOMEM;
155aa97dd1cSKonstantin Ananyev	}
156aa97dd1cSKonstantin Ananyev
157aa97dd1cSKonstantin Ananyev	RTE_PER_LCORE(_fe) = fe;
158aa97dd1cSKonstantin Ananyev
159aa97dd1cSKonstantin Ananyev	fe->snum = snum;
160aa97dd1cSKonstantin Ananyev	/* initialize the stream pool */
161aa97dd1cSKonstantin Ananyev	LIST_INIT(&fe->free.head);
162aa97dd1cSKonstantin Ananyev	LIST_INIT(&fe->use.head);
163aa97dd1cSKonstantin Ananyev
164aa97dd1cSKonstantin Ananyev	/* allocate the event queues */
165aa97dd1cSKonstantin Ananyev	fe->syneq = tle_evq_create(&eprm);
166aa97dd1cSKonstantin Ananyev	fe->ereq = tle_evq_create(&eprm);
167aa97dd1cSKonstantin Ananyev	fe->rxeq = tle_evq_create(&eprm);
168aa97dd1cSKonstantin Ananyev	fe->txeq = tle_evq_create(&eprm);
169aa97dd1cSKonstantin Ananyev
170aa97dd1cSKonstantin Ananyev	RTE_LOG(INFO, USER1, "%s(%u) synevq=%p, erevq=%p, rxevq=%p, txevq=%p\n",
171aa97dd1cSKonstantin Ananyev		__func__, lcore, fe->syneq, fe->ereq, fe->rxeq, fe->txeq);
172aa97dd1cSKonstantin Ananyev	if (fe->syneq == NULL || fe->ereq == NULL || fe->rxeq == NULL ||
173aa97dd1cSKonstantin Ananyev		fe->txeq == NULL)
174aa97dd1cSKonstantin Ananyev		return -ENOMEM;
175aa97dd1cSKonstantin Ananyev
176aa97dd1cSKonstantin Ananyev	fes = (struct netfe_stream *)(fe + 1);
177aa97dd1cSKonstantin Ananyev	for (i = 0; i != snum; i++) {
178aa97dd1cSKonstantin Ananyev		fes[i].rxev = tle_event_alloc(fe->rxeq, fes + i);
179aa97dd1cSKonstantin Ananyev		fes[i].txev = tle_event_alloc(fe->txeq, fes + i);
180aa97dd1cSKonstantin Ananyev		fes[i].erev = tle_event_alloc(fe->ereq, fes + i);
181aa97dd1cSKonstantin Ananyev		netfe_put_stream(fe, &fe->free, fes + i);
182aa97dd1cSKonstantin Ananyev	}
183aa97dd1cSKonstantin Ananyev
184aa97dd1cSKonstantin Ananyev
185aa97dd1cSKonstantin Ananyev	/* open all requested streams. */
186aa97dd1cSKonstantin Ananyev	for (i = 0; i != prm->nb_streams; i++) {
187aa97dd1cSKonstantin Ananyev		sprm = &prm->stream[i].sprm;
188aa97dd1cSKonstantin Ananyev		fes = netfe_stream_open_tcp(fe, sprm, lcore, prm->stream[i].op,
189aa97dd1cSKonstantin Ananyev			sprm->bidx, becfg.server);
190aa97dd1cSKonstantin Ananyev		if (fes == NULL) {
191aa97dd1cSKonstantin Ananyev			rc = -rte_errno;
192aa97dd1cSKonstantin Ananyev			break;
193aa97dd1cSKonstantin Ananyev		}
194aa97dd1cSKonstantin Ananyev
195aa97dd1cSKonstantin Ananyev		netfe_stream_dump(fes, &sprm->local_addr, &sprm->remote_addr);
196aa97dd1cSKonstantin Ananyev
197aa97dd1cSKonstantin Ananyev		if (prm->stream[i].op == FWD) {
198aa97dd1cSKonstantin Ananyev			fes->fwdprm = prm->stream[i].fprm;
199aa97dd1cSKonstantin Ananyev		} else if (prm->stream[i].op == TXONLY) {
200aa97dd1cSKonstantin Ananyev			fes->txlen = prm->stream[i].txlen;
201aa97dd1cSKonstantin Ananyev			fes->raddr = prm->stream[i].sprm.remote_addr;
202e151ee29SRemy Horton		} else if (prm->stream[i].op == RXTX) {
203e151ee29SRemy Horton			fes->txlen = prm->stream[i].txlen;
204e151ee29SRemy Horton			fes->rxlen = prm->stream[i].rxlen;
205aa97dd1cSKonstantin Ananyev		}
206aa97dd1cSKonstantin Ananyev
207aa97dd1cSKonstantin Ananyev		if (becfg.server == 1) {
208aa97dd1cSKonstantin Ananyev			rc = tle_tcp_stream_listen(fes->s);
209aa97dd1cSKonstantin Ananyev			RTE_LOG(INFO, USER1,
210aa97dd1cSKonstantin Ananyev				"%s(%u) tle_tcp_stream_listen(stream=%p) "
211aa97dd1cSKonstantin Ananyev				"returns %d\n",
212aa97dd1cSKonstantin Ananyev				__func__, lcore, fes->s, rc);
213aa97dd1cSKonstantin Ananyev			if (rc != 0)
214aa97dd1cSKonstantin Ananyev				break;
215aa97dd1cSKonstantin Ananyev		} else {
216aa97dd1cSKonstantin Ananyev			rc = tle_tcp_stream_connect(fes->s,
217aa97dd1cSKonstantin Ananyev				(const struct sockaddr *)&sprm->remote_addr);
218aa97dd1cSKonstantin Ananyev			RTE_LOG(INFO, USER1,
219aa97dd1cSKonstantin Ananyev				"%s(%u) tle_tcp_stream_connect(stream=%p) "
220aa97dd1cSKonstantin Ananyev				"returns %d\n",
221aa97dd1cSKonstantin Ananyev				__func__, lcore, fes->s, rc);
222aa97dd1cSKonstantin Ananyev			if (rc != 0)
223aa97dd1cSKonstantin Ananyev				break;
224aa97dd1cSKonstantin Ananyev		}
225aa97dd1cSKonstantin Ananyev	}
226aa97dd1cSKonstantin Ananyev
227aa97dd1cSKonstantin Ananyev	return rc;
228aa97dd1cSKonstantin Ananyev}
229aa97dd1cSKonstantin Ananyev
230aa97dd1cSKonstantin Ananyevstatic inline struct netfe_stream *
231aa97dd1cSKonstantin Ananyevnetfe_create_fwd_stream(struct netfe_lcore *fe, struct netfe_stream *fes,
232aa97dd1cSKonstantin Ananyev	uint32_t lcore, uint32_t bidx)
233aa97dd1cSKonstantin Ananyev{
234aa97dd1cSKonstantin Ananyev	uint32_t rc;
235aa97dd1cSKonstantin Ananyev	struct netfe_stream *fws;
236aa97dd1cSKonstantin Ananyev
237aa97dd1cSKonstantin Ananyev	fws = netfe_stream_open_tcp(fe, &fes->fwdprm, lcore, FWD, bidx, 0);
238aa97dd1cSKonstantin Ananyev	if (fws != NULL) {
239aa97dd1cSKonstantin Ananyev		rc = tle_tcp_stream_connect(fws->s,
240aa97dd1cSKonstantin Ananyev			(const struct sockaddr *)&fes->fwdprm.remote_addr);
241aa97dd1cSKonstantin Ananyev		NETFE_TRACE("%s(lc=%u, fes=%p): tle_tcp_stream_connect() "
242aa97dd1cSKonstantin Ananyev			"returns %d;\n",
243aa97dd1cSKonstantin Ananyev			__func__, rte_lcore_id(), fes, rc);
244aa97dd1cSKonstantin Ananyev
245aa97dd1cSKonstantin Ananyev		if (rc != 0) {
246aa97dd1cSKonstantin Ananyev			netfe_stream_term_tcp(fe, fws);
247aa97dd1cSKonstantin Ananyev			fws = NULL;
248aa97dd1cSKonstantin Ananyev		}
249aa97dd1cSKonstantin Ananyev	}
250aa97dd1cSKonstantin Ananyev
251aa97dd1cSKonstantin Ananyev	if (fws == NULL)
252aa97dd1cSKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s(lc=%u fes=%p) failed to open "
253aa97dd1cSKonstantin Ananyev			"forwarding stream;\n",
254aa97dd1cSKonstantin Ananyev			__func__, rte_lcore_id(), fes);
255aa97dd1cSKonstantin Ananyev
256aa97dd1cSKonstantin Ananyev	return fws;
257aa97dd1cSKonstantin Ananyev}
258aa97dd1cSKonstantin Ananyev
25921e7392fSKonstantin Ananyevstatic inline int
260aa97dd1cSKonstantin Ananyevnetfe_fwd_tcp(uint32_t lcore, struct netfe_stream *fes)
261aa97dd1cSKonstantin Ananyev{
262aa97dd1cSKonstantin Ananyev	uint32_t i, k, n;
263aa97dd1cSKonstantin Ananyev	struct rte_mbuf **pkt;
264aa97dd1cSKonstantin Ananyev	struct netfe_stream *fed;
265aa97dd1cSKonstantin Ananyev
266aa97dd1cSKonstantin Ananyev	RTE_SET_USED(lcore);
267aa97dd1cSKonstantin Ananyev
268aa97dd1cSKonstantin Ananyev	n = fes->pbuf.num;
269aa97dd1cSKonstantin Ananyev	pkt = fes->pbuf.pkt;
270aa97dd1cSKonstantin Ananyev
271aa97dd1cSKonstantin Ananyev	if (n == 0)
27221e7392fSKonstantin Ananyev		return 0;
273aa97dd1cSKonstantin Ananyev
274aa97dd1cSKonstantin Ananyev	fed = fes->fwds;
275aa97dd1cSKonstantin Ananyev
276aa97dd1cSKonstantin Ananyev	if (fed != NULL) {
277aa97dd1cSKonstantin Ananyev
278aa97dd1cSKonstantin Ananyev		k = tle_tcp_stream_send(fed->s, pkt, n);
279aa97dd1cSKonstantin Ananyev
280aa97dd1cSKonstantin Ananyev		NETFE_TRACE("%s(%u): tle_%s_stream_send(%p, %u) "
281aa97dd1cSKonstantin Ananyev				"returns %u\n",
282aa97dd1cSKonstantin Ananyev				__func__, lcore, proto_name[fes->proto],
283aa97dd1cSKonstantin Ananyev				fed->s, n, k);
284aa97dd1cSKonstantin Ananyev
285c4c44906SMohammad Abdul Awal		fed->stat.txp += k;
286c4c44906SMohammad Abdul Awal		fed->stat.drops += n - k;
287c4c44906SMohammad Abdul Awal		fes->stat.fwp += k;
288aa97dd1cSKonstantin Ananyev
289aa97dd1cSKonstantin Ananyev	} else {
290aa97dd1cSKonstantin Ananyev		NETFE_TRACE("%s(%u, %p): no fwd stream for %u pkts;\n",
291aa97dd1cSKonstantin Ananyev			__func__, lcore, fes->s, n);
292aa97dd1cSKonstantin Ananyev		for (k = 0; k != n; k++) {
293aa97dd1cSKonstantin Ananyev			NETFE_TRACE("%s(%u, %p): free(%p);\n",
294aa97dd1cSKonstantin Ananyev			__func__, lcore, fes->s, pkt[k]);
295aa97dd1cSKonstantin Ananyev			rte_pktmbuf_free(pkt[k]);
296aa97dd1cSKonstantin Ananyev		}
297aa97dd1cSKonstantin Ananyev		fes->stat.drops += n;
298aa97dd1cSKonstantin Ananyev	}
299aa97dd1cSKonstantin Ananyev
300aa97dd1cSKonstantin Ananyev	/* copy unforwarded mbufs. */
301aa97dd1cSKonstantin Ananyev	for (i = 0; i != n - k; i++)
302aa97dd1cSKonstantin Ananyev		pkt[i] = pkt[i + k];
303aa97dd1cSKonstantin Ananyev
304aa97dd1cSKonstantin Ananyev	fes->pbuf.num = i;
305aa97dd1cSKonstantin Ananyev
306aa97dd1cSKonstantin Ananyev	if (i != 0) {
307aa97dd1cSKonstantin Ananyev		tle_event_raise(fes->txev);
308aa97dd1cSKonstantin Ananyev		fes->stat.txev[TLE_SEV_UP]++;
309aa97dd1cSKonstantin Ananyev	}
310aa97dd1cSKonstantin Ananyev
311aa97dd1cSKonstantin Ananyev	if (n == RTE_DIM(fes->pbuf.pkt)) {
312aa97dd1cSKonstantin Ananyev		tle_event_active(fes->rxev, TLE_SEV_UP);
313aa97dd1cSKonstantin Ananyev		fes->stat.rxev[TLE_SEV_UP]++;
314aa97dd1cSKonstantin Ananyev	}
31521e7392fSKonstantin Ananyev
31621e7392fSKonstantin Ananyev	return (fed == NULL) ? 0 : k;
317aa97dd1cSKonstantin Ananyev}
318aa97dd1cSKonstantin Ananyev
319aa97dd1cSKonstantin Ananyevstatic inline void
32021e7392fSKonstantin Ananyevnetfe_new_conn_tcp(struct netfe_lcore *fe, uint32_t lcore,
321aa97dd1cSKonstantin Ananyev	struct netfe_stream *fes)
322aa97dd1cSKonstantin Ananyev{
32321e7392fSKonstantin Ananyev	uint32_t i, k, n;
324aa97dd1cSKonstantin Ananyev	struct netfe_stream *ts;
32521e7392fSKonstantin Ananyev	struct tle_stream *rs[MAX_PKT_BURST];
326aa97dd1cSKonstantin Ananyev	struct netfe_stream *fs[MAX_PKT_BURST];
32721e7392fSKonstantin Ananyev	struct tle_tcp_stream_cfg prm[MAX_PKT_BURST];
328aa97dd1cSKonstantin Ananyev
329aa97dd1cSKonstantin Ananyev	/* check if any syn requests are waiting */
33021e7392fSKonstantin Ananyev	n = tle_tcp_stream_accept(fes->s, rs, RTE_DIM(rs));
331aa97dd1cSKonstantin Ananyev	if (n == 0)
332aa97dd1cSKonstantin Ananyev		return;
333aa97dd1cSKonstantin Ananyev
33421e7392fSKonstantin Ananyev	NETFE_TRACE("%s(%u): tle_tcp_stream_accept(%p, %u) returns %u\n",
335aa97dd1cSKonstantin Ananyev		__func__, lcore, fes->s, MAX_PKT_BURST, n);
336aa97dd1cSKonstantin Ananyev
337aa97dd1cSKonstantin Ananyev	/* get n free streams */
338aa97dd1cSKonstantin Ananyev	k = netfe_get_streams(&fe->free, fs, n);
33921e7392fSKonstantin Ananyev	if (n != k)
34021e7392fSKonstantin Ananyev		RTE_LOG(ERR, USER1,
34121e7392fSKonstantin Ananyev			"%s(lc=%u): not enough FE resources to handle %u new "
34221e7392fSKonstantin Ananyev			"TCP streams;\n",
34321e7392fSKonstantin Ananyev			__func__, lcore, n - k);
344aa97dd1cSKonstantin Ananyev
345aa97dd1cSKonstantin Ananyev	/* fill accept params to accept k connection requests*/
346aa97dd1cSKonstantin Ananyev	for (i = 0; i != k; i++) {
347aa97dd1cSKonstantin Ananyev
348aa97dd1cSKonstantin Ananyev		ts = fs[i];
349aa97dd1cSKonstantin Ananyev		ts->s = rs[i];
350aa97dd1cSKonstantin Ananyev		ts->op = fes->op;
351aa97dd1cSKonstantin Ananyev		ts->proto = fes->proto;
352aa97dd1cSKonstantin Ananyev		ts->family = fes->family;
353aa97dd1cSKonstantin Ananyev		ts->txlen = fes->txlen;
354e151ee29SRemy Horton		ts->rxlen = fes->rxlen;
355aa97dd1cSKonstantin Ananyev
35621e7392fSKonstantin Ananyev		tle_event_active(ts->erev, TLE_SEV_DOWN);
35721e7392fSKonstantin Ananyev		if (fes->op == TXONLY || fes->op == FWD) {
358aa97dd1cSKonstantin Ananyev			tle_event_active(ts->txev, TLE_SEV_UP);
359aa97dd1cSKonstantin Ananyev			ts->stat.txev[TLE_SEV_UP]++;
36021e7392fSKonstantin Ananyev		}
36121e7392fSKonstantin Ananyev		if (fes->op != TXONLY) {
362aa97dd1cSKonstantin Ananyev			tle_event_active(ts->rxev, TLE_SEV_DOWN);
363aa97dd1cSKonstantin Ananyev			ts->stat.rxev[TLE_SEV_DOWN]++;
364aa97dd1cSKonstantin Ananyev		}
365aa97dd1cSKonstantin Ananyev
366aa97dd1cSKonstantin Ananyev		netfe_put_stream(fe, &fe->use, ts);
367aa97dd1cSKonstantin Ananyev
36821e7392fSKonstantin Ananyev		memset(&prm[i], 0, sizeof(prm[i]));
36921e7392fSKonstantin Ananyev		prm[i].recv_ev = ts->rxev;
37021e7392fSKonstantin Ananyev		prm[i].send_ev = ts->txev;
37121e7392fSKonstantin Ananyev		prm[i].err_ev = ts->erev;
37221e7392fSKonstantin Ananyev	}
37321e7392fS