[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;