Skip to content

Commit 5925947

Browse files
Shannon NelsonJeff Kirsher
authored andcommitted
ixgbe: process the Tx ipsec offload
If the skb has a security association referenced in the skb, then set up the Tx descriptor with the ipsec offload bits. While we're here, we fix an oddly named field in the context descriptor struct. Signed-off-by: Shannon Nelson <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 9210319 commit 5925947

File tree

5 files changed

+112
-9
lines changed

5 files changed

+112
-9
lines changed

drivers/net/ethernet/intel/ixgbe/ixgbe.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,11 @@ enum ixgbe_tx_flags {
172172
IXGBE_TX_FLAGS_CC = 0x08,
173173
IXGBE_TX_FLAGS_IPV4 = 0x10,
174174
IXGBE_TX_FLAGS_CSUM = 0x20,
175+
IXGBE_TX_FLAGS_IPSEC = 0x40,
175176

176177
/* software defined flags */
177-
IXGBE_TX_FLAGS_SW_VLAN = 0x40,
178-
IXGBE_TX_FLAGS_FCOE = 0x80,
178+
IXGBE_TX_FLAGS_SW_VLAN = 0x80,
179+
IXGBE_TX_FLAGS_FCOE = 0x100,
179180
};
180181

181182
/* VLAN info */
@@ -1024,12 +1025,17 @@ void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter);
10241025
void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
10251026
union ixgbe_adv_rx_desc *rx_desc,
10261027
struct sk_buff *skb);
1028+
int ixgbe_ipsec_tx(struct ixgbe_ring *tx_ring, struct ixgbe_tx_buffer *first,
1029+
struct ixgbe_ipsec_tx_data *itd);
10271030
#else
10281031
static inline void ixgbe_init_ipsec_offload(struct ixgbe_adapter *adapter) { };
10291032
static inline void ixgbe_stop_ipsec_offload(struct ixgbe_adapter *adapter) { };
10301033
static inline void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter) { };
10311034
static inline void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
10321035
union ixgbe_adv_rx_desc *rx_desc,
10331036
struct sk_buff *skb) { };
1037+
static inline int ixgbe_ipsec_tx(struct ixgbe_ring *tx_ring,
1038+
struct ixgbe_tx_buffer *first,
1039+
struct ixgbe_ipsec_tx_data *itd) { return 0; };
10341040
#endif /* CONFIG_XFRM_OFFLOAD */
10351041
#endif /* _IXGBE_H_ */

drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,11 +698,90 @@ static void ixgbe_ipsec_del_sa(struct xfrm_state *xs)
698698
}
699699
}
700700

701+
/**
702+
* ixgbe_ipsec_offload_ok - can this packet use the xfrm hw offload
703+
* @skb: current data packet
704+
* @xs: pointer to transformer state struct
705+
**/
706+
static bool ixgbe_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
707+
{
708+
if (xs->props.family == AF_INET) {
709+
/* Offload with IPv4 options is not supported yet */
710+
if (ip_hdr(skb)->ihl != 5)
711+
return false;
712+
} else {
713+
/* Offload with IPv6 extension headers is not support yet */
714+
if (ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr))
715+
return false;
716+
}
717+
718+
return true;
719+
}
720+
701721
static const struct xfrmdev_ops ixgbe_xfrmdev_ops = {
702722
.xdo_dev_state_add = ixgbe_ipsec_add_sa,
703723
.xdo_dev_state_delete = ixgbe_ipsec_del_sa,
724+
.xdo_dev_offload_ok = ixgbe_ipsec_offload_ok,
704725
};
705726

727+
/**
728+
* ixgbe_ipsec_tx - setup Tx flags for ipsec offload
729+
* @tx_ring: outgoing context
730+
* @first: current data packet
731+
* @itd: ipsec Tx data for later use in building context descriptor
732+
**/
733+
int ixgbe_ipsec_tx(struct ixgbe_ring *tx_ring,
734+
struct ixgbe_tx_buffer *first,
735+
struct ixgbe_ipsec_tx_data *itd)
736+
{
737+
struct ixgbe_adapter *adapter = netdev_priv(tx_ring->netdev);
738+
struct ixgbe_ipsec *ipsec = adapter->ipsec;
739+
struct xfrm_state *xs;
740+
struct tx_sa *tsa;
741+
742+
if (unlikely(!first->skb->sp->len)) {
743+
netdev_err(tx_ring->netdev, "%s: no xfrm state len = %d\n",
744+
__func__, first->skb->sp->len);
745+
return 0;
746+
}
747+
748+
xs = xfrm_input_state(first->skb);
749+
if (unlikely(!xs)) {
750+
netdev_err(tx_ring->netdev, "%s: no xfrm_input_state() xs = %p\n",
751+
__func__, xs);
752+
return 0;
753+
}
754+
755+
itd->sa_idx = xs->xso.offload_handle - IXGBE_IPSEC_BASE_TX_INDEX;
756+
if (unlikely(itd->sa_idx > IXGBE_IPSEC_MAX_SA_COUNT)) {
757+
netdev_err(tx_ring->netdev, "%s: bad sa_idx=%d handle=%lu\n",
758+
__func__, itd->sa_idx, xs->xso.offload_handle);
759+
return 0;
760+
}
761+
762+
tsa = &ipsec->tx_tbl[itd->sa_idx];
763+
if (unlikely(!tsa->used)) {
764+
netdev_err(tx_ring->netdev, "%s: unused sa_idx=%d\n",
765+
__func__, itd->sa_idx);
766+
return 0;
767+
}
768+
769+
first->tx_flags |= IXGBE_TX_FLAGS_IPSEC | IXGBE_TX_FLAGS_CC;
770+
771+
itd->flags = 0;
772+
if (xs->id.proto == IPPROTO_ESP) {
773+
itd->flags |= IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP |
774+
IXGBE_ADVTXD_TUCMD_L4T_TCP;
775+
if (first->protocol == htons(ETH_P_IP))
776+
itd->flags |= IXGBE_ADVTXD_TUCMD_IPV4;
777+
itd->trailer_len = xs->props.trailer_len;
778+
}
779+
if (tsa->encrypt)
780+
itd->flags |= IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN;
781+
782+
return 1;
783+
}
784+
706785
/**
707786
* ixgbe_ipsec_rx - decode ipsec bits from Rx descriptor
708787
* @rx_ring: receiving ring

drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,7 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
12821282
}
12831283

12841284
void ixgbe_tx_ctxtdesc(struct ixgbe_ring *tx_ring, u32 vlan_macip_lens,
1285-
u32 fcoe_sof_eof, u32 type_tucmd, u32 mss_l4len_idx)
1285+
u32 fceof_saidx, u32 type_tucmd, u32 mss_l4len_idx)
12861286
{
12871287
struct ixgbe_adv_tx_context_desc *context_desc;
12881288
u16 i = tx_ring->next_to_use;
@@ -1296,7 +1296,7 @@ void ixgbe_tx_ctxtdesc(struct ixgbe_ring *tx_ring, u32 vlan_macip_lens,
12961296
type_tucmd |= IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
12971297

12981298
context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens);
1299-
context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof);
1299+
context_desc->fceof_saidx = cpu_to_le32(fceof_saidx);
13001300
context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd);
13011301
context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
13021302
}

drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7799,10 +7799,12 @@ static inline bool ixgbe_ipv6_csum_is_sctp(struct sk_buff *skb)
77997799
}
78007800

78017801
static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
7802-
struct ixgbe_tx_buffer *first)
7802+
struct ixgbe_tx_buffer *first,
7803+
struct ixgbe_ipsec_tx_data *itd)
78037804
{
78047805
struct sk_buff *skb = first->skb;
78057806
u32 vlan_macip_lens = 0;
7807+
u32 fceof_saidx = 0;
78067808
u32 type_tucmd = 0;
78077809

78087810
if (skb->ip_summed != CHECKSUM_PARTIAL) {
@@ -7843,7 +7845,12 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
78437845
vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
78447846
vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
78457847

7846-
ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0, type_tucmd, 0);
7848+
if (first->tx_flags & IXGBE_TX_FLAGS_IPSEC) {
7849+
fceof_saidx |= itd->sa_idx;
7850+
type_tucmd |= itd->flags | itd->trailer_len;
7851+
}
7852+
7853+
ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, fceof_saidx, type_tucmd, 0);
78477854
}
78487855

78497856
#define IXGBE_SET_FLAG(_input, _flag, _result) \
@@ -7886,11 +7893,16 @@ static void ixgbe_tx_olinfo_status(union ixgbe_adv_tx_desc *tx_desc,
78867893
IXGBE_TX_FLAGS_CSUM,
78877894
IXGBE_ADVTXD_POPTS_TXSM);
78887895

7889-
/* enble IPv4 checksum for TSO */
7896+
/* enable IPv4 checksum for TSO */
78907897
olinfo_status |= IXGBE_SET_FLAG(tx_flags,
78917898
IXGBE_TX_FLAGS_IPV4,
78927899
IXGBE_ADVTXD_POPTS_IXSM);
78937900

7901+
/* enable IPsec */
7902+
olinfo_status |= IXGBE_SET_FLAG(tx_flags,
7903+
IXGBE_TX_FLAGS_IPSEC,
7904+
IXGBE_ADVTXD_POPTS_IPSEC);
7905+
78947906
/*
78957907
* Check Context must be set if Tx switch is enabled, which it
78967908
* always is for case where virtual functions are running
@@ -8354,6 +8366,7 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
83548366
u32 tx_flags = 0;
83558367
unsigned short f;
83568368
u16 count = TXD_USE_COUNT(skb_headlen(skb));
8369+
struct ixgbe_ipsec_tx_data ipsec_tx = { 0 };
83578370
__be16 protocol = skb->protocol;
83588371
u8 hdr_len = 0;
83598372

@@ -8458,11 +8471,16 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
84588471
}
84598472

84608473
#endif /* IXGBE_FCOE */
8474+
8475+
#ifdef CONFIG_XFRM_OFFLOAD
8476+
if (skb->sp && !ixgbe_ipsec_tx(tx_ring, first, &ipsec_tx))
8477+
goto out_drop;
8478+
#endif
84618479
tso = ixgbe_tso(tx_ring, first, &hdr_len);
84628480
if (tso < 0)
84638481
goto out_drop;
84648482
else if (!tso)
8465-
ixgbe_tx_csum(tx_ring, first);
8483+
ixgbe_tx_csum(tx_ring, first, &ipsec_tx);
84668484

84678485
/* add the ATR filter if ATR is on */
84688486
if (test_bit(__IXGBE_TX_FDIR_INIT_DONE, &tx_ring->state))

drivers/net/ethernet/intel/ixgbe/ixgbe_type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2895,7 +2895,7 @@ union ixgbe_adv_rx_desc {
28952895
/* Context descriptors */
28962896
struct ixgbe_adv_tx_context_desc {
28972897
__le32 vlan_macip_lens;
2898-
__le32 seqnum_seed;
2898+
__le32 fceof_saidx;
28992899
__le32 type_tucmd_mlhl;
29002900
__le32 mss_l4len_idx;
29012901
};

0 commit comments

Comments
 (0)