stream.h revision 37854f54
1/*
2 * Copyright (c) 2016-2017  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 _STREAM_H_
17#define _STREAM_H_
18
19#include "ctx.h"
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
25/*
26 * Common structure that must be present as first field in all partcular
27 * L4 (UDP/TCP, etc.) stream implementations.
28 */
29struct tle_stream {
30
31	STAILQ_ENTRY(tle_stream) link;
32	struct tle_ctx *ctx;
33
34	uint8_t type;	       /* TLE_V4 or TLE_V6 */
35
36	/* Stream address information. */
37	union l4_ports port;
38	union l4_ports pmsk;
39
40	union {
41		struct {
42			union ipv4_addrs addr;
43			union ipv4_addrs mask;
44		} ipv4;
45		struct {
46			union ipv6_addrs addr;
47			union ipv6_addrs mask;
48		} ipv6;
49	};
50};
51
52static inline uint32_t
53get_streams(struct tle_ctx *ctx, struct tle_stream *s[], uint32_t num)
54{
55	struct tle_stream *p;
56	uint32_t i, n;
57
58	rte_spinlock_lock(&ctx->streams.lock);
59
60	n = RTE_MIN(ctx->streams.nb_free, num);
61	for (i = 0, p = STAILQ_FIRST(&ctx->streams.free);
62			i != n;
63			i++, p = STAILQ_NEXT(p, link))
64		s[i] = p;
65
66	if (p == NULL)
67		/* we retrieved all free entries */
68		STAILQ_INIT(&ctx->streams.free);
69	else
70		STAILQ_FIRST(&ctx->streams.free) = p;
71
72	ctx->streams.nb_free -= n;
73	rte_spinlock_unlock(&ctx->streams.lock);
74	return n;
75}
76
77static inline struct tle_stream *
78get_stream(struct tle_ctx *ctx)
79{
80	struct tle_stream *s;
81
82	s = NULL;
83	if (ctx->streams.nb_free == 0)
84		return s;
85
86	get_streams(ctx, &s, 1);
87	return s;
88}
89
90static inline void
91put_stream(struct tle_ctx *ctx, struct tle_stream *s, int32_t head)
92{
93	s->type = TLE_VNUM;
94	rte_spinlock_lock(&ctx->streams.lock);
95	if (head != 0)
96		STAILQ_INSERT_HEAD(&ctx->streams.free, s, link);
97	else
98		STAILQ_INSERT_TAIL(&ctx->streams.free, s, link);
99	ctx->streams.nb_free++;
100	rte_spinlock_unlock(&ctx->streams.lock);
101}
102
103/* calculate number of drbs per stream. */
104static inline uint32_t
105calc_stream_drb_num(const struct tle_ctx *ctx, uint32_t obj_num)
106{
107	uint32_t num;
108
109	num = (ctx->prm.max_stream_sbufs + obj_num - 1) / obj_num;
110	num = num + num / 2;
111	num = RTE_MAX(num, RTE_DIM(ctx->dev) + 1);
112	return num;
113}
114
115static inline uint32_t
116drb_nb_elem(const struct tle_ctx *ctx)
117{
118	return (ctx->prm.send_bulk_size != 0) ?
119		ctx->prm.send_bulk_size : MAX_PKT_BURST;
120}
121
122static inline int32_t
123stream_get_dest(struct tle_stream *s, const void *dst_addr,
124	struct tle_dest *dst)
125{
126	int32_t rc;
127	const struct in_addr *d4;
128	const struct in6_addr *d6;
129	struct tle_ctx *ctx;
130	struct tle_dev *dev;
131
132	ctx = s->ctx;
133
134	/* it is here just to keep gcc happy. */
135	d4 = NULL;
136	d6 = NULL;
137
138	if (s->type == TLE_V4) {
139		d4 = dst_addr;
140		rc = ctx->prm.lookup4(ctx->prm.lookup4_data, d4, dst);
141	} else if (s->type == TLE_V6) {
142		d6 = dst_addr;
143		rc = ctx->prm.lookup6(ctx->prm.lookup6_data, d6, dst);
144	} else
145		rc = -ENOENT;
146
147	if (rc < 0 || dst->dev == NULL || dst->dev->ctx != ctx)
148		return -ENOENT;
149
150	dev = dst->dev;
151	dst->ol_flags = dev->tx.ol_flags[s->type];
152
153	if (s->type == TLE_V4) {
154		struct ipv4_hdr *l3h;
155		l3h = (struct ipv4_hdr *)(dst->hdr + dst->l2_len);
156		l3h->src_addr = dev->prm.local_addr4.s_addr;
157		l3h->dst_addr = d4->s_addr;
158	} else {
159		struct ipv6_hdr *l3h;
160		l3h = (struct ipv6_hdr *)(dst->hdr + dst->l2_len);
161		rte_memcpy(l3h->src_addr, &dev->prm.local_addr6,
162			sizeof(l3h->src_addr));
163		rte_memcpy(l3h->dst_addr, d6, sizeof(l3h->dst_addr));
164	}
165
166	return dev - ctx->dev;
167}
168
169#ifdef __cplusplus
170}
171#endif
172
173#endif /* _STREAM_H_ */
174