1/*
2 * Copyright (c) 2016  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 __FWDTBL_H__
17#define __FWDTBL_H__
18
19struct fwd4_key {
20	uint32_t port;
21	struct in_addr addr;
22} __attribute__((__packed__));
23
24struct fwd6_key {
25	uint32_t port;
26	struct in6_addr addr;
27} __attribute__((__packed__));
28
29union fwd_key {
30	struct fwd4_key k4;
31	struct fwd6_key k6;
32};
33
34static struct rte_hash *
35fwd_tbl_key_prep(const struct netfe_lcore *fe, uint16_t family,
36	const struct sockaddr *sa, union fwd_key *key)
37{
38	struct rte_hash *h;
39	const struct sockaddr_in *sin4;
40	const struct sockaddr_in6 *sin6;
41
42	if (family == AF_INET) {
43		h = fe->fw4h;
44		sin4 = (const struct sockaddr_in *)sa;
45		key->k4.port = sin4->sin_port;
46		key->k4.addr = sin4->sin_addr;
47	} else {
48		h = fe->fw6h;
49		sin6 = (const struct sockaddr_in6 *)sa;
50		key->k6.port = sin6->sin6_port;
51		key->k6.addr = sin6->sin6_addr;
52	}
53
54	return h;
55}
56
57static int
58fwd_tbl_add(struct netfe_lcore *fe, uint16_t family, const struct sockaddr *sa,
59	struct netfe_stream *data)
60{
61	int32_t rc;
62	struct rte_hash *h;
63	union fwd_key key;
64
65	h = fwd_tbl_key_prep(fe, family, sa, &key);
66	rc = rte_hash_add_key_data(h, &key, data);
67	return rc;
68}
69
70static struct netfe_stream *
71fwd_tbl_lkp(struct netfe_lcore *fe, uint16_t family, const struct sockaddr *sa)
72{
73	int rc;
74	void *d;
75	struct rte_hash *h;
76	union fwd_key key;
77
78	h = fwd_tbl_key_prep(fe, family, sa, &key);
79	rc = rte_hash_lookup_data(h, &key, &d);
80	if (rc < 0)
81		d = NULL;
82	return d;
83}
84
85static int
86fwd_tbl_init(struct netfe_lcore *fe, uint16_t family, uint32_t lcore)
87{
88	int32_t rc;
89	struct rte_hash **h;
90	struct rte_hash_parameters hprm;
91	char buf[RTE_HASH_NAMESIZE];
92
93	if (family == AF_INET) {
94		snprintf(buf, sizeof(buf), "fwd4tbl@%u", lcore);
95		h = &fe->fw4h;
96		hprm.key_len = sizeof(struct fwd4_key);
97	} else {
98		snprintf(buf, sizeof(buf), "fwd6tbl@%u", lcore);
99		h = &fe->fw6h;
100		hprm.key_len = sizeof(struct fwd6_key);
101	}
102
103	hprm.name = buf;
104	hprm.entries = RTE_MAX(2 * fe->snum, 0x10U);
105	hprm.socket_id = rte_lcore_to_socket_id(lcore);
106	hprm.hash_func = NULL;
107	hprm.hash_func_init_val = 0;
108
109	*h = rte_hash_create(&hprm);
110	if (*h == NULL)
111		rc = (rte_errno != 0) ? -rte_errno : -ENOMEM;
112	else
113		rc = 0;
114	return rc;
115}
116
117#endif /* __FWDTBL_H__ */
118