ed6815275348730cf099eae37d82901cdc08ab21
[dpdk.git] / drivers / net / octeontx2 / otx2_ethdev_sec.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (C) 2020 Marvell International Ltd.
3  */
4
5 #include <rte_ethdev.h>
6 #include <rte_eventdev.h>
7 #include <rte_malloc.h>
8 #include <rte_memzone.h>
9 #include <rte_security.h>
10
11 #include "otx2_ethdev.h"
12 #include "otx2_ethdev_sec.h"
13 #include "otx2_ipsec_fp.h"
14
15 #define ETH_SEC_MAX_PKT_LEN     1450
16
17 struct eth_sec_tag_const {
18         RTE_STD_C11
19         union {
20                 struct {
21                         uint32_t rsvd_11_0  : 12;
22                         uint32_t port       : 8;
23                         uint32_t event_type : 4;
24                         uint32_t rsvd_31_24 : 8;
25                 };
26                 uint32_t u32;
27         };
28 };
29
30 static inline void
31 in_sa_mz_name_get(char *name, int size, uint16_t port)
32 {
33         snprintf(name, size, "otx2_ipsec_in_sadb_%u", port);
34 }
35
36 int
37 otx2_eth_sec_ctx_create(struct rte_eth_dev *eth_dev)
38 {
39         struct rte_security_ctx *ctx;
40
41         ctx = rte_malloc("otx2_eth_sec_ctx",
42                          sizeof(struct rte_security_ctx), 0);
43         if (ctx == NULL)
44                 return -ENOMEM;
45
46         /* Populate ctx */
47
48         ctx->device = eth_dev;
49         ctx->sess_cnt = 0;
50
51         eth_dev->security_ctx = ctx;
52
53         return 0;
54 }
55
56 void
57 otx2_eth_sec_ctx_destroy(struct rte_eth_dev *eth_dev)
58 {
59         rte_free(eth_dev->security_ctx);
60 }
61
62 static int
63 eth_sec_ipsec_cfg(struct rte_eth_dev *eth_dev, uint8_t tt)
64 {
65         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
66         uint16_t port = eth_dev->data->port_id;
67         struct nix_inline_ipsec_lf_cfg *req;
68         struct otx2_mbox *mbox = dev->mbox;
69         struct eth_sec_tag_const tag_const;
70         char name[RTE_MEMZONE_NAMESIZE];
71         const struct rte_memzone *mz;
72
73         in_sa_mz_name_get(name, RTE_MEMZONE_NAMESIZE, port);
74         mz = rte_memzone_lookup(name);
75         if (mz == NULL)
76                 return -EINVAL;
77
78         req = otx2_mbox_alloc_msg_nix_inline_ipsec_lf_cfg(mbox);
79         req->enable = 1;
80         req->sa_base_addr = mz->iova;
81
82         req->ipsec_cfg0.tt = tt;
83
84         tag_const.u32 = 0;
85         tag_const.event_type = RTE_EVENT_TYPE_ETHDEV;
86         tag_const.port = port;
87         req->ipsec_cfg0.tag_const = tag_const.u32;
88
89         req->ipsec_cfg0.sa_pow2_size =
90                         rte_log2_u32(sizeof(struct otx2_ipsec_fp_in_sa));
91         req->ipsec_cfg0.lenm1_max = ETH_SEC_MAX_PKT_LEN - 1;
92
93         req->ipsec_cfg1.sa_idx_w = rte_log2_u32(dev->ipsec_in_max_spi);
94         req->ipsec_cfg1.sa_idx_max = dev->ipsec_in_max_spi - 1;
95
96         return otx2_mbox_process(mbox);
97 }
98
99 int
100 otx2_eth_sec_init(struct rte_eth_dev *eth_dev)
101 {
102         const size_t sa_width = sizeof(struct otx2_ipsec_fp_in_sa);
103         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
104         uint16_t port = eth_dev->data->port_id;
105         char name[RTE_MEMZONE_NAMESIZE];
106         const struct rte_memzone *mz;
107         int mz_sz, ret;
108         uint16_t nb_sa;
109
110         RTE_BUILD_BUG_ON(sa_width < 32 || sa_width > 512 ||
111                          !RTE_IS_POWER_OF_2(sa_width));
112
113         if (!(dev->tx_offloads & DEV_TX_OFFLOAD_SECURITY) &&
114             !(dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY))
115                 return 0;
116
117         nb_sa = dev->ipsec_in_max_spi;
118         mz_sz = nb_sa * sa_width;
119         in_sa_mz_name_get(name, RTE_MEMZONE_NAMESIZE, port);
120         mz = rte_memzone_reserve_aligned(name, mz_sz, rte_socket_id(),
121                                          RTE_MEMZONE_IOVA_CONTIG, OTX2_ALIGN);
122
123         if (mz == NULL) {
124                 otx2_err("Could not allocate inbound SA DB");
125                 return -ENOMEM;
126         }
127
128         memset(mz->addr, 0, mz_sz);
129
130         ret = eth_sec_ipsec_cfg(eth_dev, SSO_TT_ORDERED);
131         if (ret < 0) {
132                 otx2_err("Could not configure inline IPsec");
133                 goto sec_fini;
134         }
135
136         return 0;
137
138 sec_fini:
139         otx2_err("Could not configure device for security");
140         otx2_eth_sec_fini(eth_dev);
141         return ret;
142 }
143
144 void
145 otx2_eth_sec_fini(struct rte_eth_dev *eth_dev)
146 {
147         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
148         uint16_t port = eth_dev->data->port_id;
149         char name[RTE_MEMZONE_NAMESIZE];
150
151         if (!(dev->tx_offloads & DEV_TX_OFFLOAD_SECURITY) &&
152             !(dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY))
153                 return;
154
155         in_sa_mz_name_get(name, RTE_MEMZONE_NAMESIZE, port);
156         rte_memzone_free(rte_memzone_lookup(name));
157 }