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