[qca-nss-clients] fix IPsec NATT issue

Change-Id: Ib717231d1b2e41fbfbfa97f2b5280b7b4672c3a6
Signed-off-by: Arunkumar T <athand@codeaurora.org>
Signed-off-by: mandrw <mandrw@codeaurora.org>
diff --git a/ipsecmgr/nss_ipsecmgr_sa.c b/ipsecmgr/nss_ipsecmgr_sa.c
index c7b9e46..a3fbe4a 100644
--- a/ipsecmgr/nss_ipsecmgr_sa.c
+++ b/ipsecmgr/nss_ipsecmgr_sa.c
@@ -818,6 +818,7 @@
 bool nss_ipsecmgr_decap_add(struct net_device *tun, struct nss_ipsecmgr_sa *sa, struct nss_ipsecmgr_sa_data *data)
 {
 	struct nss_ipsecmgr_priv *priv = netdev_priv(tun);
+	struct nss_ipsec_rule *ipsec_rule;
 	struct nss_ipsecmgr_sa_info info;
 
 	nss_ipsecmgr_info("%p:decap_add initiated\n", tun);
@@ -832,6 +833,16 @@
 		nss_ipsecmgr_copy_v4_sa(&info.nim, &sa->data.v4);
 		nss_ipsecmgr_copy_sa_data(&info.nim, data);
 
+		/*
+		 * if NATT is set override the protocol and port numbers
+		 */
+		ipsec_rule = &info.nim.msg.push;
+		if (ipsec_rule->data.nat_t_req) {
+			ipsec_rule->sel.proto_next_hdr = IPPROTO_UDP;
+			ipsec_rule->sel.dst_port = NSS_IPSECMGR_NATT_PORT_DATA;
+			ipsec_rule->sel.src_port = NSS_IPSECMGR_NATT_PORT_DATA;
+		}
+
 		nss_ipsecmgr_decap_v4_flow2key(&sa->data.v4, &info.child_key);
 		nss_ipsecmgr_v4_sa2key(&sa->data.v4, &info.sa_key);
 		break;
diff --git a/netlink/nss_nlipv4.c b/netlink/nss_nlipv4.c
index 9031abb..4f26813 100755
--- a/netlink/nss_nlipv4.c
+++ b/netlink/nss_nlipv4.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 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.
@@ -49,6 +49,8 @@
 #include "nss_nl.h"
 #include "nss_nlcmn_if.h"
 #include "nss_nlipv4_if.h"
+#include "nss_ipsec.h"
+#include "nss_ipsecmgr.h"
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
 #define DST_NEIGH_LOOKUP(dst, ip_addr) dst_neigh_lookup(dst, ip_addr)
@@ -273,6 +275,7 @@
 {
 	struct nss_ipv4_connection_rule *conn = &msg->conn_rule;
 	const size_t rule_sz = sizeof(struct nss_ipv4_connection_rule);
+	bool override_mtu;
 	bool valid;
 
 	valid = msg->valid_flags & NSS_IPV4_RULE_CREATE_CONN_VALID;
@@ -307,10 +310,31 @@
 	/*
 	 * update the flow & return MTU(s)
 	 */
-	conn->flow_mtu = flow_dev->mtu;
 	conn->return_mtu = return_dev->mtu;
 
 	/*
+	 * If, flow device is IPsec tunnel and protocol is ESP or NAT-T (UDP@4500)
+	 * then the operation is Decapsulation. In this we would like to have the MTU
+	 * of the incoming physical/virtual device. This would avoid fragmenting the
+	 * packet in NSS before delivering it for IPsec decap
+	 */
+	switch (msg->tuple.protocol) {
+	case IPPROTO_UDP:
+		override_mtu = (flow_dev->type == NSS_IPSEC_ARPHRD_IPSEC) && (msg->tuple.flow_ident == NSS_IPSECMGR_NATT_PORT_DATA);
+		break;
+
+	case IPPROTO_ESP:
+		override_mtu = (flow_dev->type == NSS_IPSEC_ARPHRD_IPSEC);
+		break;
+
+	default:
+		override_mtu = false;
+		break;
+	}
+
+	conn->flow_mtu = override_mtu ? conn->return_mtu : flow_dev->mtu;
+
+	/*
 	 * update flow & return xlate info
 	 */
 	conn->flow_ip_xlate = msg->tuple.flow_ip;