|
4 | 4 | #include <linux/bpf_trace.h> |
5 | 5 | #include <linux/netdevice.h> |
6 | 6 | #include <linux/bitfield.h> |
| 7 | +#include <net/xfrm.h> |
7 | 8 |
|
8 | 9 | #include "../nfp_app.h" |
9 | 10 | #include "../nfp_net.h" |
@@ -167,28 +168,34 @@ nfp_nfd3_tx_csum(struct nfp_net_dp *dp, struct nfp_net_r_vector *r_vec, |
167 | 168 | u64_stats_update_end(&r_vec->tx_sync); |
168 | 169 | } |
169 | 170 |
|
170 | | -static int nfp_nfd3_prep_tx_meta(struct nfp_net_dp *dp, struct sk_buff *skb, u64 tls_handle) |
| 171 | +static int nfp_nfd3_prep_tx_meta(struct nfp_net_dp *dp, struct sk_buff *skb, |
| 172 | + u64 tls_handle, bool *ipsec) |
171 | 173 | { |
172 | 174 | struct metadata_dst *md_dst = skb_metadata_dst(skb); |
| 175 | + struct nfp_ipsec_offload offload_info; |
173 | 176 | unsigned char *data; |
174 | 177 | bool vlan_insert; |
175 | 178 | u32 meta_id = 0; |
176 | 179 | int md_bytes; |
177 | 180 |
|
178 | | - if (unlikely(md_dst || tls_handle)) { |
179 | | - if (unlikely(md_dst && md_dst->type != METADATA_HW_PORT_MUX)) |
180 | | - md_dst = NULL; |
181 | | - } |
| 181 | +#ifdef CONFIG_NFP_NET_IPSEC |
| 182 | + if (xfrm_offload(skb)) |
| 183 | + *ipsec = nfp_net_ipsec_tx_prep(dp, skb, &offload_info); |
| 184 | +#endif |
| 185 | + |
| 186 | + if (unlikely(md_dst && md_dst->type != METADATA_HW_PORT_MUX)) |
| 187 | + md_dst = NULL; |
182 | 188 |
|
183 | 189 | vlan_insert = skb_vlan_tag_present(skb) && (dp->ctrl & NFP_NET_CFG_CTRL_TXVLAN_V2); |
184 | 190 |
|
185 | | - if (!(md_dst || tls_handle || vlan_insert)) |
| 191 | + if (!(md_dst || tls_handle || vlan_insert || *ipsec)) |
186 | 192 | return 0; |
187 | 193 |
|
188 | 194 | md_bytes = sizeof(meta_id) + |
189 | 195 | !!md_dst * NFP_NET_META_PORTID_SIZE + |
190 | 196 | !!tls_handle * NFP_NET_META_CONN_HANDLE_SIZE + |
191 | | - vlan_insert * NFP_NET_META_VLAN_SIZE; |
| 197 | + vlan_insert * NFP_NET_META_VLAN_SIZE + |
| 198 | + *ipsec * NFP_NET_META_IPSEC_FIELD_SIZE; /* IPsec has 12 bytes of metadata */ |
192 | 199 |
|
193 | 200 | if (unlikely(skb_cow_head(skb, md_bytes))) |
194 | 201 | return -ENOMEM; |
@@ -218,6 +225,19 @@ static int nfp_nfd3_prep_tx_meta(struct nfp_net_dp *dp, struct sk_buff *skb, u64 |
218 | 225 | meta_id <<= NFP_NET_META_FIELD_SIZE; |
219 | 226 | meta_id |= NFP_NET_META_VLAN; |
220 | 227 | } |
| 228 | + if (*ipsec) { |
| 229 | + /* IPsec has three consecutive 4-bit IPsec metadata types, |
| 230 | + * so in total IPsec has three 4 bytes of metadata. |
| 231 | + */ |
| 232 | + data -= NFP_NET_META_IPSEC_SIZE; |
| 233 | + put_unaligned_be32(offload_info.seq_hi, data); |
| 234 | + data -= NFP_NET_META_IPSEC_SIZE; |
| 235 | + put_unaligned_be32(offload_info.seq_low, data); |
| 236 | + data -= NFP_NET_META_IPSEC_SIZE; |
| 237 | + put_unaligned_be32(offload_info.handle - 1, data); |
| 238 | + meta_id <<= NFP_NET_META_IPSEC_FIELD_SIZE; |
| 239 | + meta_id |= NFP_NET_META_IPSEC << 8 | NFP_NET_META_IPSEC << 4 | NFP_NET_META_IPSEC; |
| 240 | + } |
221 | 241 |
|
222 | 242 | data -= sizeof(meta_id); |
223 | 243 | put_unaligned_be32(meta_id, data); |
@@ -246,6 +266,7 @@ netdev_tx_t nfp_nfd3_tx(struct sk_buff *skb, struct net_device *netdev) |
246 | 266 | dma_addr_t dma_addr; |
247 | 267 | unsigned int fsize; |
248 | 268 | u64 tls_handle = 0; |
| 269 | + bool ipsec = false; |
249 | 270 | u16 qidx; |
250 | 271 |
|
251 | 272 | dp = &nn->dp; |
@@ -273,7 +294,7 @@ netdev_tx_t nfp_nfd3_tx(struct sk_buff *skb, struct net_device *netdev) |
273 | 294 | return NETDEV_TX_OK; |
274 | 295 | } |
275 | 296 |
|
276 | | - md_bytes = nfp_nfd3_prep_tx_meta(dp, skb, tls_handle); |
| 297 | + md_bytes = nfp_nfd3_prep_tx_meta(dp, skb, tls_handle, &ipsec); |
277 | 298 | if (unlikely(md_bytes < 0)) |
278 | 299 | goto err_flush; |
279 | 300 |
|
@@ -312,6 +333,8 @@ netdev_tx_t nfp_nfd3_tx(struct sk_buff *skb, struct net_device *netdev) |
312 | 333 | txd->vlan = cpu_to_le16(skb_vlan_tag_get(skb)); |
313 | 334 | } |
314 | 335 |
|
| 336 | + if (ipsec) |
| 337 | + nfp_nfd3_ipsec_tx(txd, skb); |
315 | 338 | /* Gather DMA */ |
316 | 339 | if (nr_frags > 0) { |
317 | 340 | __le64 second_half; |
@@ -764,6 +787,15 @@ nfp_nfd3_parse_meta(struct net_device *netdev, struct nfp_meta_parsed *meta, |
764 | 787 | return false; |
765 | 788 | data += sizeof(struct nfp_net_tls_resync_req); |
766 | 789 | break; |
| 790 | +#ifdef CONFIG_NFP_NET_IPSEC |
| 791 | + case NFP_NET_META_IPSEC: |
| 792 | + /* Note: IPsec packet will have zero saidx, so need add 1 |
| 793 | + * to indicate packet is IPsec packet within driver. |
| 794 | + */ |
| 795 | + meta->ipsec_saidx = get_unaligned_be32(data) + 1; |
| 796 | + data += 4; |
| 797 | + break; |
| 798 | +#endif |
767 | 799 | default: |
768 | 800 | return true; |
769 | 801 | } |
@@ -876,12 +908,11 @@ static int nfp_nfd3_rx(struct nfp_net_rx_ring *rx_ring, int budget) |
876 | 908 | struct nfp_net_dp *dp = &r_vec->nfp_net->dp; |
877 | 909 | struct nfp_net_tx_ring *tx_ring; |
878 | 910 | struct bpf_prog *xdp_prog; |
| 911 | + int idx, pkts_polled = 0; |
879 | 912 | bool xdp_tx_cmpl = false; |
880 | 913 | unsigned int true_bufsz; |
881 | 914 | struct sk_buff *skb; |
882 | | - int pkts_polled = 0; |
883 | 915 | struct xdp_buff xdp; |
884 | | - int idx; |
885 | 916 |
|
886 | 917 | xdp_prog = READ_ONCE(dp->xdp_prog); |
887 | 918 | true_bufsz = xdp_prog ? PAGE_SIZE : dp->fl_bufsz; |
@@ -1081,6 +1112,13 @@ static int nfp_nfd3_rx(struct nfp_net_rx_ring *rx_ring, int budget) |
1081 | 1112 | continue; |
1082 | 1113 | } |
1083 | 1114 |
|
| 1115 | +#ifdef CONFIG_NFP_NET_IPSEC |
| 1116 | + if (meta.ipsec_saidx != 0 && unlikely(nfp_net_ipsec_rx(&meta, skb))) { |
| 1117 | + nfp_nfd3_rx_drop(dp, r_vec, rx_ring, NULL, skb); |
| 1118 | + continue; |
| 1119 | + } |
| 1120 | +#endif |
| 1121 | + |
1084 | 1122 | if (meta_len_xdp) |
1085 | 1123 | skb_metadata_set(skb, meta_len_xdp); |
1086 | 1124 |
|
|
0 commit comments