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_TABLE_H_
17#define _STREAM_TABLE_H_
18
19#include <rte_hash.h>
20#include "tcp_misc.h"
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26struct stbl_entry {
27	void *data;
28};
29
30struct shtbl {
31	uint32_t nb_ent;  /* max number of entries in the table. */
32	rte_spinlock_t l; /* lock to protect the hash table */
33	struct rte_hash *t;
34	struct stbl_entry *ent;
35} __rte_cache_aligned;
36
37struct stbl {
38	struct shtbl ht[TLE_VNUM];
39};
40
41struct stbl4_key {
42	union l4_ports port;
43	union ipv4_addrs addr;
44} __attribute__((__packed__));
45
46struct stbl6_key {
47	union l4_ports port;
48	union ipv6_addrs addr;
49} __attribute__((__packed__));
50
51struct stbl_key {
52	union l4_ports port;
53	union {
54		union ipv4_addrs addr4;
55		union ipv6_addrs addr6;
56	};
57} __attribute__((__packed__));
58
59extern void stbl_fini(struct stbl *st);
60
61extern int stbl_init(struct stbl *st, uint32_t num, int32_t socket);
62
63static inline void
64stbl_pkt_fill_key(struct stbl_key *k, const union pkt_info *pi, uint32_t type)
65{
66	static const struct stbl_key zero = {
67		.port.raw = 0,
68	};
69
70	k->port = pi->port;
71	if (type == TLE_V4)
72		k->addr4 = pi->addr4;
73	else if (type == TLE_V6)
74		k->addr6 = *pi->addr6;
75	else
76		*k = zero;
77}
78
79static inline void
80stbl_lock(struct stbl *st, uint32_t type)
81{
82	rte_spinlock_lock(&st->ht[type].l);
83}
84
85static inline void
86stbl_unlock(struct stbl *st, uint32_t type)
87{
88	rte_spinlock_unlock(&st->ht[type].l);
89}
90
91static inline struct stbl_entry *
92stbl_add_entry(struct stbl *st, const union pkt_info *pi)
93{
94	int32_t rc;
95	uint32_t type;
96	struct shtbl *ht;
97	struct stbl_key k;
98
99	type = pi->tf.type;
100	stbl_pkt_fill_key(&k, pi, type);
101	ht = st->ht + type;
102
103	rc = rte_hash_add_key(ht->t, &k);
104	if ((uint32_t)rc >= ht->nb_ent)
105		return NULL;
106	return ht->ent + rc;
107}
108
109static inline struct stbl_entry *
110stbl_add_stream(struct stbl *st, const union pkt_info *pi, const void *s)
111{
112	struct stbl_entry *se;
113
114	se = stbl_add_entry(st, pi);
115	if (se != NULL)
116		se->data = (void *)(uintptr_t)s;
117	return se;
118}
119
120static inline struct stbl_entry *
121stbl_find_entry(struct stbl *st, const union pkt_info *pi)
122{
123	int32_t rc;
124	uint32_t type;
125	struct shtbl *ht;
126	struct stbl_key k;
127
128	type = pi->tf.type;
129	stbl_pkt_fill_key(&k, pi, type);
130	ht = st->ht + type;
131
132	rc = rte_hash_lookup(ht->t, &k);
133	if ((uint32_t)rc >= ht->nb_ent)
134		return NULL;
135	return ht->ent + rc;
136}
137
138static inline void *
139stbl_find_data(struct stbl *st, const union pkt_info *pi)
140{
141	struct stbl_entry *ent;
142
143	ent = stbl_find_entry(st, pi);
144	return (ent == NULL) ? NULL : ent->data;
145}
146
147#include "tcp_stream.h"
148
149static inline void
150stbl_stream_fill_key(struct stbl_key *k, const struct tle_stream *s,
151	uint32_t type)
152{
153	static const struct stbl_key zero = {
154		.port.raw = 0,
155	};
156
157	k->port = s->port;
158	if (type == TLE_V4)
159		k->addr4 = s->ipv4.addr;
160	else if (type == TLE_V6)
161		k->addr6 = s->ipv6.addr;
162	else
163		*k = zero;
164}
165
166static inline struct stbl_entry *
167stbl_add_stream_lock(struct stbl *st, const struct tle_tcp_stream *s)
168{
169	uint32_t type;
170	struct stbl_key k;
171	struct stbl_entry *se;
172	struct shtbl *ht;
173	int32_t rc;
174
175	type = s->s.type;
176	stbl_stream_fill_key(&k, &s->s, type);
177	ht = st->ht + type;
178
179	stbl_lock(st, type);
180	rc = rte_hash_add_key(ht->t, &k);
181	stbl_unlock(st, type);
182
183	if ((uint32_t)rc >= ht->nb_ent)
184		return NULL;
185
186	se = ht->ent + rc;
187	if (se != NULL)
188		se->data = (void *)(uintptr_t)s;
189
190	return se;
191}
192
193static inline void
194stbl_del_stream(struct stbl *st, struct stbl_entry *se,
195	const struct tle_tcp_stream *s, uint32_t lock)
196{
197	uint32_t type;
198	struct stbl_key k;
199
200	if (se == NULL)
201		return;
202
203	se->data = NULL;
204
205	type = s->s.type;
206	stbl_stream_fill_key(&k, &s->s, type);
207	if (lock != 0)
208		stbl_lock(st, type);
209	rte_hash_del_key(st->ht[type].t, &k);
210	if (lock != 0)
211		stbl_unlock(st, type);
212}
213
214#ifdef __cplusplus
215}
216#endif
217
218#endif /* _STREAM_TABLE_H_ */
219