net/cnxk: support to update precolor DSCP table
[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 #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         rc = roc_nix_inl_dev_init(inl_dev);
281         if (rc) {
282                 plt_err("Failed to init nix inl device, rc=%d(%s)", rc,
283                         roc_error_msg_get(rc));
284                 goto free_mem;
285         }
286
287         return 0;
288 free_mem:
289         rte_memzone_free(mz);
290         return rc;
291 }
292
293 static const struct rte_pci_id cnxk_nix_inl_pci_map[] = {
294         {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_PF)},
295         {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_VF)},
296         {
297                 .vendor_id = 0,
298         },
299 };
300
301 static struct rte_pci_driver cnxk_nix_inl_pci = {
302         .id_table = cnxk_nix_inl_pci_map,
303         .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA,
304         .probe = cnxk_nix_inl_dev_probe,
305         .remove = cnxk_nix_inl_dev_remove,
306 };
307
308 RTE_PMD_REGISTER_PCI(cnxk_nix_inl, cnxk_nix_inl_pci);
309 RTE_PMD_REGISTER_PCI_TABLE(cnxk_nix_inl, cnxk_nix_inl_pci_map);
310 RTE_PMD_REGISTER_KMOD_DEP(cnxk_nix_inl, "vfio-pci");
311
312 RTE_PMD_REGISTER_PARAM_STRING(cnxk_nix_inl,
313                               CNXK_NIX_INL_SELFTEST "=1"
314                               CNXK_NIX_INL_IPSEC_IN_MAX_SPI "=<1-65535>"
315                               CNXK_INL_CPT_CHANNEL "=<1-4095>/<1-4095>");