Commit 52812526 authored by David S. Miller's avatar David S. Miller

Merge branch 'nfp-ipsec-csum'

Simon Horman says:

====================
nfp: fix incorrect IPsec checksum handling

this short series resolves two problems with IPsec checksum handling
in the nfp driver.

* PATCH 1/3, 2/3: Correct setting of checksum flags.
  One patch for each of the nfd3 and nfdk datapaths.

* Patch 3/3: Correct configuration of NETIF_F_CSUM_MASK
  so that the stack does not unecessarily calculate csums for
  IPsec offload packets.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 84cba184 1cf78d4c
...@@ -324,14 +324,15 @@ netdev_tx_t nfp_nfd3_tx(struct sk_buff *skb, struct net_device *netdev) ...@@ -324,14 +324,15 @@ netdev_tx_t nfp_nfd3_tx(struct sk_buff *skb, struct net_device *netdev)
/* Do not reorder - tso may adjust pkt cnt, vlan may override fields */ /* Do not reorder - tso may adjust pkt cnt, vlan may override fields */
nfp_nfd3_tx_tso(r_vec, txbuf, txd, skb, md_bytes); nfp_nfd3_tx_tso(r_vec, txbuf, txd, skb, md_bytes);
if (ipsec)
nfp_nfd3_ipsec_tx(txd, skb);
else
nfp_nfd3_tx_csum(dp, r_vec, txbuf, txd, skb); nfp_nfd3_tx_csum(dp, r_vec, txbuf, txd, skb);
if (skb_vlan_tag_present(skb) && dp->ctrl & NFP_NET_CFG_CTRL_TXVLAN) { if (skb_vlan_tag_present(skb) && dp->ctrl & NFP_NET_CFG_CTRL_TXVLAN) {
txd->flags |= NFD3_DESC_TX_VLAN; txd->flags |= NFD3_DESC_TX_VLAN;
txd->vlan = cpu_to_le16(skb_vlan_tag_get(skb)); txd->vlan = cpu_to_le16(skb_vlan_tag_get(skb));
} }
if (ipsec)
nfp_nfd3_ipsec_tx(txd, skb);
/* Gather DMA */ /* Gather DMA */
if (nr_frags > 0) { if (nr_frags > 0) {
__le64 second_half; __le64 second_half;
......
...@@ -10,9 +10,30 @@ ...@@ -10,9 +10,30 @@
void nfp_nfd3_ipsec_tx(struct nfp_nfd3_tx_desc *txd, struct sk_buff *skb) void nfp_nfd3_ipsec_tx(struct nfp_nfd3_tx_desc *txd, struct sk_buff *skb)
{ {
struct xfrm_state *x = xfrm_input_state(skb); struct xfrm_state *x = xfrm_input_state(skb);
struct xfrm_offload *xo = xfrm_offload(skb);
struct iphdr *iph = ip_hdr(skb);
int l4_proto;
if (x->xso.dev && (x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM)) { if (x->xso.dev && (x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM)) {
txd->flags |= NFD3_DESC_TX_CSUM | NFD3_DESC_TX_IP4_CSUM | txd->flags |= NFD3_DESC_TX_CSUM;
NFD3_DESC_TX_TCP_CSUM | NFD3_DESC_TX_UDP_CSUM;
if (iph->version == 4)
txd->flags |= NFD3_DESC_TX_IP4_CSUM;
if (x->props.mode == XFRM_MODE_TRANSPORT)
l4_proto = xo->proto;
else if (x->props.mode == XFRM_MODE_TUNNEL)
l4_proto = xo->inner_ipproto;
else
return;
switch (l4_proto) {
case IPPROTO_UDP:
txd->flags |= NFD3_DESC_TX_UDP_CSUM;
return;
case IPPROTO_TCP:
txd->flags |= NFD3_DESC_TX_TCP_CSUM;
return;
}
} }
} }
...@@ -387,6 +387,7 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev) ...@@ -387,6 +387,7 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev)
if (!skb_is_gso(skb)) { if (!skb_is_gso(skb)) {
real_len = skb->len; real_len = skb->len;
/* Metadata desc */ /* Metadata desc */
if (!ipsec)
metadata = nfp_nfdk_tx_csum(dp, r_vec, 1, skb, metadata); metadata = nfp_nfdk_tx_csum(dp, r_vec, 1, skb, metadata);
txd->raw = cpu_to_le64(metadata); txd->raw = cpu_to_le64(metadata);
txd++; txd++;
...@@ -395,6 +396,7 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev) ...@@ -395,6 +396,7 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev)
(txd + 1)->raw = nfp_nfdk_tx_tso(r_vec, txbuf, skb); (txd + 1)->raw = nfp_nfdk_tx_tso(r_vec, txbuf, skb);
real_len = txbuf->real_len; real_len = txbuf->real_len;
/* Metadata desc */ /* Metadata desc */
if (!ipsec)
metadata = nfp_nfdk_tx_csum(dp, r_vec, txbuf->pkt_cnt, skb, metadata); metadata = nfp_nfdk_tx_csum(dp, r_vec, txbuf->pkt_cnt, skb, metadata);
txd->raw = cpu_to_le64(metadata); txd->raw = cpu_to_le64(metadata);
txd += 2; txd += 2;
......
...@@ -9,9 +9,13 @@ ...@@ -9,9 +9,13 @@
u64 nfp_nfdk_ipsec_tx(u64 flags, struct sk_buff *skb) u64 nfp_nfdk_ipsec_tx(u64 flags, struct sk_buff *skb)
{ {
struct xfrm_state *x = xfrm_input_state(skb); struct xfrm_state *x = xfrm_input_state(skb);
struct iphdr *iph = ip_hdr(skb);
if (x->xso.dev && (x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM)) if (x->xso.dev && (x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM)) {
flags |= NFDK_DESC_TX_L3_CSUM | NFDK_DESC_TX_L4_CSUM; if (iph->version == 4)
flags |= NFDK_DESC_TX_L3_CSUM;
flags |= NFDK_DESC_TX_L4_CSUM;
}
return flags; return flags;
} }
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <net/tls.h> #include <net/tls.h>
#include <net/vxlan.h> #include <net/vxlan.h>
#include <net/xdp_sock_drv.h> #include <net/xdp_sock_drv.h>
#include <net/xfrm.h>
#include "nfpcore/nfp_dev.h" #include "nfpcore/nfp_dev.h"
#include "nfpcore/nfp_nsp.h" #include "nfpcore/nfp_nsp.h"
...@@ -1897,6 +1898,9 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev, ...@@ -1897,6 +1898,9 @@ nfp_net_features_check(struct sk_buff *skb, struct net_device *dev,
features &= ~NETIF_F_GSO_MASK; features &= ~NETIF_F_GSO_MASK;
} }
if (xfrm_offload(skb))
return features;
/* VXLAN/GRE check */ /* VXLAN/GRE check */
switch (vlan_get_protocol(skb)) { switch (vlan_get_protocol(skb)) {
case htons(ETH_P_IP): case htons(ETH_P_IP):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment