Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2023 Marvell.
3 : : */
4 : :
5 : : #include <cnxk_ethdev.h>
6 : : #include <cnxk_ethdev_mcs.h>
7 : : #include <roc_mcs.h>
8 : :
9 : : static int
10 : 0 : mcs_resource_alloc(struct cnxk_mcs_dev *mcs_dev, enum mcs_direction dir, uint8_t rsrc_id[],
11 : : uint8_t rsrc_cnt, enum cnxk_mcs_rsrc_type type)
12 : : {
13 : 0 : struct roc_mcs_alloc_rsrc_req req = {0};
14 : : struct roc_mcs_alloc_rsrc_rsp rsp;
15 : : int i;
16 : :
17 : 0 : req.rsrc_type = type;
18 : 0 : req.rsrc_cnt = rsrc_cnt;
19 : 0 : req.dir = dir;
20 : :
21 : : memset(&rsp, 0, sizeof(struct roc_mcs_alloc_rsrc_rsp));
22 : :
23 [ # # ]: 0 : if (roc_mcs_rsrc_alloc(mcs_dev->mdev, &req, &rsp)) {
24 : 0 : plt_err("Cannot allocate mcs resource.");
25 : 0 : return -1;
26 : : }
27 : :
28 [ # # ]: 0 : for (i = 0; i < rsrc_cnt; i++) {
29 [ # # # # : 0 : switch (rsp.rsrc_type) {
# ]
30 : 0 : case CNXK_MCS_RSRC_TYPE_FLOWID:
31 : 0 : rsrc_id[i] = rsp.flow_ids[i];
32 : 0 : break;
33 : 0 : case CNXK_MCS_RSRC_TYPE_SECY:
34 : 0 : rsrc_id[i] = rsp.secy_ids[i];
35 : 0 : break;
36 : 0 : case CNXK_MCS_RSRC_TYPE_SC:
37 : 0 : rsrc_id[i] = rsp.sc_ids[i];
38 : 0 : break;
39 : 0 : case CNXK_MCS_RSRC_TYPE_SA:
40 : 0 : rsrc_id[i] = rsp.sa_ids[i];
41 : 0 : break;
42 : 0 : default:
43 : 0 : plt_err("Invalid mcs resource allocated.");
44 : 0 : return -1;
45 : : }
46 : : }
47 : : return 0;
48 : : }
49 : :
50 : : int
51 [ # # ]: 0 : cnxk_eth_macsec_sa_create(void *device, struct rte_security_macsec_sa *conf)
52 : : {
53 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
54 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
55 : 0 : uint8_t salt[RTE_SECURITY_MACSEC_SALT_LEN] = {0};
56 : 0 : struct roc_mcs_pn_table_write_req pn_req = {0};
57 : 0 : uint8_t hash_key_rev[CNXK_MACSEC_HASH_KEY] = {0};
58 : 0 : uint8_t hash_key[CNXK_MACSEC_HASH_KEY] = {0};
59 : 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
60 : : struct roc_mcs_sa_plcy_write_req req;
61 : 0 : uint8_t ciph_key[32] = {0};
62 : : enum mcs_direction dir;
63 [ # # ]: 0 : uint8_t sa_id = 0;
64 : : int i, ret = 0;
65 : :
66 [ # # ]: 0 : if (!roc_feature_nix_has_macsec())
67 : : return -ENOTSUP;
68 : :
69 : 0 : dir = (conf->dir == RTE_SECURITY_MACSEC_DIR_TX) ? MCS_TX : MCS_RX;
70 : 0 : ret = mcs_resource_alloc(mcs_dev, dir, &sa_id, 1, CNXK_MCS_RSRC_TYPE_SA);
71 [ # # ]: 0 : if (ret) {
72 : 0 : plt_err("Failed to allocate SA id.");
73 : 0 : return -ENOMEM;
74 : : }
75 : : memset(&req, 0, sizeof(struct roc_mcs_sa_plcy_write_req));
76 : 0 : req.sa_index[0] = sa_id;
77 : 0 : req.sa_cnt = 1;
78 : 0 : req.dir = dir;
79 : :
80 [ # # ]: 0 : if (conf->key.length != 16 && conf->key.length != 32)
81 : : return -EINVAL;
82 : :
83 [ # # ]: 0 : for (i = 0; i < conf->key.length; i++)
84 : 0 : ciph_key[i] = conf->key.data[conf->key.length - 1 - i];
85 : :
86 : 0 : memcpy(&req.plcy[0][0], ciph_key, conf->key.length);
87 : :
88 : 0 : roc_aes_hash_key_derive(conf->key.data, conf->key.length, hash_key);
89 [ # # ]: 0 : for (i = 0; i < CNXK_MACSEC_HASH_KEY; i++)
90 : 0 : hash_key_rev[i] = hash_key[CNXK_MACSEC_HASH_KEY - 1 - i];
91 : :
92 : : memcpy(&req.plcy[0][4], hash_key_rev, CNXK_MACSEC_HASH_KEY);
93 : :
94 [ # # ]: 0 : for (i = 0; i < RTE_SECURITY_MACSEC_SALT_LEN; i++)
95 : 0 : salt[i] = conf->salt[RTE_SECURITY_MACSEC_SALT_LEN - 1 - i];
96 : : memcpy(&req.plcy[0][6], salt, RTE_SECURITY_MACSEC_SALT_LEN);
97 : :
98 : 0 : req.plcy[0][7] |= (uint64_t)conf->ssci << 32;
99 [ # # ]: 0 : req.plcy[0][8] = (conf->dir == RTE_SECURITY_MACSEC_DIR_TX) ? (conf->an & 0x3) : 0;
100 : :
101 : 0 : ret = roc_mcs_sa_policy_write(mcs_dev->mdev, &req);
102 [ # # ]: 0 : if (ret) {
103 : 0 : plt_err("Failed to write SA policy.");
104 : 0 : return -EINVAL;
105 : : }
106 [ # # ]: 0 : pn_req.next_pn = ((uint64_t)conf->xpn << 32) | rte_be_to_cpu_32(conf->next_pn);
107 : 0 : pn_req.pn_id = sa_id;
108 : 0 : pn_req.dir = dir;
109 : :
110 : 0 : ret = roc_mcs_pn_table_write(mcs_dev->mdev, &pn_req);
111 [ # # ]: 0 : if (ret) {
112 : 0 : plt_err("Failed to write PN table.");
113 : 0 : return -EINVAL;
114 : : }
115 : :
116 : 0 : roc_mcs_sa_port_map_update(mcs_dev->mdev, sa_id, mcs_dev->port_id);
117 : :
118 : 0 : return sa_id;
119 : : }
120 : :
121 : : int
122 [ # # ]: 0 : cnxk_eth_macsec_sa_destroy(void *device, uint16_t sa_id, enum rte_security_macsec_direction dir)
123 : : {
124 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
125 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
126 : 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
127 : 0 : struct roc_mcs_clear_stats stats_req = {0};
128 [ # # ]: 0 : struct roc_mcs_free_rsrc_req req = {0};
129 : : int ret = 0;
130 : :
131 [ # # ]: 0 : if (!roc_feature_nix_has_macsec())
132 : : return -ENOTSUP;
133 : :
134 : 0 : stats_req.type = CNXK_MCS_RSRC_TYPE_SA;
135 : 0 : stats_req.id = sa_id;
136 : 0 : stats_req.dir = (dir == RTE_SECURITY_MACSEC_DIR_TX) ? MCS_TX : MCS_RX;
137 : : stats_req.all = 0;
138 : :
139 : 0 : ret = roc_mcs_stats_clear(mcs_dev->mdev, &stats_req);
140 [ # # ]: 0 : if (ret)
141 : 0 : plt_err("Failed to clear stats for SA id %u, dir %u.", sa_id, dir);
142 : :
143 : 0 : req.rsrc_id = sa_id;
144 : 0 : req.dir = (dir == RTE_SECURITY_MACSEC_DIR_TX) ? MCS_TX : MCS_RX;
145 : 0 : req.rsrc_type = CNXK_MCS_RSRC_TYPE_SA;
146 : :
147 : 0 : ret = roc_mcs_rsrc_free(mcs_dev->mdev, &req);
148 [ # # ]: 0 : if (ret)
149 : 0 : plt_err("Failed to free SA id %u, dir %u.", sa_id, dir);
150 : :
151 : : return ret;
152 : : }
153 : :
154 : : int
155 [ # # ]: 0 : cnxk_eth_macsec_sc_create(void *device, struct rte_security_macsec_sc *conf)
156 : : {
157 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
158 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
159 : 0 : struct roc_mcs_set_pn_threshold pn_thresh = {0};
160 : 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
161 : : enum mcs_direction dir;
162 [ # # ]: 0 : uint8_t sc_id = 0;
163 : : int i, ret = 0;
164 : :
165 [ # # ]: 0 : if (!roc_feature_nix_has_macsec())
166 : : return -ENOTSUP;
167 : :
168 : 0 : dir = (conf->dir == RTE_SECURITY_MACSEC_DIR_TX) ? MCS_TX : MCS_RX;
169 : 0 : ret = mcs_resource_alloc(mcs_dev, dir, &sc_id, 1, CNXK_MCS_RSRC_TYPE_SC);
170 [ # # ]: 0 : if (ret) {
171 : 0 : plt_err("Failed to allocate SC id.");
172 : 0 : return -ENOMEM;
173 : : }
174 : :
175 [ # # ]: 0 : if (conf->dir == RTE_SECURITY_MACSEC_DIR_TX) {
176 : 0 : struct roc_mcs_tx_sc_sa_map req = {0};
177 : :
178 : 0 : req.sa_index0 = conf->sc_tx.sa_id & 0xFF;
179 : 0 : req.sa_index1 = conf->sc_tx.sa_id_rekey & 0xFF;
180 : 0 : req.rekey_ena = conf->sc_tx.re_key_en;
181 : 0 : req.sa_index0_vld = conf->sc_tx.active;
182 : 0 : req.sa_index1_vld = conf->sc_tx.re_key_en && conf->sc_tx.active;
183 : : req.tx_sa_active = 0;
184 : 0 : req.sectag_sci = conf->sc_tx.sci;
185 : 0 : req.sc_id = sc_id;
186 : :
187 : 0 : ret = roc_mcs_tx_sc_sa_map_write(mcs_dev->mdev, &req);
188 [ # # ]: 0 : if (ret) {
189 : 0 : plt_err("Failed to map TX SC-SA");
190 : 0 : return -EINVAL;
191 : : }
192 : 0 : pn_thresh.xpn = conf->sc_tx.is_xpn;
193 : : } else {
194 [ # # ]: 0 : for (i = 0; i < RTE_SECURITY_MACSEC_NUM_AN; i++) {
195 : 0 : struct roc_mcs_rx_sc_sa_map req = {0};
196 : :
197 : 0 : req.sa_index = conf->sc_rx.sa_id[i] & 0x7F;
198 : 0 : req.sc_id = sc_id;
199 : 0 : req.an = i & 0x3;
200 : : req.sa_in_use = 0;
201 : : /* Clearing the sa_in_use bit automatically clears
202 : : * the corresponding pn_thresh_reached bit
203 : : */
204 : 0 : ret = roc_mcs_rx_sc_sa_map_write(mcs_dev->mdev, &req);
205 [ # # ]: 0 : if (ret) {
206 : 0 : plt_err("Failed to map RX SC-SA");
207 : 0 : return -EINVAL;
208 : : }
209 : 0 : req.sa_in_use = conf->sc_rx.sa_in_use[i];
210 : 0 : ret = roc_mcs_rx_sc_sa_map_write(mcs_dev->mdev, &req);
211 [ # # ]: 0 : if (ret) {
212 : 0 : plt_err("Failed to map RX SC-SA");
213 : 0 : return -EINVAL;
214 : : }
215 : : }
216 : 0 : pn_thresh.xpn = conf->sc_rx.is_xpn;
217 : : }
218 : :
219 : 0 : pn_thresh.threshold = conf->pn_threshold;
220 : 0 : pn_thresh.dir = dir;
221 : :
222 : 0 : ret = roc_mcs_pn_threshold_set(mcs_dev->mdev, &pn_thresh);
223 [ # # ]: 0 : if (ret) {
224 : 0 : plt_err("Failed to write PN threshold.");
225 : 0 : return -EINVAL;
226 : : }
227 : :
228 : 0 : return sc_id;
229 : : }
230 : :
231 : : int
232 [ # # ]: 0 : cnxk_eth_macsec_sc_destroy(void *device, uint16_t sc_id, enum rte_security_macsec_direction dir)
233 : : {
234 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
235 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
236 : 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
237 : 0 : struct roc_mcs_clear_stats stats_req = {0};
238 [ # # ]: 0 : struct roc_mcs_free_rsrc_req req = {0};
239 : : int ret = 0;
240 : :
241 [ # # ]: 0 : if (!roc_feature_nix_has_macsec())
242 : : return -ENOTSUP;
243 : :
244 : 0 : stats_req.type = CNXK_MCS_RSRC_TYPE_SC;
245 : 0 : stats_req.id = sc_id;
246 : 0 : stats_req.dir = (dir == RTE_SECURITY_MACSEC_DIR_TX) ? MCS_TX : MCS_RX;
247 : : stats_req.all = 0;
248 : :
249 : 0 : ret = roc_mcs_stats_clear(mcs_dev->mdev, &stats_req);
250 [ # # ]: 0 : if (ret)
251 : 0 : plt_err("Failed to clear stats for SC id %u, dir %u.", sc_id, dir);
252 : :
253 : 0 : req.rsrc_id = sc_id;
254 : 0 : req.dir = (dir == RTE_SECURITY_MACSEC_DIR_TX) ? MCS_TX : MCS_RX;
255 : 0 : req.rsrc_type = CNXK_MCS_RSRC_TYPE_SC;
256 : :
257 : 0 : ret = roc_mcs_rsrc_free(mcs_dev->mdev, &req);
258 [ # # ]: 0 : if (ret)
259 : 0 : plt_err("Failed to free SC id.");
260 : :
261 : : return ret;
262 : : }
263 : :
264 : : struct cnxk_macsec_sess *
265 : 0 : cnxk_eth_macsec_sess_get_by_sess(struct cnxk_eth_dev *dev, const struct rte_security_session *sess)
266 : : {
267 : : struct cnxk_macsec_sess *macsec_sess = NULL;
268 : :
269 [ # # ]: 0 : TAILQ_FOREACH(macsec_sess, &dev->mcs_list, entry) {
270 [ # # ]: 0 : if (macsec_sess->sess == sess)
271 : 0 : return macsec_sess;
272 : : }
273 : :
274 : : return NULL;
275 : : }
276 : :
277 : : int
278 : 0 : cnxk_eth_macsec_session_create(struct cnxk_eth_dev *dev, struct rte_security_session_conf *conf,
279 : : struct rte_security_session *sess)
280 : : {
281 : 0 : struct cnxk_macsec_sess *macsec_sess_priv = SECURITY_GET_SESS_PRIV(sess);
282 : : struct rte_security_macsec_xform *xform = &conf->macsec;
283 : 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
284 : : struct roc_mcs_secy_plcy_write_req req;
285 : : enum mcs_direction dir;
286 [ # # ]: 0 : uint8_t secy_id = 0;
287 : : uint8_t sectag_tci = 0;
288 : : int ret = 0;
289 : :
290 [ # # ]: 0 : if (!roc_feature_nix_has_macsec())
291 : : return -ENOTSUP;
292 : :
293 : 0 : dir = (xform->dir == RTE_SECURITY_MACSEC_DIR_TX) ? MCS_TX : MCS_RX;
294 : 0 : ret = mcs_resource_alloc(mcs_dev, dir, &secy_id, 1, CNXK_MCS_RSRC_TYPE_SECY);
295 [ # # ]: 0 : if (ret) {
296 : 0 : plt_err("Failed to allocate SECY id.");
297 : 0 : return -ENOMEM;
298 : : }
299 : :
300 : 0 : req.secy_id = secy_id;
301 : 0 : req.dir = dir;
302 : : req.plcy = 0L;
303 : :
304 [ # # ]: 0 : if (xform->dir == RTE_SECURITY_MACSEC_DIR_TX) {
305 : 0 : sectag_tci = ((uint8_t)xform->tx_secy.sectag_version << 5) |
306 : 0 : ((uint8_t)xform->tx_secy.end_station << 4) |
307 : 0 : ((uint8_t)xform->tx_secy.send_sci << 3) |
308 : 0 : ((uint8_t)xform->tx_secy.scb << 2) |
309 : 0 : ((uint8_t)xform->tx_secy.encrypt << 1) |
310 : 0 : (uint8_t)xform->tx_secy.encrypt;
311 : 0 : req.plcy = (((uint64_t)xform->tx_secy.mtu & 0xFFFF) << 28) |
312 : 0 : (((uint64_t)sectag_tci & 0x3F) << 22) |
313 : 0 : (((uint64_t)xform->tx_secy.sectag_off & 0x7F) << 15) |
314 : 0 : ((uint64_t)xform->tx_secy.sectag_insert_mode << 14) |
315 : 0 : ((uint64_t)xform->tx_secy.icv_include_da_sa << 13) |
316 : 0 : (((uint64_t)xform->cipher_off & 0x7F) << 6) |
317 : 0 : ((uint64_t)xform->alg << 2) |
318 : 0 : ((uint64_t)xform->tx_secy.protect_frames << 1) |
319 : 0 : (uint64_t)xform->tx_secy.ctrl_port_enable;
320 : : } else {
321 : 0 : req.plcy = ((uint64_t)xform->rx_secy.replay_win_sz << 18) |
322 : 0 : ((uint64_t)xform->rx_secy.replay_protect << 17) |
323 : 0 : ((uint64_t)xform->rx_secy.icv_include_da_sa << 16) |
324 : 0 : (((uint64_t)xform->cipher_off & 0x7F) << 9) |
325 : 0 : ((uint64_t)xform->alg << 5) |
326 : 0 : ((uint64_t)xform->rx_secy.preserve_sectag << 4) |
327 : 0 : ((uint64_t)xform->rx_secy.preserve_icv << 3) |
328 : 0 : ((uint64_t)xform->rx_secy.validate_frames << 1) |
329 : 0 : (uint64_t)xform->rx_secy.ctrl_port_enable;
330 : : }
331 : :
332 : 0 : ret = roc_mcs_secy_policy_write(mcs_dev->mdev, &req);
333 [ # # ]: 0 : if (ret) {
334 : 0 : plt_err(" Failed to configure Tx SECY");
335 : 0 : return -EINVAL;
336 : : }
337 : :
338 [ # # ]: 0 : if (xform->dir == RTE_SECURITY_MACSEC_DIR_RX) {
339 : 0 : struct roc_mcs_rx_sc_cam_write_req rx_sc_cam = {0};
340 : :
341 : 0 : rx_sc_cam.sci = xform->sci;
342 : 0 : rx_sc_cam.secy_id = secy_id & 0x3F;
343 : 0 : rx_sc_cam.sc_id = xform->sc_id;
344 : 0 : ret = roc_mcs_rx_sc_cam_write(mcs_dev->mdev, &rx_sc_cam);
345 [ # # ]: 0 : if (ret) {
346 : 0 : plt_err(" Failed to write rx_sc_cam");
347 : 0 : return -EINVAL;
348 : : }
349 : : }
350 : 0 : macsec_sess_priv->sci = xform->sci;
351 : 0 : macsec_sess_priv->sc_id = xform->sc_id;
352 : 0 : macsec_sess_priv->secy_id = secy_id;
353 : 0 : macsec_sess_priv->dir = dir;
354 : 0 : macsec_sess_priv->sess = sess;
355 : :
356 : 0 : TAILQ_INSERT_TAIL(&dev->mcs_list, macsec_sess_priv, entry);
357 : :
358 : 0 : return 0;
359 : : }
360 : :
361 : : int
362 : 0 : cnxk_eth_macsec_session_destroy(struct cnxk_eth_dev *dev, struct rte_security_session *sess)
363 : : {
364 : 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
365 : 0 : struct roc_mcs_clear_stats stats_req = {0};
366 [ # # ]: 0 : struct roc_mcs_free_rsrc_req req = {0};
367 : : struct cnxk_macsec_sess *s;
368 : : int ret = 0;
369 : :
370 [ # # ]: 0 : if (!roc_feature_nix_has_macsec())
371 : : return -ENOTSUP;
372 : :
373 : : s = SECURITY_GET_SESS_PRIV(sess);
374 : :
375 : 0 : stats_req.type = CNXK_MCS_RSRC_TYPE_SECY;
376 : 0 : stats_req.id = s->secy_id;
377 : 0 : stats_req.dir = s->dir;
378 : : stats_req.all = 0;
379 : :
380 : 0 : ret = roc_mcs_stats_clear(mcs_dev->mdev, &stats_req);
381 [ # # ]: 0 : if (ret)
382 : 0 : plt_err("Failed to clear stats for SECY id %u, dir %u.", s->secy_id, s->dir);
383 : :
384 : 0 : req.rsrc_id = s->secy_id;
385 : 0 : req.dir = s->dir;
386 : 0 : req.rsrc_type = CNXK_MCS_RSRC_TYPE_SECY;
387 : :
388 : 0 : ret = roc_mcs_rsrc_free(mcs_dev->mdev, &req);
389 [ # # ]: 0 : if (ret)
390 : 0 : plt_err("Failed to free SC id.");
391 : :
392 [ # # ]: 0 : TAILQ_REMOVE(&dev->mcs_list, s, entry);
393 : :
394 : 0 : return ret;
395 : : }
396 : :
397 : : int
398 [ # # ]: 0 : cnxk_mcs_flow_configure(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr __rte_unused,
399 : : const struct rte_flow_item pattern[],
400 : : const struct rte_flow_action actions[],
401 : : struct rte_flow_error *error __rte_unused, void **mcs_flow)
402 : : {
403 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
404 : : const struct rte_flow_item_eth *eth_item = NULL;
405 [ # # ]: 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
406 : : struct roc_mcs_flowid_entry_write_req req;
407 : : struct cnxk_mcs_flow_opts opts = {0};
408 : : struct cnxk_macsec_sess *sess;
409 : : struct rte_ether_addr src;
410 : : struct rte_ether_addr dst;
411 : : int ret;
412 : : int i = 0;
413 : :
414 [ # # ]: 0 : if (!roc_feature_nix_has_macsec())
415 : : return -ENOTSUP;
416 : :
417 : 0 : sess = cnxk_eth_macsec_sess_get_by_sess(dev,
418 : 0 : (const struct rte_security_session *)actions->conf);
419 [ # # ]: 0 : if (sess == NULL)
420 : : return -EINVAL;
421 : :
422 : 0 : ret = mcs_resource_alloc(mcs_dev, sess->dir, &sess->flow_id, 1,
423 : : CNXK_MCS_RSRC_TYPE_FLOWID);
424 [ # # ]: 0 : if (ret) {
425 : 0 : plt_err("Failed to allocate FLow id.");
426 : 0 : return -ENOMEM;
427 : : }
428 : : memset(&req, 0, sizeof(struct roc_mcs_flowid_entry_write_req));
429 : 0 : req.sci = sess->sci;
430 : 0 : req.flow_id = sess->flow_id;
431 : 0 : req.secy_id = sess->secy_id;
432 : 0 : req.sc_id = sess->sc_id;
433 : 0 : req.ena = 1;
434 : : req.ctr_pkt = 0;
435 : 0 : req.dir = sess->dir;
436 : :
437 [ # # ]: 0 : while (pattern[i].type != RTE_FLOW_ITEM_TYPE_END) {
438 [ # # ]: 0 : if (pattern[i].type == RTE_FLOW_ITEM_TYPE_ETH)
439 : 0 : eth_item = pattern[i].spec;
440 : : else
441 : 0 : plt_err("Unhandled flow item : %d", pattern[i].type);
442 : 0 : i++;
443 : : }
444 [ # # ]: 0 : if (eth_item) {
445 : 0 : dst = eth_item->hdr.dst_addr;
446 : 0 : src = eth_item->hdr.src_addr;
447 : :
448 : : /* Find ways to fill opts */
449 : :
450 : 0 : req.data[0] =
451 : 0 : (uint64_t)dst.addr_bytes[0] << 40 | (uint64_t)dst.addr_bytes[1] << 32 |
452 : 0 : (uint64_t)dst.addr_bytes[2] << 24 | (uint64_t)dst.addr_bytes[3] << 16 |
453 : 0 : (uint64_t)dst.addr_bytes[4] << 8 | (uint64_t)dst.addr_bytes[5] |
454 : 0 : (uint64_t)src.addr_bytes[5] << 48 | (uint64_t)src.addr_bytes[4] << 56;
455 : 0 : req.data[1] = (uint64_t)src.addr_bytes[3] | (uint64_t)src.addr_bytes[2] << 8 |
456 : 0 : (uint64_t)src.addr_bytes[1] << 16 |
457 : 0 : (uint64_t)src.addr_bytes[0] << 24 |
458 : 0 : (uint64_t)eth_item->hdr.ether_type << 32 |
459 : : ((uint64_t)opts.outer_tag_id & 0xFFFF) << 48;
460 : 0 : req.data[2] = ((uint64_t)opts.outer_tag_id & 0xF0000) |
461 : : ((uint64_t)opts.outer_priority & 0xF) << 4 |
462 : : ((uint64_t)opts.second_outer_tag_id & 0xFFFFF) << 8 |
463 : : ((uint64_t)opts.second_outer_priority & 0xF) << 28 |
464 : : ((uint64_t)opts.bonus_data << 32) |
465 : : ((uint64_t)opts.tag_match_bitmap << 48) |
466 : : ((uint64_t)opts.packet_type & 0xF) << 56 |
467 : : ((uint64_t)opts.outer_vlan_type & 0x7) << 60 |
468 : : ((uint64_t)opts.inner_vlan_type & 0x1) << 63;
469 : 0 : req.data[3] = ((uint64_t)opts.inner_vlan_type & 0x6) >> 1 |
470 : : ((uint64_t)opts.num_tags & 0x7F) << 2 |
471 : : ((uint64_t)opts.flowid_user & 0x1F) << 9 |
472 : : ((uint64_t)opts.express & 1) << 14 |
473 : : ((uint64_t)opts.lmac_id & 0x1F) << 15;
474 : :
475 : 0 : req.mask[0] = 0x0;
476 : 0 : req.mask[1] = 0xFFFFFFFF00000000;
477 : 0 : req.mask[2] = 0xFFFFFFFFFFFFFFFF;
478 : 0 : req.mask[3] = 0xFFFFFFFFFFFFFFFF;
479 : :
480 : 0 : ret = roc_mcs_flowid_entry_write(mcs_dev->mdev, &req);
481 [ # # ]: 0 : if (ret)
482 : : return ret;
483 : 0 : *mcs_flow = (void *)(uintptr_t)actions->conf;
484 : : } else {
485 : 0 : plt_err("Flow not confirured");
486 : 0 : return -EINVAL;
487 : : }
488 : 0 : return 0;
489 : : }
490 : :
491 : : int
492 : 0 : cnxk_mcs_flow_destroy(struct cnxk_eth_dev *dev, void *flow)
493 : : {
494 : 0 : const struct cnxk_macsec_sess *s = cnxk_eth_macsec_sess_get_by_sess(dev, flow);
495 : 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
496 : 0 : struct roc_mcs_clear_stats stats_req = {0};
497 [ # # ]: 0 : struct roc_mcs_free_rsrc_req req = {0};
498 : : int ret = 0;
499 : :
500 [ # # ]: 0 : if (!roc_feature_nix_has_macsec())
501 : : return -ENOTSUP;
502 : :
503 [ # # ]: 0 : if (s == NULL)
504 : : return 0;
505 : :
506 : : stats_req.type = CNXK_MCS_RSRC_TYPE_FLOWID;
507 : 0 : stats_req.id = s->flow_id;
508 : 0 : stats_req.dir = s->dir;
509 : : stats_req.all = 0;
510 : :
511 : 0 : ret = roc_mcs_stats_clear(mcs_dev->mdev, &stats_req);
512 [ # # ]: 0 : if (ret)
513 : 0 : plt_err("Failed to clear stats for Flow id %u, dir %u.", s->flow_id, s->dir);
514 : :
515 : 0 : req.rsrc_id = s->flow_id;
516 : 0 : req.dir = s->dir;
517 : 0 : req.rsrc_type = CNXK_MCS_RSRC_TYPE_FLOWID;
518 : :
519 : 0 : ret = roc_mcs_rsrc_free(mcs_dev->mdev, &req);
520 [ # # ]: 0 : if (ret)
521 : 0 : plt_err("Failed to free flow_id: %d.", s->flow_id);
522 : :
523 : : return ret;
524 : : }
525 : :
526 : : int
527 : 0 : cnxk_eth_macsec_sa_stats_get(void *device, uint16_t sa_id, enum rte_security_macsec_direction dir,
528 : : struct rte_security_macsec_sa_stats *stats)
529 : : {
530 : : RTE_SET_USED(device);
531 : : RTE_SET_USED(sa_id);
532 : : RTE_SET_USED(dir);
533 : : RTE_SET_USED(stats);
534 : :
535 : 0 : return 0;
536 : : }
537 : :
538 : : int
539 [ # # ]: 0 : cnxk_eth_macsec_sc_stats_get(void *device, uint16_t sc_id, enum rte_security_macsec_direction dir,
540 : : struct rte_security_macsec_sc_stats *stats)
541 : : {
542 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
543 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
544 : 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
545 [ # # ]: 0 : struct roc_mcs_stats_req req = {0};
546 : :
547 [ # # ]: 0 : if (!roc_feature_nix_has_macsec())
548 : : return -ENOTSUP;
549 : :
550 : 0 : req.id = sc_id;
551 : 0 : req.dir = (dir == RTE_SECURITY_MACSEC_DIR_RX) ? MCS_RX : MCS_TX;
552 : :
553 : 0 : return roc_mcs_sc_stats_get(mcs_dev->mdev, &req, (struct roc_mcs_sc_stats *)stats);
554 : : }
555 : :
556 : : int
557 : 0 : cnxk_eth_macsec_session_stats_get(struct cnxk_eth_dev *dev, struct cnxk_macsec_sess *sess,
558 : : struct rte_security_stats *stats)
559 : : {
560 : 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
561 : 0 : struct roc_mcs_flowid_stats flow_stats = {0};
562 : 0 : struct roc_mcs_port_stats port_stats = {0};
563 [ # # ]: 0 : struct roc_mcs_stats_req req = {0};
564 : :
565 [ # # ]: 0 : if (!roc_feature_nix_has_macsec())
566 : : return -ENOTSUP;
567 : :
568 : 0 : req.id = sess->flow_id;
569 : 0 : req.dir = sess->dir;
570 : 0 : roc_mcs_flowid_stats_get(mcs_dev->mdev, &req, &flow_stats);
571 : 0 : plt_nix_dbg("******* FLOW_ID IDX[%u] STATS dir: %u********", sess->flow_id, sess->dir);
572 : 0 : plt_nix_dbg("TX: tcam_hit_cnt: 0x%" PRIx64, flow_stats.tcam_hit_cnt);
573 : :
574 : 0 : req.id = mcs_dev->port_id;
575 : 0 : req.dir = sess->dir;
576 : 0 : roc_mcs_port_stats_get(mcs_dev->mdev, &req, &port_stats);
577 : 0 : plt_nix_dbg("********** PORT[0] STATS ****************");
578 : 0 : plt_nix_dbg("RX tcam_miss_cnt: 0x%" PRIx64, port_stats.tcam_miss_cnt);
579 : 0 : plt_nix_dbg("RX parser_err_cnt: 0x%" PRIx64, port_stats.parser_err_cnt);
580 : 0 : plt_nix_dbg("RX preempt_err_cnt: 0x%" PRIx64, port_stats.preempt_err_cnt);
581 : 0 : plt_nix_dbg("RX sectag_insert_err_cnt: 0x%" PRIx64, port_stats.sectag_insert_err_cnt);
582 : :
583 : 0 : req.id = sess->secy_id;
584 : 0 : req.dir = sess->dir;
585 : :
586 : 0 : return roc_mcs_secy_stats_get(mcs_dev->mdev, &req,
587 : 0 : (struct roc_mcs_secy_stats *)(&stats->macsec));
588 : : }
589 : :
590 : : static int
591 : 0 : cnxk_mcs_event_cb(void *userdata, struct roc_mcs_event_desc *desc, void *cb_arg,
592 : : uint8_t port_id)
593 : : {
594 : 0 : struct rte_eth_event_macsec_desc d = {0};
595 : : struct cnxk_mcs_dev *mcs_dev = userdata;
596 : :
597 : 0 : d.metadata = (uint64_t)userdata;
598 : :
599 [ # # # # : 0 : switch (desc->type) {
# # ]
600 : 0 : case ROC_MCS_EVENT_SECTAG_VAL_ERR:
601 : 0 : d.type = RTE_ETH_EVENT_MACSEC_SECTAG_VAL_ERR;
602 [ # # # # : 0 : switch (desc->subtype) {
# # ]
603 : 0 : case ROC_MCS_EVENT_RX_SECTAG_V_EQ1:
604 : 0 : d.subtype = RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_V_EQ1;
605 : 0 : break;
606 : 0 : case ROC_MCS_EVENT_RX_SECTAG_E_EQ0_C_EQ1:
607 : 0 : d.subtype = RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_E_EQ0_C_EQ1;
608 : 0 : break;
609 : 0 : case ROC_MCS_EVENT_RX_SECTAG_SL_GTE48:
610 : 0 : d.subtype = RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_SL_GTE48;
611 : 0 : break;
612 : 0 : case ROC_MCS_EVENT_RX_SECTAG_ES_EQ1_SC_EQ1:
613 : 0 : d.subtype = RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_ES_EQ1_SC_EQ1;
614 : 0 : break;
615 : 0 : case ROC_MCS_EVENT_RX_SECTAG_SC_EQ1_SCB_EQ1:
616 : 0 : d.subtype = RTE_ETH_SUBEVENT_MACSEC_RX_SECTAG_SC_EQ1_SCB_EQ1;
617 : 0 : break;
618 : 0 : default:
619 : 0 : plt_err("Unknown MACsec sub event : %d", desc->subtype);
620 : : }
621 : : break;
622 : 0 : case ROC_MCS_EVENT_RX_SA_PN_HARD_EXP:
623 : 0 : d.type = RTE_ETH_EVENT_MACSEC_RX_SA_PN_HARD_EXP;
624 [ # # ]: 0 : if (mcs_dev->port_id != port_id)
625 : : return 0;
626 : : break;
627 : 0 : case ROC_MCS_EVENT_RX_SA_PN_SOFT_EXP:
628 : 0 : d.type = RTE_ETH_EVENT_MACSEC_RX_SA_PN_SOFT_EXP;
629 [ # # ]: 0 : if (mcs_dev->port_id != port_id)
630 : : return 0;
631 : : break;
632 : 0 : case ROC_MCS_EVENT_TX_SA_PN_HARD_EXP:
633 : 0 : d.type = RTE_ETH_EVENT_MACSEC_TX_SA_PN_HARD_EXP;
634 [ # # ]: 0 : if (mcs_dev->port_id != port_id)
635 : : return 0;
636 : : break;
637 : 0 : case ROC_MCS_EVENT_TX_SA_PN_SOFT_EXP:
638 : 0 : d.type = RTE_ETH_EVENT_MACSEC_TX_SA_PN_SOFT_EXP;
639 [ # # ]: 0 : if (mcs_dev->port_id != port_id)
640 : : return 0;
641 : : break;
642 : 0 : default:
643 : 0 : plt_err("Unknown MACsec event type: %d", desc->type);
644 : : }
645 : :
646 : 0 : rte_eth_dev_callback_process(cb_arg, RTE_ETH_EVENT_MACSEC, &d);
647 : :
648 : 0 : return 0;
649 : : }
650 : :
651 : : void
652 : 0 : cnxk_mcs_dev_fini(struct cnxk_eth_dev *dev)
653 : : {
654 : 0 : struct cnxk_mcs_dev *mcs_dev = dev->mcs_dev;
655 : : int rc;
656 : :
657 : 0 : rc = roc_mcs_event_cb_unregister(mcs_dev->mdev, ROC_MCS_EVENT_SECTAG_VAL_ERR);
658 [ # # ]: 0 : if (rc)
659 : 0 : plt_err("Failed to unregister MCS event callback: rc: %d", rc);
660 : :
661 : 0 : rc = roc_mcs_event_cb_unregister(mcs_dev->mdev, ROC_MCS_EVENT_TX_SA_PN_SOFT_EXP);
662 [ # # ]: 0 : if (rc)
663 : 0 : plt_err("Failed to unregister MCS event callback: rc: %d", rc);
664 : :
665 : 0 : rc = roc_mcs_event_cb_unregister(mcs_dev->mdev, ROC_MCS_EVENT_RX_SA_PN_SOFT_EXP);
666 [ # # ]: 0 : if (rc)
667 : 0 : plt_err("Failed to unregister MCS event callback: rc: %d", rc);
668 : :
669 : : /* Cleanup MACsec dev */
670 : 0 : roc_mcs_dev_fini(mcs_dev->mdev);
671 : :
672 : 0 : plt_free(mcs_dev);
673 : 0 : }
674 : :
675 : : int
676 : 0 : cnxk_mcs_dev_init(struct cnxk_eth_dev *dev, uint8_t mcs_idx)
677 : : {
678 : 0 : struct roc_mcs_intr_cfg intr_cfg = {0};
679 : 0 : struct roc_mcs_hw_info hw_info = {0};
680 : : struct cnxk_mcs_dev *mcs_dev;
681 : : int rc;
682 : :
683 : 0 : rc = roc_mcs_hw_info_get(&hw_info);
684 [ # # ]: 0 : if (rc) {
685 : 0 : plt_err("MCS HW info get failed: rc: %d ", rc);
686 : 0 : return rc;
687 : : }
688 : :
689 : 0 : mcs_dev = plt_zmalloc(sizeof(struct cnxk_mcs_dev), PLT_CACHE_LINE_SIZE);
690 [ # # ]: 0 : if (!mcs_dev)
691 : : return -ENOMEM;
692 : :
693 : 0 : mcs_dev->idx = mcs_idx;
694 : 0 : mcs_dev->mdev = roc_mcs_dev_init(mcs_dev->idx);
695 [ # # ]: 0 : if (!mcs_dev->mdev) {
696 : 0 : plt_free(mcs_dev);
697 : 0 : return rc;
698 : : }
699 : 0 : mcs_dev->port_id = dev->eth_dev->data->port_id;
700 : :
701 : 0 : intr_cfg.intr_mask =
702 : : ROC_MCS_CPM_RX_SECTAG_V_EQ1_INT | ROC_MCS_CPM_RX_SECTAG_E_EQ0_C_EQ1_INT |
703 : : ROC_MCS_CPM_RX_SECTAG_SL_GTE48_INT | ROC_MCS_CPM_RX_SECTAG_ES_EQ1_SC_EQ1_INT |
704 : : ROC_MCS_CPM_RX_SECTAG_SC_EQ1_SCB_EQ1_INT | ROC_MCS_CPM_RX_PACKET_XPN_EQ0_INT |
705 : : ROC_MCS_CPM_RX_PN_THRESH_REACHED_INT | ROC_MCS_CPM_TX_PACKET_XPN_EQ0_INT |
706 : : ROC_MCS_CPM_TX_PN_THRESH_REACHED_INT | ROC_MCS_CPM_TX_SA_NOT_VALID_INT |
707 : : ROC_MCS_BBE_RX_DFIFO_OVERFLOW_INT | ROC_MCS_BBE_RX_PLFIFO_OVERFLOW_INT |
708 : : ROC_MCS_BBE_TX_DFIFO_OVERFLOW_INT | ROC_MCS_BBE_TX_PLFIFO_OVERFLOW_INT |
709 : : ROC_MCS_PAB_RX_CHAN_OVERFLOW_INT | ROC_MCS_PAB_TX_CHAN_OVERFLOW_INT;
710 : :
711 : 0 : rc = roc_mcs_intr_configure(mcs_dev->mdev, &intr_cfg);
712 [ # # ]: 0 : if (rc) {
713 : 0 : plt_err("Failed to configure MCS interrupts: rc: %d", rc);
714 : 0 : plt_free(mcs_dev);
715 : 0 : return rc;
716 : : }
717 : :
718 : 0 : rc = roc_mcs_event_cb_register(mcs_dev->mdev, ROC_MCS_EVENT_SECTAG_VAL_ERR,
719 : 0 : cnxk_mcs_event_cb, dev->eth_dev, mcs_dev);
720 [ # # ]: 0 : if (rc) {
721 : 0 : plt_err("Failed to register MCS event callback: rc: %d", rc);
722 : 0 : plt_free(mcs_dev);
723 : 0 : return rc;
724 : : }
725 : 0 : rc = roc_mcs_event_cb_register(mcs_dev->mdev, ROC_MCS_EVENT_TX_SA_PN_SOFT_EXP,
726 : 0 : cnxk_mcs_event_cb, dev->eth_dev, mcs_dev);
727 [ # # ]: 0 : if (rc) {
728 : 0 : plt_err("Failed to register MCS event callback: rc: %d", rc);
729 : 0 : plt_free(mcs_dev);
730 : 0 : return rc;
731 : : }
732 : 0 : rc = roc_mcs_event_cb_register(mcs_dev->mdev, ROC_MCS_EVENT_RX_SA_PN_SOFT_EXP,
733 : 0 : cnxk_mcs_event_cb, dev->eth_dev, mcs_dev);
734 [ # # ]: 0 : if (rc) {
735 : 0 : plt_err("Failed to register MCS event callback: rc: %d", rc);
736 : 0 : plt_free(mcs_dev);
737 : 0 : return rc;
738 : : }
739 : 0 : dev->mcs_dev = mcs_dev;
740 : :
741 : 0 : return 0;
742 : : }
|