]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(C) 2020 Marvell International Ltd. | |
3 | */ | |
4 | ||
5 | #ifndef __OTX2_ETHDEV_SEC_TX_H__ | |
6 | #define __OTX2_ETHDEV_SEC_TX_H__ | |
7 | ||
8 | #include <rte_security.h> | |
9 | #include <rte_mbuf.h> | |
10 | ||
11 | #include "otx2_ethdev_sec.h" | |
12 | ||
13 | struct otx2_ipsec_fp_out_hdr { | |
14 | uint32_t ip_id; | |
15 | uint32_t seq; | |
16 | uint8_t iv[16]; | |
17 | }; | |
18 | ||
19 | static __rte_always_inline int32_t | |
20 | otx2_ipsec_fp_out_rlen_get(struct otx2_sec_session_ipsec_ip *sess, | |
21 | uint32_t plen) | |
22 | { | |
23 | uint32_t enc_payload_len; | |
24 | ||
25 | enc_payload_len = RTE_ALIGN_CEIL(plen + sess->roundup_len, | |
26 | sess->roundup_byte); | |
27 | ||
28 | return sess->partial_len + enc_payload_len; | |
29 | } | |
30 | ||
31 | static __rte_always_inline void | |
32 | otx2_ssogws_head_wait(struct otx2_ssogws *ws); | |
33 | ||
34 | static __rte_always_inline int | |
35 | otx2_sec_event_tx(struct otx2_ssogws *ws, struct rte_event *ev, | |
36 | struct rte_mbuf *m, const struct otx2_eth_txq *txq, | |
37 | const uint32_t offload_flags) | |
38 | { | |
39 | uint32_t dlen, rlen, desc_headroom, extend_head, extend_tail; | |
40 | struct otx2_sec_session_ipsec_ip *sess; | |
41 | struct otx2_ipsec_fp_out_hdr *hdr; | |
42 | struct otx2_ipsec_fp_out_sa *sa; | |
43 | uint64_t data_addr, desc_addr; | |
44 | struct otx2_sec_session *priv; | |
45 | struct otx2_cpt_inst_s inst; | |
46 | uint64_t lmt_status; | |
47 | char *data; | |
48 | ||
49 | struct desc { | |
50 | struct otx2_cpt_res cpt_res __rte_aligned(OTX2_CPT_RES_ALIGN); | |
51 | struct nix_send_hdr_s nix_hdr | |
52 | __rte_aligned(OTX2_NIX_SEND_DESC_ALIGN); | |
53 | union nix_send_sg_s nix_sg; | |
54 | struct nix_iova_s nix_iova; | |
55 | } *sd; | |
56 | ||
57 | priv = get_sec_session_private_data((void *)(m->udata64)); | |
58 | sess = &priv->ipsec.ip; | |
59 | sa = &sess->out_sa; | |
60 | ||
61 | RTE_ASSERT(sess->cpt_lmtline != NULL); | |
62 | RTE_ASSERT(!(offload_flags & (NIX_TX_OFFLOAD_MBUF_NOFF_F | | |
63 | NIX_TX_OFFLOAD_VLAN_QINQ_F))); | |
64 | ||
65 | dlen = rte_pktmbuf_pkt_len(m) + sizeof(*hdr) - RTE_ETHER_HDR_LEN; | |
66 | rlen = otx2_ipsec_fp_out_rlen_get(sess, dlen - sizeof(*hdr)); | |
67 | ||
68 | RTE_BUILD_BUG_ON(OTX2_CPT_RES_ALIGN % OTX2_NIX_SEND_DESC_ALIGN); | |
69 | RTE_BUILD_BUG_ON(sizeof(sd->cpt_res) % OTX2_NIX_SEND_DESC_ALIGN); | |
70 | ||
71 | extend_head = sizeof(*hdr); | |
72 | extend_tail = rlen - dlen; | |
73 | ||
74 | desc_headroom = (OTX2_CPT_RES_ALIGN - 1) + sizeof(*sd); | |
75 | ||
76 | if (unlikely(!rte_pktmbuf_is_contiguous(m)) || | |
77 | unlikely(rte_pktmbuf_headroom(m) < extend_head + desc_headroom) || | |
78 | unlikely(rte_pktmbuf_tailroom(m) < extend_tail)) { | |
79 | goto drop; | |
80 | } | |
81 | ||
82 | /* | |
83 | * Extend mbuf data to point to the expected packet buffer for NIX. | |
84 | * This includes the Ethernet header followed by the encrypted IPsec | |
85 | * payload | |
86 | */ | |
87 | rte_pktmbuf_append(m, extend_tail); | |
88 | data = rte_pktmbuf_prepend(m, extend_head); | |
89 | data_addr = rte_pktmbuf_mtophys(m); | |
90 | ||
91 | /* | |
92 | * Move the Ethernet header, to insert otx2_ipsec_fp_out_hdr prior | |
93 | * to the IP header | |
94 | */ | |
95 | memcpy(data, data + sizeof(*hdr), RTE_ETHER_HDR_LEN); | |
96 | ||
97 | hdr = (struct otx2_ipsec_fp_out_hdr *)(data + RTE_ETHER_HDR_LEN); | |
98 | ||
99 | if (sa->ctl.enc_type == OTX2_IPSEC_FP_SA_ENC_AES_GCM) { | |
100 | /* AES-128-GCM */ | |
101 | memcpy(hdr->iv, &sa->nonce, 4); | |
102 | memset(hdr->iv + 4, 0, 12); //TODO: make it random | |
103 | } else { | |
104 | /* AES-128-[CBC] + [SHA1] */ | |
105 | memset(hdr->iv, 0, 16); //TODO: make it random | |
106 | } | |
107 | ||
108 | /* Keep CPT result and NIX send descriptors in headroom */ | |
109 | sd = (void *)RTE_PTR_ALIGN(data - desc_headroom, OTX2_CPT_RES_ALIGN); | |
110 | desc_addr = data_addr - RTE_PTR_DIFF(data, sd); | |
111 | ||
112 | /* Prepare CPT instruction */ | |
113 | ||
114 | inst.nixtx_addr = (desc_addr + offsetof(struct desc, nix_hdr)) >> 4; | |
115 | inst.doneint = 0; | |
116 | inst.nixtxl = 1; | |
117 | inst.res_addr = desc_addr + offsetof(struct desc, cpt_res); | |
118 | inst.u64[2] = 0; | |
119 | inst.u64[3] = 0; | |
120 | inst.wqe_ptr = desc_addr >> 3; /* FIXME: Handle errors */ | |
121 | inst.qord = 1; | |
122 | inst.opcode = OTX2_CPT_OP_INLINE_IPSEC_OUTB; | |
123 | inst.dlen = dlen; | |
124 | inst.dptr = data_addr + RTE_ETHER_HDR_LEN; | |
125 | inst.u64[7] = sess->inst_w7; | |
126 | ||
127 | /* First word contains 8 bit completion code & 8 bit uc comp code */ | |
128 | sd->cpt_res.u16[0] = 0; | |
129 | ||
130 | /* Prepare NIX send descriptors for output expected from CPT */ | |
131 | ||
132 | sd->nix_hdr.w0.u = 0; | |
133 | sd->nix_hdr.w1.u = 0; | |
134 | sd->nix_hdr.w0.sq = txq->sq; | |
135 | sd->nix_hdr.w0.sizem1 = 1; | |
136 | sd->nix_hdr.w0.total = rte_pktmbuf_data_len(m); | |
137 | sd->nix_hdr.w0.aura = npa_lf_aura_handle_to_aura(m->pool->pool_id); | |
138 | ||
139 | sd->nix_sg.u = 0; | |
140 | sd->nix_sg.subdc = NIX_SUBDC_SG; | |
141 | sd->nix_sg.ld_type = NIX_SENDLDTYPE_LDD; | |
142 | sd->nix_sg.segs = 1; | |
143 | sd->nix_sg.seg1_size = rte_pktmbuf_data_len(m); | |
144 | ||
145 | sd->nix_iova.addr = rte_mbuf_data_iova(m); | |
146 | ||
147 | /* Mark mempool object as "put" since it is freed by NIX */ | |
148 | __mempool_check_cookies(m->pool, (void **)&m, 1, 0); | |
149 | ||
150 | if (!ev->sched_type) | |
151 | otx2_ssogws_head_wait(ws); | |
152 | ||
153 | inst.param1 = sess->esn_hi >> 16; | |
154 | inst.param2 = sess->esn_hi & 0xffff; | |
155 | ||
156 | hdr->seq = rte_cpu_to_be_32(sess->seq); | |
157 | hdr->ip_id = rte_cpu_to_be_32(sess->ip_id); | |
158 | ||
159 | sess->ip_id++; | |
160 | sess->esn++; | |
161 | ||
162 | rte_cio_wmb(); | |
163 | ||
164 | do { | |
165 | otx2_lmt_mov(sess->cpt_lmtline, &inst, 2); | |
166 | lmt_status = otx2_lmt_submit(sess->cpt_nq_reg); | |
167 | } while (lmt_status == 0); | |
168 | ||
169 | return 1; | |
170 | ||
171 | drop: | |
172 | if (offload_flags & NIX_TX_OFFLOAD_MBUF_NOFF_F) { | |
173 | /* Don't free if reference count > 1 */ | |
174 | if (rte_pktmbuf_prefree_seg(m) == NULL) | |
175 | return 0; | |
176 | } | |
177 | rte_pktmbuf_free(m); | |
178 | return 0; | |
179 | } | |
180 | ||
181 | #endif /* __OTX2_ETHDEV_SEC_TX_H__ */ |