nss-packages-qosmio/qca-nss-clients/patches/0004-11.4-tunipip6.patch
2022-12-04 05:16:42 -05:00

910 lines
29 KiB
Diff

--- a/exports/nss_connmgr_tunipip6.h
+++ b/exports/nss_connmgr_tunipip6.h
@@ -28,12 +28,13 @@ enum nss_connmgr_tunipip6_err_codes {
NSS_CONNMGR_TUNIPIP6_TUN_DESTROY_FAILURE, /**< Tunnel destroy failure. */
NSS_CONNMGR_TUNIPIP6_TUN_NONE, /**< Invalid tunnel type */
NSS_CONNMGR_TUNIPIP6_NETDEV_TYPE_FAILURE, /**< Netdevice is not of type ipv6-in-ipv4. */
- NSS_CONNMGR_TUNIPIP6_MAPRULE_ADD_FAILURE, /**< BMR/FMR addition failure. */
- NSS_CONNMGR_TUNIPIP6_MAPRULE_DEL_FAILURE, /**< BMR/FMR deletion failure. */
- NSS_CONNMGR_TUNIPIP6_FMR_RULE_FLUSH_FAILURE, /**< FMR flush failure. */
+ NSS_CONNMGR_TUNIPIP6_MAPRULE_ADD_FAILURE, /**< BMR/FMR addition failure. */
+ NSS_CONNMGR_TUNIPIP6_MAPRULE_DEL_FAILURE, /**< BMR/FMR deletion failure. */
+ NSS_CONNMGR_TUNIPIP6_FMR_RULE_FLUSH_FAILURE, /**< FMR flush failure. */
NSS_CONNMGR_TUNIPIP6_NO_DEV, /**< No NSS node found. */
NSS_CONNMGR_TUNIPIP6_INVALID_PARAM, /**< Invalid tunnel parameters. */
NSS_CONNMGR_TUNIPIP6_INVALID_RULE_TYPE, /**< Invalid maprule type. */
+ NSS_CONNMGR_TUNIPIP6_CONTEXT_FAILURE, /**< Tunnel host context not found. */
};
/*
--- a/tunipip6/Makefile
+++ b/tunipip6/Makefile
@@ -2,9 +2,8 @@
ccflags-y += -I$(obj)/../exports -I$(obj)/..
ccflags-y += -DNSS_CLIENT_BUILD_ID="$(BUILD_ID)"
ccflags-y += -DNSS_TUNIPIP6_DEBUG_LEVEL=0
-ccflags-y += -Werror
obj-m += qca-nss-tunipip6.o
-qca-nss-tunipip6-objs := nss_connmgr_tunipip6.o nss_connmgr_tunipip6_sysctl.o
+qca-nss-tunipip6-objs := nss_connmgr_tunipip6.o nss_connmgr_tunipip6_sysctl.o nss_connmgr_tunipip6_stats.o
ifneq ($(findstring 4.4, $(KERNELVERSION)),)
ccflags-y += -DDRAFT03_SUPPORT
endif
--- a/tunipip6/nss_connmgr_tunipip6.c
+++ b/tunipip6/nss_connmgr_tunipip6.c
@@ -20,7 +20,6 @@
#include <linux/types.h>
#include <linux/ip.h>
#include <linux/of.h>
-#include <linux/tcp.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -29,71 +28,123 @@
#include <linux/if.h>
#include <net/ip_tunnels.h>
#include <net/ip6_tunnel.h>
-#include <linux/if_arp.h>
#include <nss_api_if.h>
#include "nss_connmgr_tunipip6.h"
#include "nss_connmgr_tunipip6_sysctl.h"
+#include "nss_connmgr_tunipip6_priv.h"
+
+#define NSS_TUNIPIP6_MAX_FMR 255 /* Maximum number of forward mapping rule (FMR). */
/*
- * NSS tunipip6 debug macros
+ * Frag Id update is disabled by default
*/
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 1)
-#define nss_tunipip6_assert(fmt, args...)
-#else
-#define nss_tunipip6_assert(c) if (!(c)) { BUG_ON(!(c)); }
-#endif
-
-#if defined(CONFIG_DYNAMIC_DEBUG)
+bool frag_id_update = false;
+/*
+ * Creating custom ipip6 interface is disabled by default.
+ */
+static bool enable_custom;
+module_param(enable_custom, bool, 0);
/*
- * Compile messages for dynamic enable/disable
+ * tunipip6 global context.
*/
-#define nss_tunipip6_warning(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
-#define nss_tunipip6_info(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
-#define nss_tunipip6_trace(s, ...) pr_debug("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
-#else
+struct nss_tunipip6_context tunipip6_ctx;
/*
- * Statically compile messages at different levels
+ * nss_tunipip6_alloc_instance()
+ * Allocate tunipip6 interface instance.
*/
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 2)
-#define nss_tunipip6_warning(s, ...)
-#else
-#define nss_tunipip6_warning(s, ...) pr_warn("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
-#endif
+static struct nss_tunipip6_instance *nss_tunipip6_alloc_instance(struct net_device *dev,
+ int inner_ifnum,
+ int outer_ifnum)
+{
+ struct nss_tunipip6_instance*ntii;
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 3)
-#define nss_tunipip6_info(s, ...)
-#else
-#define nss_tunipip6_info(s, ...) pr_notice("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
-#endif
+ ntii = vzalloc(sizeof(*ntii));
+ if (!ntii) {
+ nss_tunipip6_warning("%px: Not able to allocate tunipip6 instance\n", dev);
+ return NULL;
+ }
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 4)
-#define nss_tunipip6_trace(s, ...)
-#else
-#define nss_tunipip6_trace(s, ...) pr_info("%s[%d]:" s, __func__, __LINE__, ##__VA_ARGS__)
-#endif
-#endif
+ ntii->dev = dev;
+
+ /*
+ * Create statistics dentry.
+ */
+ if (!nss_tunipip6_stats_dentry_create(ntii)) {
+ vfree(ntii);
+ nss_tunipip6_warning("%px: Not able to create tunipip6 statistics dentry\n", dev);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&ntii->list);
+ ntii->inner_ifnum = inner_ifnum;
+ ntii->outer_ifnum = outer_ifnum;
+ dev_hold(dev);
+ return ntii;
+}
/*
- * Frag Id update is disabled by default
+ * nss_tunipip6_free_instance()
+ * Delete the tunipip6 interface instance from the list and free it.
+ *
+ * Note: tunnel list lock is expected to be held by the caller.
*/
-bool frag_id_update = false;
+static void nss_tunipip6_free_instance(struct nss_tunipip6_instance *ntii)
+{
+ if (!list_empty(&ntii->list)) {
+ list_del(&ntii->list);
+ }
+
+ vfree(ntii);
+}
+
/*
- * Creating custom ipip6 interface is disabled by default.
+ * nss_tunipip6_find_instance()
+ * Find tunipip6 interface instance from list.
+ *
+ * Note: tunnel list lock is expected to be held by the caller.
*/
-static bool enable_custom;
-module_param(enable_custom, bool, 0);
+struct nss_tunipip6_instance *nss_tunipip6_find_instance(struct net_device *dev)
+{
+ struct nss_tunipip6_instance *ntii;
+
+ /*
+ * Check if dev instance is in the list
+ */
+ list_for_each_entry(ntii, &tunipip6_ctx.dev_list, list) {
+ if (ntii->dev == dev) {
+ return ntii;
+ }
+ }
+
+ return NULL;
+}
/*
- * tunipip6 stats structure
+ * nss_tunipip6_find_and_free_instance()
+ * Find and free the tunipip6 instance.
*/
-struct nss_tunipip6_stats {
- uint32_t rx_packets; /* Number of received packets */
- uint32_t rx_bytes; /* Number of received bytes */
- uint32_t tx_packets; /* Number of transmitted packets */
- uint32_t tx_bytes; /* Number of transmitted bytes */
-};
+static enum nss_connmgr_tunipip6_err_codes nss_tunipip6_find_and_free_instance(struct net_device *netdev)
+{
+ struct dentry *dentry;
+ struct nss_tunipip6_instance *ntii;
+
+ spin_lock_bh(&tunipip6_ctx.lock);
+ ntii = nss_tunipip6_find_instance(netdev);
+ if (!ntii) {
+ spin_unlock_bh(&tunipip6_ctx.lock);
+ nss_tunipip6_warning("%px: Not able to find tunipip6 instance for dev:%s\n", netdev, netdev->name);
+ return NSS_CONNMGR_TUNIPIP6_CONTEXT_FAILURE;
+ }
+
+ dentry = ntii->dentry;
+ nss_tunipip6_free_instance(ntii);
+ spin_unlock_bh(&tunipip6_ctx.lock);
+ debugfs_remove(dentry);
+ dev_put(netdev);
+ return NSS_CONNMGR_TUNIPIP6_SUCCESS;
+}
/*
* nss_tunipip6_encap_exception()
@@ -289,20 +340,29 @@ static void nss_tunipip6_decap_exception
/*
* nss_tunipip6_update_dev_stats
- * Update the Dev stats received from NetAp
+ * Update the Dev stats received from NSS
*/
static void nss_tunipip6_update_dev_stats(struct net_device *dev,
- struct nss_tunipip6_stats_sync_msg *sync_stats)
+ struct nss_tunipip6_msg *tnlmsg)
{
struct pcpu_sw_netstats stats;
+ enum nss_dynamic_interface_type interface_type;
+ struct nss_tunipip6_stats_sync_msg *sync_stats = (struct nss_tunipip6_stats_sync_msg *)&tnlmsg->msg.stats_sync;
+
+ interface_type = nss_dynamic_interface_get_type(nss_tunipip6_get_context(), tnlmsg->cm.interface);
+
+ memset(&stats, 0, sizeof(stats));
+ if (interface_type == NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_INNER) {
+ stats.tx_packets = sync_stats->node_stats.tx_packets;
+ stats.tx_bytes = sync_stats->node_stats.tx_bytes;
+ } else if (interface_type == NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6_OUTER) {
+ stats.rx_packets = sync_stats->node_stats.rx_packets;
+ stats.rx_bytes = sync_stats->node_stats.rx_bytes;
+ } else {
+ nss_tunipip6_warning("%px: Invalid interface type received from NSS\n", dev);
+ return;
+ }
- u64_stats_init(&stats.syncp);
- u64_stats_update_begin(&stats.syncp);
- stats.rx_packets = sync_stats->node_stats.rx_packets;
- stats.rx_bytes = sync_stats->node_stats.rx_bytes;
- stats.tx_packets = sync_stats->node_stats.tx_packets;
- stats.tx_bytes = sync_stats->node_stats.tx_bytes;
- u64_stats_update_end(&stats.syncp);
dev->stats.rx_dropped += nss_cmn_rx_dropped_sum(&sync_stats->node_stats);
/* TODO: Update rx_dropped stats in ip6_update_offload_stats() */
@@ -316,11 +376,20 @@ static void nss_tunipip6_update_dev_stat
void nss_tunipip6_event_receive(void *if_ctx, struct nss_tunipip6_msg *tnlmsg)
{
struct net_device *netdev = NULL;
+
netdev = (struct net_device *)if_ctx;
switch (tnlmsg->cm.type) {
case NSS_TUNIPIP6_RX_STATS_SYNC:
- nss_tunipip6_update_dev_stats(netdev, (struct nss_tunipip6_stats_sync_msg *)&tnlmsg->msg.stats_sync);
+ /*
+ * Update netdevice statistics.
+ */
+ nss_tunipip6_update_dev_stats(netdev, tnlmsg);
+
+ /*
+ * Update NSS statistics for tunipip6.
+ */
+ nss_tunipip6_stats_sync(netdev, tnlmsg);
break;
default:
@@ -415,7 +484,7 @@ static void nss_tunipip6_dev_parse_param
tnlcfg->ttl_inherit = false;
tnlcfg->tos_inherit = true;
tnlcfg->frag_id_update = frag_id_update;
-
+ tnlcfg->fmr_max = NSS_TUNIPIP6_MAX_FMR;
/*
* Flow Label In kernel is stored in big endian format.
*/
@@ -454,9 +523,9 @@ static void nss_connmgr_tunipip6_configu
tunnel = (struct ip6_tnl *)netdev_priv(netdev);
/*
- * Configure FMR table up to NSS_TUNIPIP6_MAX_FMR_NUMBER, the rest will be forwarded to BR
+ * Configure FMR table up to NSS_TUNIPIP6_MAX_FMR, the rest will be forwarded to BR
*/
- for (fmr = tunnel->parms.fmrs; fmr && fmr_number < NSS_TUNIPIP6_MAX_FMR_NUMBER; fmr = fmr->next, fmr_number++) {
+ for (fmr = tunnel->parms.fmrs; fmr && fmr_number < NSS_TUNIPIP6_MAX_FMR; fmr = fmr->next, fmr_number++) {
/*
* Prepare "rulecfg"
*/
@@ -497,6 +566,7 @@ enum nss_connmgr_tunipip6_err_codes nss_
int inner_ifnum, outer_ifnum;
uint32_t features = 0;
nss_tx_status_t status;
+ struct nss_tunipip6_instance *ntii;
#if IS_ENABLED(CONFIG_MAP_E_SUPPORT)
#ifndef DRAFT03_SUPPORT
@@ -626,7 +696,7 @@ configure_tunnel:
status = nss_tunipip6_tx_sync(nss_ctx, &tnlmsg);
if (status != NSS_TX_SUCCESS) {
nss_tunipip6_warning("%px: Tunnel up command error %d\n", netdev, status);
- goto config_fail;
+ goto context_alloc_fail;
}
/*
@@ -644,12 +714,28 @@ configure_tunnel:
status = nss_tunipip6_tx_sync(nss_ctx, &tnlmsg);
if (status != NSS_TX_SUCCESS) {
nss_tunipip6_warning("%px: Tunnel up command error %d\n", netdev, status);
- goto config_fail;
+ goto context_alloc_fail;
}
+ /*
+ * Initialize tunipip6 instance.
+ */
+ ntii = nss_tunipip6_alloc_instance(netdev, inner_ifnum, outer_ifnum);
+ if (!ntii) {
+ nss_tunipip6_warning("%px: Not able to create tunipip6 instance\n", netdev);
+ goto context_alloc_fail;
+ }
+
+ /*
+ * Add the new tunipip6 instance to the global list.
+ */
+ spin_lock_bh(&tunipip6_ctx.lock);
+ list_add(&ntii->list, &tunipip6_ctx.dev_list);
+ spin_unlock_bh(&tunipip6_ctx.lock);
+
return NSS_CONNMGR_TUNIPIP6_SUCCESS;
-config_fail:
+context_alloc_fail:
nss_unregister_tunipip6_if(outer_ifnum);
outer_reg_fail:
nss_unregister_tunipip6_if(inner_ifnum);
@@ -675,6 +761,8 @@ EXPORT_SYMBOL(nss_connmgr_tunipip6_creat
*/
enum nss_connmgr_tunipip6_err_codes nss_connmgr_tunipip6_destroy_interface(struct net_device *netdev)
{
+ enum nss_connmgr_tunipip6_err_codes ret;
+
/*
* Validate netdev for ipv6-in-ipv4 Tunnel
*/
@@ -682,7 +770,20 @@ enum nss_connmgr_tunipip6_err_codes nss_
return NSS_CONNMGR_TUNIPIP6_NETDEV_TYPE_FAILURE;
}
- return _nss_tunipip6_dyn_interface_destroy(netdev);
+ /*
+ * Destroy tunipip6 NSS context.
+ */
+ ret = _nss_tunipip6_dyn_interface_destroy(netdev);
+ if (ret != NSS_CONNMGR_TUNIPIP6_SUCCESS) {
+ nss_tunipip6_warning("%px: Not able to destroy NSS context. Err: %d\n", netdev, ret);
+ return ret;
+ }
+
+ /*
+ * Find and free the tunipip6 instance.
+ */
+ ret = nss_tunipip6_find_and_free_instance(netdev);
+ return ret;
}
EXPORT_SYMBOL(nss_connmgr_tunipip6_destroy_interface);
@@ -941,6 +1042,39 @@ static int nss_tunipip6_dev_event(struct
}
/*
+ * nss_tunipip6_destroy_interface_all()
+ * Destroy NSS interfaces and free instance for all tunipip6 interfaces.
+ */
+static void nss_tunipip6_destroy_interface_all(void)
+{
+ struct net_device *netdev;
+ struct dentry *dentry;
+ struct nss_tunipip6_instance *ntii;
+
+ spin_lock_bh(&tunipip6_ctx.lock);
+ ntii = list_first_entry_or_null(&tunipip6_ctx.dev_list, struct nss_tunipip6_instance, list);
+ do {
+ if (!ntii) {
+ spin_unlock_bh(&tunipip6_ctx.lock);
+ return;
+ }
+
+ netdev = ntii->dev;
+ dentry = ntii->dentry;
+ nss_tunipip6_free_instance(ntii);
+ spin_unlock_bh(&tunipip6_ctx.lock);
+
+ dev_put(netdev);
+ debugfs_remove(dentry);
+ _nss_tunipip6_dyn_interface_destroy(netdev);
+
+ spin_lock_bh(&tunipip6_ctx.lock);
+ ntii = list_first_entry_or_null(&tunipip6_ctx.dev_list, struct nss_tunipip6_instance, list);
+ } while (ntii);
+ spin_unlock_bh(&tunipip6_ctx.lock);
+}
+
+/*
* Linux Net device Notifier
*/
struct notifier_block nss_tunipip6_notifier = {
@@ -965,6 +1099,20 @@ int __init nss_tunipip6_init_module(void
NSS_CLIENT_BUILD_ID);
/*
+ * Initialize lock and dev list.
+ */
+ INIT_LIST_HEAD(&tunipip6_ctx.dev_list);
+ spin_lock_init(&tunipip6_ctx.lock);
+
+ /*
+ * Create the debugfs directory for statistics.
+ */
+ if (!nss_tunipip6_stats_dentry_init()) {
+ nss_tunipip6_trace("Failed to initialize debugfs\n");
+ return -1;
+ }
+
+ /*
* Do not register net device notification for
* custom tunnel. Net device notification is used only
* for standard tunnel.
@@ -1000,6 +1148,16 @@ void __exit nss_tunipip6_exit_module(voi
#endif
/*
+ * Free Host and NSS tunipip6 instances.
+ */
+ nss_tunipip6_destroy_interface_all();
+
+ /*
+ * De-initialize debugfs.
+ */
+ nss_tunipip6_stats_dentry_deinit();
+
+ /*
* Unregister net device notification for standard tunnel.
*/
if (!enable_custom) {
--- /dev/null
+++ b/tunipip6/nss_connmgr_tunipip6_priv.h
@@ -0,0 +1,94 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+#ifndef __NSS_CONNMGR_TUNIPIP6_PRIV_H_
+#define __NSS_CONNMGR_TUNIPIP6_PRIV_H_
+
+#include "nss_connmgr_tunipip6_stats.h"
+#include <linux/debugfs.h>
+
+/*
+ * tunipip6 context
+ */
+extern struct nss_tunipip6_context tunipip6_ctx;
+
+/*
+ * NSS tunipip6 debug macros
+ */
+#if (NSS_TUNIPIP6_DEBUG_LEVEL < 1)
+#define nss_tunipip6_assert(fmt, args...)
+#else
+#define nss_tunipip6_assert(c) if (!(c)) { BUG_ON(!(c)); }
+#endif
+
+/*
+ * Compile messages for dynamic enable/disable
+ */
+#if defined(CONFIG_DYNAMIC_DEBUG)
+#define nss_tunipip6_warning(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define nss_tunipip6_info(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define nss_tunipip6_trace(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#else /* CONFIG_DYNAMIC_DEBUG */
+/*
+ * Statically compile messages at different levels
+ */
+#if (NSS_TUNIPIP6_DEBUG_LEVEL < 2)
+#define nss_tunipip6_warning(s, ...)
+#else
+#define nss_tunipip6_warning(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#endif
+
+#if (NSS_TUNIPIP6_DEBUG_LEVEL < 3)
+#define nss_tunipip6_info(s, ...)
+#else
+#define nss_tunipip6_info(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#endif
+
+#if (NSS_TUNIPIP6_DEBUG_LEVEL < 4)
+#define nss_tunipip6_trace(s, ...)
+#else
+#define nss_tunipip6_trace(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#endif
+#endif /* CONFIG_DYNAMIC_DEBUG */
+
+extern struct nss_tunipip6_context tunipip6_ctx;
+
+/*
+ * tunipip6 global context structure.
+ */
+struct nss_tunipip6_context {
+ struct list_head dev_list; /* List of tunipip6 interface instances */
+ struct dentry *tunipip6_dentry_dir; /* tunipip6 debugfs directory entry */
+ spinlock_t lock; /* Lock to protect list. */
+};
+
+/*
+ * tunipip6 interface instance structure.
+ */
+struct nss_tunipip6_instance {
+ struct list_head list; /* List of tunipip6 interface instance */
+ struct net_device *dev; /* tunipip6 netdevice */
+ struct dentry *dentry; /* debugfs entry for this tunnel device */
+ struct nss_tunipip6_stats stats; /* tunipip6 statistics */
+ uint32_t inner_ifnum; /* tunipip6 inner dynamic interface */
+ uint32_t outer_ifnum; /* tunipip6 outer dynamic interface */
+};
+
+struct nss_tunipip6_instance *nss_tunipip6_find_instance(struct net_device *dev);
+
+#endif /* __NSS_CONNMGR_TUNIPIP6_PRIV_H_ */
--- /dev/null
+++ b/tunipip6/nss_connmgr_tunipip6_stats.c
@@ -0,0 +1,225 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+#include <nss_api_if.h>
+#include "nss_connmgr_tunipip6_priv.h"
+
+/*
+ * nss_tunipip6_stats_str
+ * tunipip6 statistics strings for NSS tunnel stats
+ */
+static int8_t *nss_tunipip6_stats_str[NSS_TUNIPIP6_STATS_MAX] = {
+ "rx pkts",
+ "rx bytes",
+ "tx pkts",
+ "tx bytes",
+ "rx queue 0 dropped",
+ "rx queue 1 dropped",
+ "rx queue 2 dropped",
+ "rx queue 3 dropped",
+ "encap low headroom",
+ "encap unhandled_protocol",
+ "encap enqueue fail",
+ "encap tunnel exist",
+ "encap total fmr_count",
+ "encap fmr add count",
+ "encap fmr del count",
+ "encap fmr flush count",
+ "encap fmr update_count",
+ "encap fmr add_fail count",
+ "encap fmr del_fail count",
+ "encap error no fmr",
+ "encap bmr add count",
+ "encap bmr del count",
+ "encap error bmr exist",
+ "encap error no bmr",
+ "decap enqueue fail",
+};
+
+/*
+ * nss_tunipip6_stats_show()
+ * Read tunipip6 tunnel statistics
+ */
+static int nss_tunipip6_stats_show(struct seq_file *m, void __attribute__((unused))*p)
+{
+ int i;
+ struct nss_tunipip6_instance *tun_inst;
+ struct nss_tunipip6_stats *tunipip6_tunnel_stats;
+
+ tun_inst = vzalloc(sizeof(struct nss_tunipip6_instance));
+ if (!tun_inst) {
+ nss_tunipip6_warning("Failed to allocate memory for tun_inst\n");
+ return -ENOMEM;
+ }
+
+ tunipip6_tunnel_stats = vzalloc(sizeof(struct nss_tunipip6_stats));
+ if (!tunipip6_tunnel_stats) {
+ nss_tunipip6_warning("Failed to allocate memory for tunipip6_tunnel_stats\n");
+ vfree(tun_inst);
+ return -ENOMEM;
+ }
+
+ /*
+ * Copy the tunnel and stats information from the tunnel instance.
+ */
+ spin_lock_bh(&tunipip6_ctx.lock);
+ memcpy(tun_inst, m->private, sizeof(struct nss_tunipip6_instance));
+ memcpy(tunipip6_tunnel_stats, &tun_inst->stats, sizeof(struct nss_tunipip6_stats));
+ spin_unlock_bh(&tunipip6_ctx.lock);
+
+ seq_printf(m, "\n\tInner ifnum %u stats:\n", tun_inst->inner_ifnum);
+ for (i = 0; i < NSS_TUNIPIP6_STATS_MAX; i++) {
+ seq_printf(m, "\t\t%s = %llu\n",
+ nss_tunipip6_stats_str[i],
+ tunipip6_tunnel_stats->inner_stats[i]);
+ }
+
+ seq_printf(m, "\n\tOuter ifnum %u stats:\n", tun_inst->outer_ifnum);
+ for (i = 0; i < NSS_TUNIPIP6_STATS_MAX; i++) {
+ seq_printf(m, "\t\t%s = %llu\n",
+ nss_tunipip6_stats_str[i],
+ tunipip6_tunnel_stats->outer_stats[i]);
+ }
+
+ seq_printf(m, "\n%s tunnel stats end\n\n", tun_inst->dev->name);
+ vfree(tun_inst);
+ vfree(tunipip6_tunnel_stats);
+ return 0;
+}
+
+/*
+ * nss_tunipip6_stats_open()
+ */
+static int nss_tunipip6_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, nss_tunipip6_stats_show, inode->i_private);
+}
+
+/*
+ * nss_tunipip6_stats_update()
+ * Update inner or outer node statistics
+ */
+static void nss_tunipip6_stats_update(uint64_t *stats, struct nss_tunipip6_stats_sync_msg *stats_msg)
+{
+ uint32_t i, *src;
+ uint64_t *dest = stats;
+
+ src = &stats_msg->node_stats.rx_packets;
+ for (i = NSS_TUNIPIP6_STATS_RX_PKTS; i < NSS_TUNIPIP6_STATS_MAX; i++, src++, dest++) {
+ *dest += *src;
+ }
+}
+
+/*
+ * nss_tunipip6_stats_sync()
+ * Sync function for tunipip6 statistics
+ */
+void nss_tunipip6_stats_sync(struct net_device *dev, struct nss_tunipip6_msg *ntm)
+{
+ uint32_t ifnum = ntm->cm.interface;
+ struct nss_tunipip6_stats_sync_msg *stats = &ntm->msg.stats_sync;
+ struct nss_tunipip6_instance *ntii;
+ struct nss_tunipip6_stats *s;
+
+ spin_lock_bh(&tunipip6_ctx.lock);
+ ntii = nss_tunipip6_find_instance(dev);
+ if (!ntii) {
+ spin_unlock_bh(&tunipip6_ctx.lock);
+ nss_tunipip6_warning("%px: Not able to find context for device: %s\n", dev, dev->name);
+ return;
+ }
+
+ s = &ntii->stats;
+ if (ntii->inner_ifnum == ifnum) {
+ nss_tunipip6_stats_update(s->inner_stats, stats);
+ } else if (ntii->outer_ifnum == ifnum) {
+ nss_tunipip6_stats_update(s->outer_stats, stats);
+ } else {
+ nss_tunipip6_warning("%px: Netdev=%s invalid interface number. Interface No: %u\n", dev, dev->name, ifnum);
+ }
+
+ spin_unlock_bh(&tunipip6_ctx.lock);
+}
+
+/*
+ * nss_tunipip6_stats_ops
+ * File operations for tunipip6 tunnel stats
+ */
+static const struct file_operations nss_tunipip6_stats_ops = { \
+ .open = nss_tunipip6_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+/*
+ * nss_tunipip6_stats_dentry_destroy()
+ * Remove debufs file for given tunnel.
+ */
+void nss_tunipip6_stats_dentry_destroy(struct nss_tunipip6_instance *tun_inst)
+{
+ debugfs_remove(tun_inst->dentry);
+}
+
+/*
+ * nss_tunipip6_stats_dentry_create()
+ * Create dentry for a given tunnel.
+ */
+bool nss_tunipip6_stats_dentry_create(struct nss_tunipip6_instance *tun_inst)
+{
+ char dentry_name[IFNAMSIZ];
+
+ scnprintf(dentry_name, sizeof(dentry_name), "%s", tun_inst->dev->name);
+ tun_inst->dentry = debugfs_create_file(dentry_name, S_IRUGO,
+ tunipip6_ctx.tunipip6_dentry_dir, tun_inst, &nss_tunipip6_stats_ops);
+ if (!tun_inst->dentry) {
+ nss_tunipip6_warning("Debugfs file creation failed for tun %s\n", tun_inst->dev->name);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * nss_tunipip6_stats_dentry_deinit()
+ * Cleanup the debugfs tree.
+ */
+void nss_tunipip6_stats_dentry_deinit(void)
+{
+ if (tunipip6_ctx.tunipip6_dentry_dir) {
+ debugfs_remove_recursive(tunipip6_ctx.tunipip6_dentry_dir);
+ }
+}
+
+/*
+ * nss_tunipip6_stats_dentry_init()
+ * Create tunipip6 tunnel statistics debugfs entry.
+ */
+bool nss_tunipip6_stats_dentry_init(void)
+{
+ /*
+ * Initialize debugfs directory.
+ */
+ tunipip6_ctx.tunipip6_dentry_dir = debugfs_create_dir("qca-nss-tunipip6", NULL);
+ if (!tunipip6_ctx.tunipip6_dentry_dir) {
+ nss_tunipip6_warning("Failed to create debug entry for subsystem: qca-nss-tunipip6\n");
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+++ b/tunipip6/nss_connmgr_tunipip6_stats.h
@@ -0,0 +1,73 @@
+/*
+ ******************************************************************************
+ * Copyright (c) 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * ****************************************************************************
+ */
+
+#ifndef _NSS_CONNMGR_TUNIPIP6_STATS_H_
+#define _NSS_CONNMGR_TUNIPIP6_STATS_H_
+
+struct nss_tunipip6_instance;
+
+/*
+ * tunipip6 statistic counters
+ */
+enum nss_tunipip6_stats_type {
+ NSS_TUNIPIP6_STATS_RX_PKTS,
+ NSS_TUNIPIP6_STATS_RX_BYTES,
+ NSS_TUNIPIP6_STATS_TX_PKTS,
+ NSS_TUNIPIP6_STATS_TX_BYTES,
+ NSS_TUNIPIP6_STATS_RX_QUEUE_0_DROPPED,
+ NSS_TUNIPIP6_STATS_RX_QUEUE_1_DROPPED,
+ NSS_TUNIPIP6_STATS_RX_QUEUE_2_DROPPED,
+ NSS_TUNIPIP6_STATS_RX_QUEUE_3_DROPPED,
+ NSS_TUNIPIP6_STATS_EXCEP_ENCAP_LOW_HEADROOM,
+ NSS_TUNIPIP6_STATS_EXCEP_ENCAP_UNHANDLED_PROTOCOL,
+ NSS_TUNIPIP6_STATS_DROP_ENCAP_ENQUEUE_FAIL,
+ NSS_TUNIPIP6_STATS_CONFIG_ERR_TUNNEL,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_TOTAL_FMR,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_FMR_ADD,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_FMR_DEL,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_FMR_FLUSH,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_FMR_UPDATE,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_FMR_ADD_FAIL,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_FMR_DEL_FAIL,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_ERR_NO_FMR,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_BMR_ADD,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_BMR_DEL,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_ERR_BMR_EXIST,
+ NSS_TUNIPIP6_STATS_CONFIG_ENCAP_ERR_NO_BMR,
+ NSS_TUNIPIP6_STATS_DROP_DECAP_ENQUEUE_FAIL,
+ NSS_TUNIPIP6_STATS_MAX,
+};
+
+/*
+ * tunipip6 statistics
+ */
+struct nss_tunipip6_stats {
+ uint64_t inner_stats[NSS_TUNIPIP6_STATS_MAX];
+ uint64_t outer_stats[NSS_TUNIPIP6_STATS_MAX];
+};
+
+/*
+ * tunipip6 statistics API
+ */
+extern void nss_tunipip6_stats_sync(struct net_device *dev, struct nss_tunipip6_msg *ntm);
+extern void nss_tunipip6_stats_dentry_deinit(void);
+extern bool nss_tunipip6_stats_dentry_init(void);
+extern void nss_tunipip6_stats_dentry_destroy(struct nss_tunipip6_instance *tun_inst);
+extern bool nss_tunipip6_stats_dentry_create(struct nss_tunipip6_instance *tun_inst);
+
+#endif /* _NSS_CONNMGR_TUNIPIP6_STATS_H_ */
--- a/tunipip6/nss_connmgr_tunipip6_sysctl.c
+++ b/tunipip6/nss_connmgr_tunipip6_sysctl.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021, 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
@@ -61,7 +61,7 @@ static int nss_tunipip6_data_parser(stru
bool ipv4_prefix_valid = false, ipv4_prefix_len_valid = false, ipv6_suffix_len_valid = false;
bool rule_type_valid = false, ea_len_valid = false, psid_offset_valid = false, netdev_valid = false;
struct nss_connmgr_tunipip6_maprule_cfg mrcfg = {0};
- char *buf = kzalloc(MAX_PROC_SIZE, GFP_KERNEL);
+ char *buf;
enum nss_connmgr_tunipip6_err_codes status;
struct net_device *dev = NULL;
char *pfree;
@@ -69,7 +69,11 @@ static int nss_tunipip6_data_parser(stru
int ret;
int count;
+ if (!write) {
+ return -EINVAL;
+ }
+ buf = kzalloc(MAX_PROC_SIZE, GFP_KERNEL);
if (!buf) {
return -ENOMEM;
}
@@ -122,6 +126,7 @@ static int nss_tunipip6_data_parser(stru
if ((rule_type !=NSS_CONNMGR_TUNIPIP6_RULE_BMR) &&
(rule_type != NSS_CONNMGR_TUNIPIP6_RULE_FMR)) {
+ kfree(pfree);
goto fail;
}
rule_type_valid = true;
@@ -135,6 +140,7 @@ static int nss_tunipip6_data_parser(stru
}
if (frag_id != 0 && frag_id != 1) {
+ kfree(pfree);
goto fail;
}
continue;
@@ -396,9 +402,9 @@ static int nss_tunipip6_cmd_procfs_read_
b. To delete maprule(BMR):\n\
echo dev=<map-mape/MAP-E netdevice> rule_type=<1> > remove_map_rule\n\
3. To flush FMR entries:\n\
- echo dev=<map-mape/MAP-E netdevice> > flush_fmr_rule\n\
- 4. To enable/disable frag id:\n\
- echo frag_id_update=<0/1> > frag_id\n\
+ echo dev=<map-mape/MAP-E netdevice> > flush_fmr_rule\n");
+ pr_info("\t\t\t4. To enable/disable frag id: \n\
+ echo frag_id_update=<0/1> > frag_id \n\
=====end of help=====\n");
*lenp = 0;
return ret;