if (!(adapter->netdev->features & NETIF_F_HW_ESP)) return;
/* reload the Rx and Tx keys */ for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) { struct rx_sa *r = &ipsec->rx_tbl[i]; struct tx_sa *t = &ipsec->tx_tbl[i]; int ret;
if (r->used) {
ret = ixgbevf_ipsec_set_pf_sa(adapter, r->xs); if (ret < 0)
netdev_err(netdev, "reload rx_tbl[%d] failed = %d\n",
i, ret);
}
if (t->used) {
ret = ixgbevf_ipsec_set_pf_sa(adapter, t->xs); if (ret < 0)
netdev_err(netdev, "reload tx_tbl[%d] failed = %d\n",
i, ret);
}
}
}
if (rxtable) { if (ipsec->num_rx_sa == IXGBE_IPSEC_MAX_SA_COUNT) return -ENOSPC;
/* search rx sa table */ for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) { if (!ipsec->rx_tbl[i].used) return i;
}
} else { if (ipsec->num_tx_sa == IXGBE_IPSEC_MAX_SA_COUNT) return -ENOSPC;
/* search tx sa table */ for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) { if (!ipsec->tx_tbl[i].used) return i;
}
}
if (strcmp(alg_name, aes_gcm_name)) {
netdev_err(dev, "Unsupported IPsec algorithm - please use %s\n",
aes_gcm_name); return -EINVAL;
}
/* The key bytes come down in a big endian array of bytes, so *wedon'tneedtodoanybyteswapping. *160accountsfor16bytekeyand4bytesalt
*/ if (key_len > IXGBE_IPSEC_KEY_BITS) {
*mysalt = ((u32 *)key_data)[4];
} elseif (key_len == IXGBE_IPSEC_KEY_BITS) {
*mysalt = 0;
} else {
netdev_err(dev, "IPsec hw offload only supports keys up to 128 bits with a 32 bit salt\n"); return -EINVAL;
}
memcpy(mykey, key_data, 16);
if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) { struct rx_sa rsa;
if (xs->calg) {
NL_SET_ERR_MSG_MOD(extack, "Compression offload not supported"); return -EINVAL;
}
/* find the first unused index */
ret = ixgbevf_ipsec_find_empty_idx(ipsec, true); if (ret < 0) {
NL_SET_ERR_MSG_MOD(extack, "No space for SA in Rx table!"); return ret;
}
sa_idx = (u16)ret;
if (rsa.xs->id.proto & IPPROTO_ESP)
rsa.decrypt = xs->ealg || xs->aead;
/* get the key and salt */
ret = ixgbevf_ipsec_parse_proto_keys(dev, xs, rsa.key,
&rsa.salt); if (ret) {
NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Rx SA table"); return ret;
}
/* get ip for rx sa table */ if (xs->props.family == AF_INET6)
memcpy(rsa.ipaddr, &xs->id.daddr.a6, 16); else
memcpy(&rsa.ipaddr[3], &xs->id.daddr.a4, 4);
rsa.mode = IXGBE_RXMOD_VALID; if (rsa.xs->id.proto & IPPROTO_ESP)
rsa.mode |= IXGBE_RXMOD_PROTO_ESP; if (rsa.decrypt)
rsa.mode |= IXGBE_RXMOD_DECRYPT; if (rsa.xs->props.family == AF_INET6)
rsa.mode |= IXGBE_RXMOD_IPV6;
ret = ixgbevf_ipsec_set_pf_sa(adapter, xs); if (ret < 0) return ret;
rsa.pfsa = ret;
/* the preparations worked, so save the info */
memcpy(&ipsec->rx_tbl[sa_idx], &rsa, sizeof(rsa));
/* hash the new entry for faster search in Rx path */
hash_add_rcu(ipsec->rx_sa_list, &ipsec->rx_tbl[sa_idx].hlist,
(__force u32)rsa.xs->id.spi);
} else { struct tx_sa tsa;
/* find the first unused index */
ret = ixgbevf_ipsec_find_empty_idx(ipsec, false); if (ret < 0) {
NL_SET_ERR_MSG_MOD(extack, "No space for SA in Tx table"); return ret;
}
sa_idx = (u16)ret;
if (xs->id.proto & IPPROTO_ESP)
tsa.encrypt = xs->ealg || xs->aead;
ret = ixgbevf_ipsec_parse_proto_keys(dev, xs, tsa.key,
&tsa.salt); if (ret) {
NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Tx SA table");
memset(&tsa, 0, sizeof(tsa)); return ret;
}
ret = ixgbevf_ipsec_set_pf_sa(adapter, xs); if (ret < 0) return ret;
tsa.pfsa = ret;
/* the preparations worked, so save the info */
memcpy(&ipsec->tx_tbl[sa_idx], &tsa, sizeof(tsa));
if (xs->id.proto == IPPROTO_ESP) {
itd->flags |= IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP |
IXGBE_ADVTXD_TUCMD_L4T_TCP; if (first->protocol == htons(ETH_P_IP))
itd->flags |= IXGBE_ADVTXD_TUCMD_IPV4;
/* The actual trailer length is authlen (16 bytes) plus *2bytesfortheprotoandthepadlenvalues,plus *padlenbytesofpadding.Thisendsupnotthesame *asthestaticvaluefoundinxs->props.trailer_len(21). * *...butifwe'redoingGSO,don'tbotherasthestack *doesn'taddatrailerforthose.
*/ if (!skb_is_gso(first->skb)) { /* The "correct" way to get the auth length would be *touse *authlen=crypto_aead_authsize(xs->data); *butsinceweknowweonlyhaveonesizetoworry *about*wecanletthecompilerusetheconstant *andsaveusafewCPUcycles.
*/ constint authlen = IXGBE_IPSEC_AUTH_BITS / 8; struct sk_buff *skb = first->skb;
u8 padlen; int ret;
ret = skb_copy_bits(skb, skb->len - (authlen + 2),
&padlen, 1); if (unlikely(ret)) return0;
itd->trailer_len = authlen + 2 + padlen;
}
} if (tsa->encrypt)
itd->flags |= IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.