Merge "[qca-nss-clients] Avoid fragmentation for wan to lan direction"
diff --git a/netlink/nss_nlgre_redir_cmd.c b/netlink/nss_nlgre_redir_cmd.c
index 3653bea..d9f8364 100644
--- a/netlink/nss_nlgre_redir_cmd.c
+++ b/netlink/nss_nlgre_redir_cmd.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2015-2016,2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016,2018-2020, The Linux Foundation. All rights reserved.
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * above copyright notice and this permission notice appear in all copies.
@@ -29,6 +29,8 @@
 #include "nss_nlgre_redir_cmd.h"
 #include "nss_nlgre_redir_cmn.h"
 #include "nss_nlgre_redir_lag.h"
+#include "nss_nlipv6_if.h"
+#include "nss_nlipv4_if.h"
 
 /*
  * To get lock on deploy_mode
@@ -425,10 +427,25 @@
  * nss_nlgre_redir_cmd_get_ifnum()
  * 	Get the interface number corresponding to netdev
  */
-int nss_nlgre_redir_cmd_get_ifnum(struct net_device* dev, enum nss_dynamic_interface_type type)
+int nss_nlgre_redir_cmd_get_ifnum(struct net_device *dev, uint8_t proto)
 {
+	enum nss_dynamic_interface_type type;
 	int ifnum;
 
+	switch (proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_UDPLITE:
+		type = NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_WIFI_OFFL_INNER;
+		break;
+	case IPPROTO_GRE:
+		type = NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER;
+		break;
+	default:
+		nss_nl_error("Invalid protocol %d\n", proto);
+		return -1;
+	}
+
 	/*
 	 * Get the interface number depending upon the dev and type
 	 */
@@ -441,3 +458,38 @@
 	return ifnum;
 }
 
+/*
+ * nss_nlgre_redir_cmd_get_mtu()
+ * 	Returns the mtu based on the device passed
+ */
+int nss_nlgre_redir_cmd_get_mtu(struct net_device *dev, uint8_t iptype, int ifnum)
+{
+	enum nss_dynamic_interface_type type;
+	struct nss_ctx_instance *nss_ctx;
+	int mtu = dev->mtu;
+
+	nss_ctx = nss_gre_redir_get_context();
+	type = nss_dynamic_interface_get_type(nss_ctx, ifnum);
+	switch (iptype) {
+	case NSS_GRE_REDIR_IP_HDR_TYPE_IPV4:
+		if (type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER) {
+			mtu = NSS_NLIPV4_MAX_MTU;
+		} else if (mtu < NSS_NLIPV4_MIN_MTU) {
+			mtu = NSS_NLIPV4_MIN_MTU;
+		}
+
+		break;
+	case NSS_GRE_REDIR_IP_HDR_TYPE_IPV6:
+		if (type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER) {
+			mtu = NSS_NLIPV6_MAX_MTU;
+		} else if (mtu < NSS_NLIPV6_MIN_MTU) {
+			mtu = NSS_NLIPV6_MIN_MTU;
+		}
+
+		break;
+	}
+
+	return mtu;
+}
+
+
diff --git a/netlink/nss_nlgre_redir_cmd.h b/netlink/nss_nlgre_redir_cmd.h
index 858f82a..9e759f0 100644
--- a/netlink/nss_nlgre_redir_cmd.h
+++ b/netlink/nss_nlgre_redir_cmd.h
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2014-2015,2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015,2019-2020, The Linux Foundation. All rights reserved.
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * above copyright notice and this permission notice appear in all copies.
@@ -46,6 +46,12 @@
  * nss_nlgre_redir_cmd_get_ifnum()
  * 	Get the interface number corresponding to netdev
  */
-int nss_nlgre_redir_cmd_get_ifnum(struct net_device* dev, enum nss_dynamic_interface_type type);
+int nss_nlgre_redir_cmd_get_ifnum(struct net_device *dev, uint8_t proto);
+
+/*
+ * nss_nlgre_redir_cmd_get_mtu()
+ * 	Returns the mtu based on the device passed
+ */
+int nss_nlgre_redir_cmd_get_mtu(struct net_device *dev, uint8_t iptype, int ifnum);
 
 #endif /* __NSS_NLGRE_REDIR_CMD_H */
diff --git a/netlink/nss_nlgre_redir_cmn.c b/netlink/nss_nlgre_redir_cmn.c
index f927a9d..7a1b7e0 100644
--- a/netlink/nss_nlgre_redir_cmn.c
+++ b/netlink/nss_nlgre_redir_cmn.c
@@ -135,14 +135,14 @@
 static void nss_nlgre_redir_cmn_host_data_cb(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi)
 {
 	struct nss_ctx_instance *nss_ctx = nss_gre_redir_get_context();
-	struct nss_gre_redir_decap_per_pkt_metadata *meta_data_decap = NULL;
 
 	if (!skb) {
 		nss_nl_trace("%p: SKB is NULL\n", nss_ctx);
 		return;
 	}
 
-	meta_data_decap = (struct nss_gre_redir_decap_per_pkt_metadata *)(skb->data - NSS_GRE_REDIR_PER_PACKET_METADATA_OFFSET);
+	nss_nl_trace("%p: Exception packet on host inner:\n", skb);
+	nss_nlgre_redir_cmn_print_hex_dump(skb);
 	skb->protocol = eth_type_trans(skb, netdev);
 	netif_receive_skb(skb);
 }
@@ -153,9 +153,17 @@
  */
 static void nss_nlgre_redir_cmn_wifi_offl_data_cb(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi)
 {
+	struct nss_ctx_instance *nss_ctx = nss_gre_redir_get_context();
+
+	if (!skb) {
+		nss_nl_warn("%p: SKB is NULL\n", nss_ctx);
+		return;
+	}
+
 	nss_nl_trace("%p: Exception packet on wifi offld inner:\n", skb);
-	nss_nlgre_redir_cmn_print_skb(skb);
-	dev_kfree_skb(skb);
+	nss_nlgre_redir_cmn_print_hex_dump(skb);
+	skb->protocol = eth_type_trans(skb, netdev);
+	netif_receive_skb(skb);
 }
 
 /*
@@ -165,7 +173,7 @@
 static void nss_nlgre_redir_cmn_sjack_data_cb(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi)
 {
 	nss_nl_trace("%p: Exception packet on sjack inner node:\n", skb);
-	nss_nlgre_redir_cmn_print_skb(skb);
+	nss_nlgre_redir_cmn_print_hex_dump(skb);
 	dev_kfree_skb(skb);
 }
 
@@ -176,7 +184,7 @@
 static void nss_nlgre_redir_cmn_outer_data_cb(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi)
 {
 	nss_nl_trace("%p: Exception packet on outer node:\n", skb);
-	nss_nlgre_redir_cmn_print_skb(skb);
+	nss_nlgre_redir_cmn_print_hex_dump(skb);
 	dev_kfree_skb(skb);
 }
 
@@ -286,7 +294,7 @@
 	/*
 	 * Configuring gre_redir meta data.
 	 */
-	meta_data_encap = (struct nss_gre_redir_encap_per_pkt_metadata *)(skb->data - NSS_GRE_REDIR_PER_PACKET_METADATA_OFFSET);
+	meta_data_encap = (struct nss_gre_redir_encap_per_pkt_metadata *)(skb->head + NSS_GRE_REDIR_PER_PACKET_METADATA_OFFSET);
 	memset(meta_data_encap, 0, sizeof(struct nss_gre_redir_encap_per_pkt_metadata));
 	meta_data_encap->gre_flags = 0;
 	meta_data_encap->gre_prio = 0;
@@ -398,6 +406,27 @@
 };
 
 /*
+ * nss_nlgre_redir_cmn_print_hex_dump()
+ *	To print hex dump of packet received
+ */
+void nss_nlgre_redir_cmn_print_hex_dump(struct sk_buff *skb)
+{
+	int16_t dump_sz = (skb->len < NSS_NLGRE_REDIR_PKT_DUMP_SZ) ? skb->len : NSS_NLGRE_REDIR_PKT_DUMP_SZ;
+
+	dump_sz -= NSS_NLGRE_REDIR_PKT_DUMP_OFFSET;
+	if (dump_sz > 0) {
+		/*
+		 * Enable dynamic debug to print
+		 */
+		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, skb->data, dump_sz);
+		return;
+	}
+
+	nss_nl_warn("Could not print packet skb->len=%d, DUMP_SZ=%d, DUMP_OFFSET=%d\n",
+			skb->len, NSS_NLGRE_REDIR_PKT_DUMP_SZ, NSS_NLGRE_REDIR_PKT_DUMP_OFFSET);
+}
+
+/*
  * nss_nlgre_redir_cmn_mode_str_to_enum()
  * 	Returns the type of mode
  */
@@ -493,40 +522,6 @@
 }
 
 /*
- * nss_nlgre_redir_cmn_print_skb()
- * 	Prints the skb data
- */
-void nss_nlgre_redir_cmn_print_skb(struct sk_buff *skb)
-{
-	int length;
-	int iter;
-
-	/*
-	 * Check if length is less than 16 bytes
-	 * Else bring down to minimum multiple of 16 bytes.
-	 */
-	if (skb->len < 16) {
-		nss_nl_trace("%p: Skb too small to print min size: 16 bytes\n", skb);
-		return;
-	}
-
-	length = (skb->len / 16);
-	if (length > NSS_NLGRE_REDIR_CMN_MAX_SKB_PRINT_LEN)
-		length = NSS_NLGRE_REDIR_CMN_MAX_SKB_PRINT_LEN;
-
-	/*
-	 * Print first 48 bytes of sk_buff
-	 */
-	for (iter = 0; iter < length; iter++) {
-		nss_nl_trace("%04xx: %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x\n", iter,
-			skb->data[iter * 8], skb->data[iter * 8 + 1], skb->data[iter * 8 + 2], skb->data[iter * 8 + 3],
-			skb->data[iter * 8 + 4], skb->data[iter * 8 + 5], skb->data[iter * 8 + 6], skb->data[iter * 8 + 7],
-			skb->data[iter * 8 + 8], skb->data[iter * 8 + 9], skb->data[iter * 8 + 10], skb->data[iter * 8 + 11],
-			skb->data[iter * 8 + 10], skb->data[iter * 8 + 13], skb->data[iter * 8 + 14], skb->data[iter * 8 + 15]);
-	}
-}
-
-/*
  * nss_gre_redir_unregister_and_deallocate()
  *	Unregisters and deallocates corresponding dev and node.
  */
diff --git a/netlink/nss_nlgre_redir_cmn.h b/netlink/nss_nlgre_redir_cmn.h
index 64daaaa..00138b1 100644
--- a/netlink/nss_nlgre_redir_cmn.h
+++ b/netlink/nss_nlgre_redir_cmn.h
@@ -27,6 +27,8 @@
 #define NSS_NLGRE_REDIR_CMN_MAX_SKB_PRINT_LEN 3		/**< Maximum length of skb to print */
 #define NSS_NLGRE_REDIR_CMN_MIN_TUNNELS 0		/**< Mininum number of tunnels required */
 #define NSS_NLGRE_REDIR_CMN_IP_TTL 128			/**< Time to live for IP */
+#define NSS_NLGRE_REDIR_PKT_DUMP_SZ 64			/**< Size of packet to dump */
+#define NSS_NLGRE_REDIR_PKT_DUMP_OFFSET 0		/**< Dump offset */
 
 /*
  * netdevice private data
@@ -112,10 +114,10 @@
 bool nss_nlgre_redir_cmn_unregister_and_deallocate(struct net_device *dev, uint32_t type);
 
 /*
- * nss_nlgre_redir_cmn_print_skb()
- * 	Prints the first 48 bytes of skb
+ * nss_nlgre_redir_cmn_print_hex_dump()
+ *	Prints the initials few bytes of packet
  */
-void nss_nlgre_redir_cmn_print_skb(struct sk_buff *skb);
+void nss_nlgre_redir_cmn_print_hex_dump(struct sk_buff *skb);
 
 /*
  * nss_nlgre_redir_cmn_create_tun()
diff --git a/netlink/nss_nlgre_redir_lag.c b/netlink/nss_nlgre_redir_lag.c
index 7b76bcc..3839df4 100644
--- a/netlink/nss_nlgre_redir_lag.c
+++ b/netlink/nss_nlgre_redir_lag.c
@@ -51,7 +51,7 @@
 static void nss_nlgre_redir_lag_us_data_cb(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi)
 {
 	nss_nl_trace("Exception packet on lag_us node:\n");
-	nss_nlgre_redir_cmn_print_skb(skb);
+	nss_nlgre_redir_cmn_print_hex_dump(skb);
 	dev_kfree_skb_any(skb);
 }
 
@@ -62,7 +62,7 @@
 static void nss_nlgre_redir_lag_ds_data_cb(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi)
 {
 	nss_nl_trace("Exception packet on lag_ds node:\n");
-	nss_nlgre_redir_cmn_print_skb(skb);
+	nss_nlgre_redir_cmn_print_hex_dump(skb);
 	dev_kfree_skb_any(skb);
 }
 
diff --git a/netlink/nss_nlipv4.c b/netlink/nss_nlipv4.c
index 80003f6..6e1fa23 100644
--- a/netlink/nss_nlipv4.c
+++ b/netlink/nss_nlipv4.c
@@ -326,15 +326,14 @@
 		/*
 		 * Currently this implementation is only for gre_redir
 		 */
-		conn->flow_interface_num = nss_nlgre_redir_cmd_get_ifnum(flow_dev,
-					NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER);
+		conn->flow_interface_num = nss_nlgre_redir_cmd_get_ifnum(flow_dev, tuple->protocol);
 		if (conn->flow_interface_num < 0 ) {
 			nss_nl_error("%p: Failed to get flow interface number (dev:%s, type:%d)\n",
 								flow_dev, flow_dev->name, flow_iftype);
 			return -EINVAL;
 		}
 
-		conn->flow_mtu = NSS_NLIPV4_MAX_MTU;
+		conn->flow_mtu = nss_nlgre_redir_cmd_get_mtu(flow_dev, NSS_GRE_REDIR_IP_HDR_TYPE_IPV4, conn->flow_interface_num);
 		break;
 
 	case NSS_NL_IFTYPE_VLAN:
@@ -384,15 +383,14 @@
 		break;
 
 	case NSS_NL_IFTYPE_TUNNEL_GRE:
-		conn->return_interface_num = nss_nlgre_redir_cmd_get_ifnum(return_dev,
-				NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_WIFI_OFFL_INNER);
+		conn->return_interface_num = nss_nlgre_redir_cmd_get_ifnum(return_dev, tuple->protocol);
 		if (conn->return_interface_num < 0 ) {
 			nss_nl_error("%p: Failed to get return interface number (dev:%s, type:%d)\n",
 							return_dev, return_dev->name, return_iftype);
 			return -EINVAL;
 		}
 
-		conn->return_mtu = NSS_NLIPV4_MAX_MTU;
+		conn->return_mtu = nss_nlgre_redir_cmd_get_mtu(return_dev, NSS_GRE_REDIR_IP_HDR_TYPE_IPV4, conn->return_interface_num);
 		break;
 
 	case NSS_NL_IFTYPE_VLAN:
diff --git a/netlink/nss_nlipv6.c b/netlink/nss_nlipv6.c
index febe480..f19e826 100644
--- a/netlink/nss_nlipv6.c
+++ b/netlink/nss_nlipv6.c
@@ -336,14 +336,14 @@
 		break;
 
 	case NSS_NL_IFTYPE_TUNNEL_GRE:
-		conn->flow_interface_num = nss_nlgre_redir_cmd_get_ifnum(flow_dev, NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER);
+		conn->flow_interface_num = nss_nlgre_redir_cmd_get_ifnum(flow_dev, tuple->protocol);
 		if (conn->flow_interface_num < 0 ) {
 			nss_nl_error("%p: Failed to get flow interface number (dev:%s, type:%d)\n",
 			flow_dev, flow_dev->name, flow_iftype);
 			return -EINVAL;
 		}
 
-		conn->flow_mtu = NSS_NLIPV6_MAX_MTU;
+		conn->flow_mtu = nss_nlgre_redir_cmd_get_mtu(flow_dev, NSS_GRE_REDIR_IP_HDR_TYPE_IPV6, conn->flow_interface_num);
 		break;
 
 	case NSS_NL_IFTYPE_VLAN:
@@ -394,15 +394,14 @@
 		break;
 
 	case NSS_NL_IFTYPE_TUNNEL_GRE:
-		conn->return_interface_num = nss_nlgre_redir_cmd_get_ifnum(return_dev,
-		NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_WIFI_OFFL_INNER);
+		conn->return_interface_num = nss_nlgre_redir_cmd_get_ifnum(return_dev, tuple->protocol);
 		if (conn->return_interface_num < 0 ) {
 			nss_nl_error("%p: Failed to get return interface number (dev:%s, type:%d)\n",
 			return_dev, return_dev->name, return_iftype);
 			return -EINVAL;
 		}
 
-		conn->return_mtu = NSS_NLIPV6_MAX_MTU;
+		conn->return_mtu = nss_nlgre_redir_cmd_get_mtu(return_dev, NSS_GRE_REDIR_IP_HDR_TYPE_IPV6, conn->return_interface_num);
 		break;
 
 	case NSS_NL_IFTYPE_VLAN: