[qca-nss-clients] Modify GRE exception handler

Modified eth_type_trans usage in GRE exception handler.

Change-Id: Ied81f278efe864181ca259390cda57c23f63ef92
Signed-off-by: Subhash Kumar Katnpally <skatnapa@codeaurora.org>
diff --git a/gre/nss_connmgr_gre.c b/gre/nss_connmgr_gre.c
index d9e78f3..9b39dae 100644
--- a/gre/nss_connmgr_gre.c
+++ b/gre/nss_connmgr_gre.c
@@ -359,28 +359,44 @@
 					  __attribute__((unused)) struct napi_struct *napi)
 {
 
+	struct ethhdr *eth_hdr;
 	if (unlikely(!enable_notifier)) {
 		nss_connmgr_gre_error("%p: NSS GRE exception handler called\n", dev);
 		dev_kfree_skb_any(skb);
 		return;
 	}
 
-	skb->dev = dev;
-	skb->skb_iif = dev->ifindex;
-	skb->protocol = eth_type_trans(skb, dev);
-	switch (ntohs(skb->protocol)) {
-	case ETH_P_IP:
-		return nss_connmgr_gre_v4_exception(dev, skb);
-
-	case ETH_P_IPV6:
-		return nss_connmgr_gre_v6_exception(dev, skb);
-	default:
-		break;
+	if (unlikely(!pskb_may_pull(skb, sizeof(struct ethhdr)))) {
+		nss_connmgr_gre_warning("%p: pskb_may_pull failed for skb:%p\n", dev, skb);
+		dev_kfree_skb_any(skb);
+		return;
+	}
+	eth_hdr = (struct ethhdr *)skb->data;
+	if (likely(eth_proto_is_802_3(eth_hdr->h_proto))) {
+		switch (ntohs(eth_hdr->h_proto)) {
+		case ETH_P_IP:
+			if (unlikely(!pskb_may_pull(skb, sizeof(struct iphdr)))) {
+				nss_connmgr_gre_warning("%p: pskb_may_pull failed for skb:%p\n", dev, skb);
+				dev_kfree_skb_any(skb);
+				return;
+			}
+			return nss_connmgr_gre_v4_exception(dev, skb);
+		case ETH_P_IPV6:
+			if (unlikely(!pskb_may_pull(skb, sizeof(struct ipv6hdr)))) {
+				nss_connmgr_gre_warning("%p: pskb_may_pull failed for skb:%p\n", dev, skb);
+				dev_kfree_skb_any(skb);
+				return;
+			}
+			return nss_connmgr_gre_v6_exception(dev, skb);
+		default:
+			break;
+		}
 	}
 
 	/*
 	 * These are decapped and exceptioned non IP packets.
 	 */
+	skb->protocol = eth_type_trans(skb, dev);
 	netif_receive_skb(skb);
 	return;
 }
diff --git a/gre/nss_connmgr_gre_v4.c b/gre/nss_connmgr_gre_v4.c
index 4835cd0..6275738 100644
--- a/gre/nss_connmgr_gre_v4.c
+++ b/gre/nss_connmgr_gre_v4.c
@@ -190,13 +190,14 @@
 	iphdr->saddr = htonl(iphdr->saddr);
 	iphdr->daddr = htonl(iphdr->daddr);
 
-	if (!cfg->tos_inherit) {
-		iphdr->tos = cfg->tos;
+	iphdr->tos = cfg->tos << 2;
+	if (cfg->tos_inherit) {
+		iphdr->tos |= 0x1 ;
 	}
 
 	iphdr->ttl = cfg->ttl;
 	if (cfg->ttl_inherit) {
-		iphdr->ttl = 0x1;
+		iphdr->ttl = 0;
 	}
 
 	if (cfg->set_df) {
@@ -223,33 +224,47 @@
  */
 void nss_connmgr_gre_v4_exception(struct net_device *dev, struct sk_buff *skb)
 {
-	struct iphdr *iph = (struct iphdr *)skb->data;
+	struct ethhdr *eth_hdr = (struct ethhdr *)skb->data;
+	struct iphdr *iph = (struct iphdr *)(eth_hdr + 1);
+
 	if (iph->protocol != IPPROTO_GRE) {
 
 		/*
 		 * These are decapped IP packets.
 		 */
+		skb->protocol = eth_type_trans(skb, dev);
 		netif_receive_skb(skb);
 		return;
 	}
-	if (unlikely(!pskb_may_pull(skb, (sizeof(struct iphdr) + sizeof(struct gre_base_hdr))))) {
+
+	/*
+	 * GRE encapsulated packet exceptioned, remove the encapsulation
+	 * and transmit on GRE interface.
+	 */
+	if (unlikely(!pskb_may_pull(skb, (sizeof(struct ethhdr) + sizeof(struct iphdr)
+				+ sizeof(struct gre_base_hdr))))) {
 		nss_connmgr_gre_warning("%p: pskb_may_pull failed for skb:%p\n", dev, skb);
 		dev_kfree_skb_any(skb);
 		return;
 	}
-	skb_pull(skb, sizeof(struct iphdr));
-	skb_pull(skb, sizeof(struct gre_base_hdr));
+	skb_pull(skb, (sizeof(struct ethhdr) + sizeof(struct iphdr)
+				+ sizeof(struct gre_base_hdr)));
 
 	if (unlikely(!pskb_may_pull(skb, sizeof(struct ethhdr)))) {
 		nss_connmgr_gre_warning("%p: pskb_may_pull failed for skb:%p\n", dev, skb);
 		dev_kfree_skb_any(skb);
 		return;
 	}
-	skb->protocol = eth_type_trans(skb, dev);
-	skb_push(skb, ETH_HLEN);
-
+	skb->dev = dev;
+	if (likely(eth_proto_is_802_3(eth_hdr->h_proto))) {
+		skb->protocol = eth_hdr->h_proto;
+	} else {
+		skb->protocol = htons(ETH_P_802_2);
+	}
+	skb_reset_mac_header(skb);
 	skb_reset_network_header(skb);
 	skb_reset_transport_header(skb);
+	skb_reset_mac_len(skb);
 	dev_queue_xmit(skb);
 }
 
@@ -280,7 +295,7 @@
 	cmsg->ikey = t->parms.i_key;
 	cmsg->okey = t->parms.o_key;
 	cmsg->ttl = iphdr->ttl;
-	cmsg->tos = iphdr->tos;
+	cmsg->tos = iphdr->tos >> 2;
 
 	/*
 	 * fill in MAC addresses
diff --git a/gre/nss_connmgr_gre_v6.c b/gre/nss_connmgr_gre_v6.c
index 0bff247..01fcc47 100644
--- a/gre/nss_connmgr_gre_v6.c
+++ b/gre/nss_connmgr_gre_v6.c
@@ -126,34 +126,50 @@
  */
 void nss_connmgr_gre_v6_exception(struct net_device *dev, struct sk_buff *skb)
 {
-	struct ipv6hdr *ip6h = (struct ipv6hdr *)skb->data;
+	struct ethhdr *eth = (struct ethhdr *)skb->data;
+	struct ipv6hdr *ip6h = (struct ipv6hdr *)(eth + 1);
+
 	if (ip6h->nexthdr != IPPROTO_GRE) {
 
 		/*
 		 * These are decapped IP packets.
 		 */
+		skb->protocol = eth_type_trans(skb, dev);
 		netif_receive_skb(skb);
 		return;
 	}
-	if (unlikely(!pskb_may_pull(skb, (sizeof(struct ipv6hdr) + sizeof(struct gre_base_hdr))))) {
+
+	/*
+	 * GRE encapsulated packet exceptioned, remove the encapsulation
+	 * and transmit on GRE interface.
+	 */
+	if (unlikely(!pskb_may_pull(skb, (sizeof(struct ethhdr) + sizeof(struct ipv6hdr)
+				+ sizeof(struct gre_base_hdr))))) {
 		nss_connmgr_gre_warning("%p: pskb_may_pull failed for skb:%p\n", dev, skb);
 		dev_kfree_skb_any(skb);
 		return;
 	}
-	skb_pull(skb, sizeof(struct ipv6hdr));
-	skb_pull(skb, sizeof(struct gre_base_hdr));
+	skb_pull(skb, (sizeof(struct ethhdr) + sizeof(struct ipv6hdr)
+				+ sizeof(struct gre_base_hdr)));
 
 	if (unlikely(!pskb_may_pull(skb, sizeof(struct ethhdr)))) {
 		nss_connmgr_gre_warning("%p: pskb_may_pull failed for skb:%p\n", dev, skb);
 		dev_kfree_skb_any(skb);
 		return;
 	}
-	skb->protocol = eth_type_trans(skb, dev);
-	skb_push(skb, ETH_HLEN);
-
+	skb->dev = dev;
+	if (likely(eth_proto_is_802_3(eth->h_proto))) {
+		skb->protocol = eth->h_proto;
+	} else {
+		/*
+		 *      Real 802.2 LLC
+		 */
+		skb->protocol = htons(ETH_P_802_2);
+	}
+	skb_reset_mac_header(skb);
 	skb_reset_network_header(skb);
 	skb_reset_transport_header(skb);
-
+	skb_reset_mac_len(skb);
 	dev_queue_xmit(skb);
 }
 
@@ -194,14 +210,11 @@
 	memcpy(t->parms.laddr.s6_addr, &cfg->src_ip, 16);
 	memcpy(t->parms.raddr.s6_addr, &cfg->dest_ip, 16);
 
-	t->parms.flowinfo = cfg->tos;
-	if (cfg->tos_inherit) {
-		t->parms.flowinfo = 0;
-	}
+	t->parms.flowinfo = 0;
 
 	t->parms.hop_limit = cfg->ttl;
 	if (cfg->ttl_inherit) {
-		t->parms.hop_limit = 0x1;
+		t->parms.hop_limit = 0;
 	}
 
 	if (cfg->ikey_valid) {
@@ -234,9 +247,12 @@
 	memcpy(cmsg->src_ip, t->parms.laddr.s6_addr, 16);
 	memcpy(cmsg->dest_ip, t->parms.raddr.s6_addr, 16);
 
+	/*
+	 * IPv6 outer tos field is always inherited from inner IP header.
+	 */
 	cmsg->flags = nss_connmgr_gre_get_nss_config_flags(t->parms.o_flags,
 								     t->parms.i_flags,
-								     t->parms.flowinfo,
+								     0x1,
 								     t->parms.hop_limit, 0);
 
 	cmsg->ikey = t->parms.i_key;