Merge "[qca-nss-clients] Metadata based tunnel TX"
diff --git a/bridge/Makefile b/bridge/Makefile
index f9e445e..12f09c8 100644
--- a/bridge/Makefile
+++ b/bridge/Makefile
@@ -15,7 +15,7 @@
ccflags-y += -DNSS_BRIDGE_MGR_PPE_SUPPORT
endif
-ifeq ($(CONFIG_BONDING), $(filter $(CONFIG_BONDING), y m))
+ifneq (,$(filter $(CONFIG_BONDING),y m))
ifneq ($(findstring 4.4, $(KERNELVERSION)),)
ccflags-y += -DBONDING_SUPPORT
endif
diff --git a/gre/nss_connmgr_gre_v4.c b/gre/nss_connmgr_gre_v4.c
index 29873da..a8897a3 100644
--- a/gre/nss_connmgr_gre_v4.c
+++ b/gre/nss_connmgr_gre_v4.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-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.
@@ -93,8 +93,6 @@
return GRE_ERR_RADDR_ROUTE_LOOKUP;
}
- rcu_read_lock();
-
neigh = dst_neigh_lookup(&rt->dst, (const void *)&raddr);
if (!neigh) {
neigh = neigh_lookup(&arp_tbl, (const void *)&raddr, rt->dst.dev);
@@ -112,7 +110,6 @@
neigh = neigh_create(&arp_tbl, &raddr, rt->dst.dev);
if (IS_ERR_OR_NULL(neigh)) {
nss_connmgr_gre_warning("Unable to create ARP request neigh for %pI4\n", &raddr);
- rcu_read_unlock();
ip_rt_put(rt);
return GRE_ERR_NEIGH_CREATE;
}
@@ -123,7 +120,6 @@
}
if (neigh->dev->type == ARPHRD_LOOPBACK) {
- rcu_read_unlock();
ip_rt_put(rt);
neigh_release(neigh);
nss_connmgr_gre_warning("Err in destination MAC address, neighbour dev is loop back for %pI4\n", &raddr);
@@ -132,7 +128,6 @@
}
if (neigh->dev->flags & IFF_NOARP) {
- rcu_read_unlock();
ip_rt_put(rt);
neigh_release(neigh);
nss_connmgr_gre_warning("Err in destination MAC address, neighbour dev is of type NO_ARP for %pI4\n", &raddr);
@@ -140,7 +135,6 @@
}
ether_addr_copy(dest_mac, neigh->ha);
- rcu_read_unlock();
ip_rt_put(rt);
neigh_release(neigh);
nss_connmgr_gre_info("Destination MAC address for %pI4 is %pM\n", &raddr, dest_mac);
diff --git a/nss_connmgr_tunipip6.c b/nss_connmgr_tunipip6.c
index 6aab27d..d401bdf 100644
--- a/nss_connmgr_tunipip6.c
+++ b/nss_connmgr_tunipip6.c
@@ -29,7 +29,10 @@
#include <linux/tcp.h>
#include <linux/module.h>
#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <net/ip.h>
#include <net/ipv6.h>
+#include <linux/if.h>
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,9,0))
#include <net/ipip.h>
#else
@@ -94,7 +97,7 @@
* nss_tunipip6_encap_exception()
* Exception handler registered to NSS driver.
*
- * This function is called when no rule is found for successful encapsulation.
+ * Exception handler registered to NSS for handling tunipip6 ipv4 pkts.
*/
static void nss_tunipip6_encap_exception(struct net_device *dev, struct sk_buff *skb, __attribute__((unused)) struct napi_struct *napi)
{
@@ -114,20 +117,94 @@
* nss_tunipip6_decap_exception()
* Exception handler registered to NSS driver.
*
- * This function is called when no rule is found for successful decapsulation.
+ * Exception handler registered to NSS for handling tunipip6 ipv6 pkts.
*/
static void nss_tunipip6_decap_exception(struct net_device *dev, struct sk_buff *skb, __attribute__((unused)) struct napi_struct *napi)
{
- skb->dev = dev;
- nss_tunipip6_info("received - %d bytes name %s ver %x\n",
- skb->len, dev->name, (skb->data[0] >> 4));
+ const struct net_device_ops *ops = dev->netdev_ops;
+ struct netdev_queue *queue;
+ struct iphdr *iph;
+ struct rtable *rt;
+ int cpu;
+ int8_t ver = skb->data[0] >> 4;
- skb->protocol = htons(ETH_P_IPV6);
+ nss_tunipip6_trace("%p: received - %d bytes name %s ver %x\n",
+ dev, skb->len, dev->name, ver);
+
+ nss_tunipip6_assert(ver == 6);
+
+ if (unlikely(!pskb_may_pull(skb, sizeof(struct ipv6hdr)))) {
+ nss_tunipip6_warning("%p: pskb_may_pull failed to pull ipv6 header", dev);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ skb_pull(skb, sizeof(struct ipv6hdr));
+
+ if (unlikely(!pskb_may_pull(skb, sizeof(struct iphdr)))) {
+ nss_tunipip6_warning("%p: pskb_may_pull failed to linearize iphdr, packet does not have a proper IPv4 header.", dev);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
skb_reset_network_header(skb);
+
+ iph = ip_hdr(skb);
+ nss_tunipip6_assert(iph->version == 4);
+
+ rt = ip_route_output(&init_net, iph->daddr, 0, 0, 0);
+ if (unlikely(IS_ERR(rt))) {
+ nss_tunipip6_info("%p: Failed to find IPv4 route for %pI4\n", skb, &iph->daddr);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ nss_tunipip6_trace("%p: Route look up successful for dest_ip: %pI4 src_ip: %pI4\n",
+ skb, &iph->daddr, &iph->saddr);
+
+ skb_dst_drop(skb);
+ skb_dst_set(skb, &rt->dst);
+
+ skb_reset_transport_header(skb);
+
+ /*
+ * Set ignore df bit to fragment the packet in kernel.
+ */
+ if (!(iph->frag_off & htons(IP_DF))) {
+ skb->ignore_df = true;
+ }
+
+ skb->protocol = htons(ETH_P_IP);
skb->pkt_type = PACKET_HOST;
skb->skb_iif = dev->ifindex;
+ skb->dev = dev;
skb->ip_summed = CHECKSUM_NONE;
- netif_receive_skb(skb);
+
+ /*
+ * This is needed to acquire HARD_TX_LOCK.
+ */
+ cpu = smp_processor_id();
+ queue = skb_get_tx_queue(dev, skb);
+
+ nss_tunipip6_trace("%p: skb queue mapping: %d, cpu: %d", skb, skb_get_queue_mapping(skb), cpu);
+
+ /*
+ * Take HARD_TX_LOCK to be in sync with the kernel.
+ */
+ HARD_TX_LOCK(dev, queue, cpu);
+
+ /*
+ * Check if queue is alive
+ */
+ if (unlikely(netif_xmit_frozen_or_stopped(queue))) {
+ HARD_TX_UNLOCK(dev, queue);
+ nss_tunipip6_trace("%p: Dropping the packet, as queue: %p is not alive", skb, queue);
+ skb_dst_drop(skb);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+ ops->ndo_start_xmit(skb, dev);
+ HARD_TX_UNLOCK(dev, queue);
}
/*
diff --git a/pppoe/Makefile b/pppoe/Makefile
index 05e8749..1a2d899 100644
--- a/pppoe/Makefile
+++ b/pppoe/Makefile
@@ -5,7 +5,7 @@
obj-m += qca-nss-pppoe.o
qca-nss-pppoe-objs := nss_connmgr_pppoe.o
-ifeq ($(CONFIG_BONDING), $(filter $(CONFIG_BONDING), y m))
+ifneq (,$(filter $(CONFIG_BONDING),y m))
ifneq ($(findstring 4.4, $(KERNELVERSION)),)
ccflags-y += -DBONDING_SUPPORT
endif
diff --git a/vlan/Makefile b/vlan/Makefile
index e623c82..ff2ac99 100644
--- a/vlan/Makefile
+++ b/vlan/Makefile
@@ -11,7 +11,7 @@
ccflags-y += -DNSS_VLAN_MGR_DEBUG_LEVEL=0
ccflags-y += -Werror
-ifeq ($(CONFIG_BONDING), $(filter $(CONFIG_BONDING), y m))
+ifneq (,$(filter $(CONFIG_BONDING),y m))
ifneq ($(findstring 4.4, $(KERNELVERSION)),)
ccflags-y += -DBONDING_SUPPORT
endif