xref: /dpdk/drivers/net/cnxk/cnxk_ethdev_sec.c (revision d0b8a4e1)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include <cnxk_ethdev.h>
6 
7 #define CNXK_NIX_INL_SELFTEST	      "selftest"
8 #define CNXK_NIX_INL_IPSEC_IN_MAX_SPI "ipsec_in_max_spi"
9 #define CNXK_INL_CPT_CHANNEL	      "inl_cpt_channel"
10 
11 struct inl_cpt_channel {
12 	bool is_multi_channel;
13 	uint16_t channel;
14 	uint16_t mask;
15 };
16 
17 #define CNXK_NIX_INL_DEV_NAME RTE_STR(cnxk_nix_inl_dev_)
18 #define CNXK_NIX_INL_DEV_NAME_LEN                                              \
19 	(sizeof(CNXK_NIX_INL_DEV_NAME) + PCI_PRI_STR_SIZE)
20 
21 static inline int
22 bitmap_ctzll(uint64_t slab)
23 {
24 	if (slab == 0)
25 		return 0;
26 
27 	return __builtin_ctzll(slab);
28 }
29 
30 int
31 cnxk_eth_outb_sa_idx_get(struct cnxk_eth_dev *dev, uint32_t *idx_p)
32 {
33 	uint32_t pos, idx;
34 	uint64_t slab;
35 	int rc;
36 
37 	if (!dev->outb.sa_bmap)
38 		return -ENOTSUP;
39 
40 	pos = 0;
41 	slab = 0;
42 	/* Scan from the beginning */
43 	plt_bitmap_scan_init(dev->outb.sa_bmap);
44 	/* Scan bitmap to get the free sa index */
45 	rc = plt_bitmap_scan(dev->outb.sa_bmap, &pos, &slab);
46 	/* Empty bitmap */
47 	if (rc == 0) {
48 		plt_err("Outbound SA' exhausted, use 'ipsec_out_max_sa' "
49 			"devargs to increase");
50 		return -ERANGE;
51 	}
52 
53 	/* Get free SA index */
54 	idx = pos + bitmap_ctzll(slab);
55 	plt_bitmap_clear(dev->outb.sa_bmap, idx);
56 	*idx_p = idx;
57 	return 0;
58 }
59 
60 int
61 cnxk_eth_outb_sa_idx_put(struct cnxk_eth_dev *dev, uint32_t idx)
62 {
63 	if (idx >= dev->outb.max_sa)
64 		return -EINVAL;
65 
66 	/* Check if it is already free */
67 	if (plt_bitmap_get(dev->outb.sa_bmap, idx))
68 		return -EINVAL;
69 
70 	/* Mark index as free */
71 	plt_bitmap_set(dev->outb.sa_bmap, idx);
72 	return 0;
73 }
74 
75 struct cnxk_eth_sec_sess *
76 cnxk_eth_sec_sess_get_by_spi(struct cnxk_eth_dev *dev, uint32_t spi, bool inb)
77 {
78 	struct cnxk_eth_sec_sess_list *list;
79 	struct cnxk_eth_sec_sess *eth_sec;
80 
81 	list = inb ? &dev->inb.list : &dev->outb.list;
82 	TAILQ_FOREACH(eth_sec, list, entry) {
83 		if (eth_sec->spi == spi)
84 			return eth_sec;
85 	}
86 
87 	return NULL;
88 }
89 
90 struct cnxk_eth_sec_sess *
91 cnxk_eth_sec_sess_get_by_sess(struct cnxk_eth_dev *dev,
92 			      struct rte_security_session *sess)
93 {
94 	struct cnxk_eth_sec_sess *eth_sec = NULL;
95 
96 	/* Search in inbound list */
97 	TAILQ_FOREACH(eth_sec, &dev->inb.list, entry) {
98 		if (eth_sec->sess == sess)
99 			return eth_sec;
100 	}
101 
102 	/* Search in outbound list */
103 	TAILQ_FOREACH(eth_sec, &dev->outb.list, entry) {
104 		if (eth_sec->sess == sess)
105 			return eth_sec;
106 	}
107 
108 	return NULL;
109 }
110 
111 static unsigned int
112 cnxk_eth_sec_session_get_size(void *device __rte_unused)
113 {
114 	return sizeof(struct cnxk_eth_sec_sess);
115 }
116 
117 struct rte_security_ops cnxk_eth_sec_ops = {
118 	.session_get_size = cnxk_eth_sec_session_get_size
119 };
120 
121 static int
122 parse_ipsec_in_max_spi(const char *key, const char *value, void *extra_args)
123 {
124 	RTE_SET_USED(key);
125 	uint32_t val;
126 
127 	val = atoi(value);
128 
129 	*(uint16_t *)extra_args = val;
130 
131 	return 0;
132 }
133 
134 static int
135 parse_selftest(const char *key, const char *value, void *extra_args)
136 {
137 	RTE_SET_USED(key);
138 	uint32_t val;
139 
140 	val = atoi(value);
141 
142 	*(uint8_t *)extra_args = !!(val == 1);
143 	return 0;
144 }
145 
146 static int
147 parse_inl_cpt_channel(const char *key, const char *value, void *extra_args)
148 {
149 	RTE_SET_USED(key);
150 	uint16_t chan = 0, mask = 0;
151 	char *next = 0;
152 
153 	/* next will point to the separator '/' */
154 	chan = strtol(value, &next, 16);
155 	mask = strtol(++next, 0, 16);
156 
157 	if (chan > GENMASK(12, 0) || mask > GENMASK(12, 0))
158 		return -EINVAL;
159 
160 	((struct inl_cpt_channel *)extra_args)->channel = chan;
161 	((struct inl_cpt_channel *)extra_args)->mask = mask;
162 	((struct inl_cpt_channel *)extra_args)->is_multi_channel = true;
163 
164 	return 0;
165 }
166 
167 static int
168 nix_inl_parse_devargs(struct rte_devargs *devargs,
169 		      struct roc_nix_inl_dev *inl_dev)
170 {
171 	uint32_t ipsec_in_max_spi = BIT(8) - 1;
172 	struct inl_cpt_channel cpt_channel;
173 	struct rte_kvargs *kvlist;
174 	uint8_t selftest = 0;
175 
176 	memset(&cpt_channel, 0, sizeof(cpt_channel));
177 
178 	if (devargs == NULL)
179 		goto null_devargs;
180 
181 	kvlist = rte_kvargs_parse(devargs->args, NULL);
182 	if (kvlist == NULL)
183 		goto exit;
184 
185 	rte_kvargs_process(kvlist, CNXK_NIX_INL_SELFTEST, &parse_selftest,
186 			   &selftest);
187 	rte_kvargs_process(kvlist, CNXK_NIX_INL_IPSEC_IN_MAX_SPI,
188 			   &parse_ipsec_in_max_spi, &ipsec_in_max_spi);
189 	rte_kvargs_process(kvlist, CNXK_INL_CPT_CHANNEL, &parse_inl_cpt_channel,
190 			   &cpt_channel);
191 	rte_kvargs_free(kvlist);
192 
193 null_devargs:
194 	inl_dev->ipsec_in_max_spi = ipsec_in_max_spi;
195 	inl_dev->selftest = selftest;
196 	inl_dev->channel = cpt_channel.channel;
197 	inl_dev->chan_mask = cpt_channel.mask;
198 	inl_dev->is_multi_channel = cpt_channel.is_multi_channel;
199 	return 0;
200 exit:
201 	return -EINVAL;
202 }
203 
204 static inline char *
205 nix_inl_dev_to_name(struct rte_pci_device *pci_dev, char *name)
206 {
207 	snprintf(name, CNXK_NIX_INL_DEV_NAME_LEN,
208 		 CNXK_NIX_INL_DEV_NAME PCI_PRI_FMT, pci_dev->addr.domain,
209 		 pci_dev->addr.bus, pci_dev->addr.devid,
210 		 pci_dev->addr.function);
211 
212 	return name;
213 }
214 
215 static int
216 cnxk_nix_inl_dev_remove(struct rte_pci_device *pci_dev)
217 {
218 	char name[CNXK_NIX_INL_DEV_NAME_LEN];
219 	const struct rte_memzone *mz;
220 	struct roc_nix_inl_dev *dev;
221 	int rc;
222 
223 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
224 		return 0;
225 
226 	mz = rte_memzone_lookup(nix_inl_dev_to_name(pci_dev, name));
227 	if (!mz)
228 		return 0;
229 
230 	dev = mz->addr;
231 
232 	/* Cleanup inline dev */
233 	rc = roc_nix_inl_dev_fini(dev);
234 	if (rc) {
235 		plt_err("Failed to cleanup inl dev, rc=%d(%s)", rc,
236 			roc_error_msg_get(rc));
237 		return rc;
238 	}
239 
240 	rte_memzone_free(mz);
241 	return 0;
242 }
243 
244 static int
245 cnxk_nix_inl_dev_probe(struct rte_pci_driver *pci_drv,
246 		       struct rte_pci_device *pci_dev)
247 {
248 	char name[CNXK_NIX_INL_DEV_NAME_LEN];
249 	struct roc_nix_inl_dev *inl_dev;
250 	const struct rte_memzone *mz;
251 	int rc = -ENOMEM;
252 
253 	RTE_SET_USED(pci_drv);
254 
255 	rc = roc_plt_init();
256 	if (rc) {
257 		plt_err("Failed to initialize platform model, rc=%d", rc);
258 		return rc;
259 	}
260 
261 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
262 		return 0;
263 
264 	mz = rte_memzone_reserve_aligned(nix_inl_dev_to_name(pci_dev, name),
265 					 sizeof(*inl_dev), SOCKET_ID_ANY, 0,
266 					 RTE_CACHE_LINE_SIZE);
267 	if (mz == NULL)
268 		return rc;
269 
270 	inl_dev = mz->addr;
271 	inl_dev->pci_dev = pci_dev;
272 
273 	/* Parse devargs string */
274 	rc = nix_inl_parse_devargs(pci_dev->device.devargs, inl_dev);
275 	if (rc) {
276 		plt_err("Failed to parse devargs rc=%d", rc);
277 		goto free_mem;
278 	}
279 
280 	inl_dev->attach_cptlf = true;
281 	rc = roc_nix_inl_dev_init(inl_dev);
282 	if (rc) {
283 		plt_err("Failed to init nix inl device, rc=%d(%s)", rc,
284 			roc_error_msg_get(rc));
285 		goto free_mem;
286 	}
287 
288 	return 0;
289 free_mem:
290 	rte_memzone_free(mz);
291 	return rc;
292 }
293 
294 static const struct rte_pci_id cnxk_nix_inl_pci_map[] = {
295 	{RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_PF)},
296 	{RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_VF)},
297 	{
298 		.vendor_id = 0,
299 	},
300 };
301 
302 static struct rte_pci_driver cnxk_nix_inl_pci = {
303 	.id_table = cnxk_nix_inl_pci_map,
304 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA,
305 	.probe = cnxk_nix_inl_dev_probe,
306 	.remove = cnxk_nix_inl_dev_remove,
307 };
308 
309 RTE_PMD_REGISTER_PCI(cnxk_nix_inl, cnxk_nix_inl_pci);
310 RTE_PMD_REGISTER_PCI_TABLE(cnxk_nix_inl, cnxk_nix_inl_pci_map);
311 RTE_PMD_REGISTER_KMOD_DEP(cnxk_nix_inl, "vfio-pci");
312 
313 RTE_PMD_REGISTER_PARAM_STRING(cnxk_nix_inl,
314 			      CNXK_NIX_INL_SELFTEST "=1"
315 			      CNXK_NIX_INL_IPSEC_IN_MAX_SPI "=<1-65535>"
316 			      CNXK_INL_CPT_CHANNEL "=<1-4095>/<1-4095>");
317