[qca-nss-sfe] Use HW csum in TX if possible.
Change-Id: I7857b24e1fa0e240a41109b6c4ce0625293a8154
Signed-off-by: Ratheesh Kannoth <quic_rkannoth@quicinc.com>
diff --git a/sfe_ipv4_tcp.c b/sfe_ipv4_tcp.c
index df8df0c..b9dcdce 100644
--- a/sfe_ipv4_tcp.c
+++ b/sfe_ipv4_tcp.c
@@ -127,6 +127,7 @@
u32 flags;
struct net_device *xmit_dev;
bool ret;
+ bool hw_csum;
/*
* Is our packet too short to contain a valid UDP header?
@@ -496,6 +497,13 @@
iph->ttl = ttl - 1;
/*
+ * Enable HW csum if rx checksum is verified and xmit interface is CSUM offload capable.
+ * Note: If L4 csum at Rx was found to be incorrect, we (router) should use incremental L4 checksum here
+ * so that HW does not re-calculate/replace the L4 csum
+ */
+ hw_csum = !!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_CSUM_OFFLOAD) && (skb->ip_summed == CHECKSUM_UNNECESSARY);
+
+ /*
* Do we have to perform translations of the source address/port?
*/
if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) {
@@ -505,19 +513,17 @@
iph->saddr = cm->xlate_src_ip;
tcph->source = cm->xlate_src_port;
- /*
- * Do we have a non-zero UDP checksum? If we do then we need
- * to update it.
- */
- tcp_csum = tcph->check;
- if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) {
- sum = tcp_csum + cm->xlate_src_partial_csum_adjustment;
- } else {
- sum = tcp_csum + cm->xlate_src_csum_adjustment;
- }
+ if (unlikely(!hw_csum)) {
+ tcp_csum = tcph->check;
+ if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ sum = tcp_csum + cm->xlate_src_partial_csum_adjustment;
+ } else {
+ sum = tcp_csum + cm->xlate_src_csum_adjustment;
+ }
- sum = (sum & 0xffff) + (sum >> 16);
- tcph->check = (u16)sum;
+ sum = (sum & 0xffff) + (sum >> 16);
+ tcph->check = (u16)sum;
+ }
}
/*
@@ -530,25 +536,30 @@
iph->daddr = cm->xlate_dest_ip;
tcph->dest = cm->xlate_dest_port;
- /*
- * Do we have a non-zero UDP checksum? If we do then we need
- * to update it.
- */
- tcp_csum = tcph->check;
- if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) {
- sum = tcp_csum + cm->xlate_dest_partial_csum_adjustment;
- } else {
- sum = tcp_csum + cm->xlate_dest_csum_adjustment;
- }
+ if (unlikely(!hw_csum)) {
+ tcp_csum = tcph->check;
+ if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ sum = tcp_csum + cm->xlate_dest_partial_csum_adjustment;
+ } else {
+ sum = tcp_csum + cm->xlate_dest_csum_adjustment;
+ }
- sum = (sum & 0xffff) + (sum >> 16);
- tcph->check = (u16)sum;
+ sum = (sum & 0xffff) + (sum >> 16);
+ tcph->check = (u16)sum;
+ }
}
/*
- * Replace the IP checksum.
+ * If HW checksum offload is not possible, full L3 checksum and incremental L4 checksum
+ * are used to update the packet. Setting ip_summed to CHECKSUM_UNNECESSARY ensures checksum is
+ * not recalculated further in packet path.
*/
- iph->check = sfe_ipv4_gen_ip_csum(iph);
+ if (likely(hw_csum)) {
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ } else {
+ iph->check = sfe_ipv4_gen_ip_csum(iph);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
/*
* Update traffic stats.