Merge "[qca-nss-drv] Add GRE redir mark static interface"
diff --git a/Makefile b/Makefile
index 6605399..0fd7b9f 100644
--- a/Makefile
+++ b/Makefile
@@ -39,6 +39,9 @@
nss_gre_redir_lag_us_log.o \
nss_gre_redir_lag_us_stats.o \
nss_gre_redir_stats.o \
+ nss_gre_redir_mark.o \
+ nss_gre_redir_mark_log.o \
+ nss_gre_redir_mark_stats.o \
nss_gre_tunnel.o \
nss_gre_tunnel_log.o \
nss_gre_tunnel_stats.o \
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 18df2d3..8ed1aff 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -78,6 +78,7 @@
#include "nss_pm.h"
#include "nss_freq.h"
#include "nss_tstamp.h"
+#include "nss_gre_redir_mark.h"
#endif
/**
@@ -96,7 +97,7 @@
#define NSS_MAX_PHYSICAL_INTERFACES 8 /**< Maximum number of physical interfaces. */
#define NSS_MAX_VIRTUAL_INTERFACES 16 /**< Maximum number of virtual interfaces. */
#define NSS_MAX_TUNNEL_INTERFACES 4 /**< Maximum number of tunnel interfaces. */
-#define NSS_MAX_SPECIAL_INTERFACES 56 /**< Maximum number of special interfaces. */
+#define NSS_MAX_SPECIAL_INTERFACES 57 /**< Maximum number of special interfaces. */
#define NSS_MAX_WIFI_RADIO_INTERFACES 3 /**< Maximum number of radio interfaces. */
/*
@@ -228,6 +229,8 @@
/**< Special interface number for timestamp transmit. */
#define NSS_TSTAMP_RX_INTERFACE (NSS_SPECIAL_IF_START + 55)
/**< Special interface number for timestamp receive. */
+#define NSS_GRE_REDIR_MARK_INTERFACE (NSS_SPECIAL_IF_START + 56)
+ /**< Special interface number for GRE redirect mark. */
/**
* Wireless Multimedia Extention Access Category to TID. @hideinitializer
diff --git a/exports/nss_gre_redir_mark.h b/exports/nss_gre_redir_mark.h
new file mode 100644
index 0000000..8d71f51
--- /dev/null
+++ b/exports/nss_gre_redir_mark.h
@@ -0,0 +1,278 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2019, 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.
+ **************************************************************************
+ */
+
+/**
+ * @file nss_gre_redir_mark.h
+ * NSS GRE Redirect mark interface definitions.
+ */
+
+#ifndef __NSS_GRE_REDIR_MARK_H
+#define __NSS_GRE_REDIR_MARK_H
+
+/**
+ * nss_gre_redir_mark messages
+ * Message types for GRE redirect mark requests and responses.
+ */
+enum nss_gre_redir_mark_msg_types {
+ NSS_GRE_REDIR_MARK_REG_CB_MSG, /**< Register callback configuration message. */
+ NSS_GRE_REDIR_MARK_STATS_SYNC_MSG, /**< Statistics synchronization message. */
+ NSS_GRE_REDIR_MARK_MSG_MAX, /**< Maximum message type. */
+};
+
+/**
+ * nss_gre_redir_mark errors
+ * Error codes for GRE redirect mark configuration message.
+ */
+enum nss_gre_redir_mark_error_types {
+ NSS_GRE_REDIR_MARK_ERROR_NONE, /**< Configuration successful. */
+ NSS_GRE_REDIR_MARK_ERROR_INV_IF_NUM, /**< Invalid interface number for callback registration. */
+ NSS_GRE_REDIR_MARK_ERROR_INV_ETH_TYPE, /**< Invalid Ethernet type for the destination interface. */
+ NSS_GRE_REDIR_MARK_ERROR_TYPE_MAX
+};
+
+/**
+ * nss_gre_redir_mark_metadata
+ * HLOS to NSS per packet downstream metadata.
+ */
+struct nss_gre_redir_mark_metadata {
+ uint32_t dst_ifnum; /**< Destination Tx interface number. */
+ uint8_t wifi_tid; /**< TID value. */
+ uint8_t app_id; /**< Application ID. */
+ uint16_t hw_hash_idx; /**< Hardware AST hash index value. */
+ uint32_t tx_status; /**< Tx status. */
+ uint16_t offset; /**< Buffer offset from the metadata. */
+ uint16_t magic; /**< Metadata magic. */
+};
+
+/**
+ * nss_gre_redir_mark_stats
+ * GRE redirect mark statistics.
+ */
+struct nss_gre_redir_mark_stats_sync_msg {
+ struct nss_cmn_node_stats node_stats; /**< Common node statistics. */
+ uint32_t hlos_magic_fail; /**< HLOS magic fail count. */
+ uint32_t invalid_dst_drop; /**< Invalid Tx interface drop count. */
+ uint32_t dst_enqueue_success; /**< Next egress interface enqueue success count. */
+ uint32_t dst_enqueue_drop; /**< Next egress interface enqueue drop count. */
+ uint32_t inv_appid; /**< Invalid application ID for the Tx completion packets. */
+ uint32_t headroom_unavail; /**< Packet headroom unavailable to write metadata. */
+ uint32_t tx_completion_success; /**< Tx completion host enqueue success count. */
+ uint32_t tx_completion_drop; /**< Tx completion host enqueue drop count. */
+};
+
+/**
+ * nss_gre_redir_mark_register_cb_msg
+ * Tx completion function register configuration message.
+ */
+struct nss_gre_redir_mark_register_cb_msg {
+ uint32_t nss_if_num; /**< NSS Tx interface number on which callback needs to be registered. */
+};
+
+/**
+ * nss_gre_redir_mark_msg
+ * Structure that describes the interface message.
+ */
+struct nss_gre_redir_mark_msg {
+ struct nss_cmn_msg cm; /**< Common message. */
+
+ /**
+ * Payload of a GRE redirect mark message.
+ */
+ union {
+ struct nss_gre_redir_mark_register_cb_msg reg_cb_msg;
+ /**< Configuration message to register for callback on completion. */
+ struct nss_gre_redir_mark_stats_sync_msg stats_sync;
+ /**< Mark node statistics synchronization. */
+ } msg; /**< Message payload for GRE redirect mark messages exchanged with NSS core. */
+};
+
+/**
+ * Callback function for receiving GRE redirect mark data.
+ *
+ * @datatypes
+ * net_device \n
+ * sk_buff \n
+ * napi_struct
+ *
+ * @param[in] netdev Pointer to the associated network device.
+ * @param[in] skb Pointer to the data socket buffer.
+ * @param[in] napi Pointer to the NAPI structure.
+ */
+typedef void (*nss_gre_redir_mark_data_callback_t)(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi);
+
+/**
+ * Callback function for receiving GRE redirect mark messages.
+ *
+ * @datatypes
+ * nss_cmn_msg
+ *
+ * @param[in] app_data Pointer to the application context of the message.
+ * @param[in] msg Pointer to the message data.
+ */
+typedef void (*nss_gre_redir_mark_msg_callback_t)(void *app_data, struct nss_cmn_msg *msg);
+
+/**
+ * nss_gre_redir_mark_unregister_if
+ * Deregisters a GRE redirect mark interface from the NSS.
+ *
+ * @param[in] if_num GRE redirect mark interface number.
+ *
+ * @return
+ * None.
+ *
+ * @dependencies
+ * The GRE redirect mark interface must have been previously registered.
+ *
+ * @return
+ * True if successful, else false.
+ */
+extern bool nss_gre_redir_mark_unregister_if(uint32_t if_num);
+
+/**
+ * nss_gre_redir_mark_tx_buf
+ * Sends data buffers to NSS firmware asynchronously.
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * sk_buff
+ *
+ * @param[in] nss_ctx Pointer to the NSS context.
+ * @param[in] os_buf Pointer to the OS buffer (e.g. skbuff).
+ * @param[in] if_num GRE redirect mark interface number.
+ *
+ * @return
+ * Status of the Tx operation.
+ */
+extern nss_tx_status_t nss_gre_redir_mark_tx_buf(struct nss_ctx_instance *nss_ctx, struct sk_buff *os_buf,
+ uint32_t if_num);
+
+/**
+ * nss_gre_redir_exception_ds_reg_cb
+ * Configure a callback on VAP for downstream GRE exception flows.
+ *
+ * @datatypes
+ * nss_gre_redir_exception_ds_reg_cb_msg
+ *
+ * @param[in] ifnum NSS interface number.
+ * @param[in] ngrcm Downstream exception callback registration message.
+ *
+ * @return
+ * Status of Tx operation.
+ */
+extern nss_tx_status_t nss_gre_redir_mark_reg_cb(int ifnum,
+ struct nss_gre_redir_mark_register_cb_msg *ngrcm);
+
+/**
+ * nss_gre_redir_mark_tx_msg
+ * Sends GRE redirect mark messages.
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * nss_gre_redir_msg
+ *
+ * @param[in] nss_ctx Pointer to the NSS context.
+ * @param[in] msg Pointer to the message data.
+ *
+ * @return
+ * Status of the Tx operation.
+ */
+extern nss_tx_status_t nss_gre_redir_mark_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_gre_redir_mark_msg *msg);
+
+/**
+ * nss_gre_redir_mark_tx_msg_sync
+ * Sends messages to NSS firmware synchronously.
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * nss_gre_redir_mark_msg
+ *
+ * @param[in] nss_ctx NSS core context.
+ * @param[in] ngrm Pointer to GRE redirect mark message data.
+ *
+ * @return
+ * Status of Tx operation.
+ */
+extern nss_tx_status_t nss_gre_redir_mark_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_redir_mark_msg *ngrm);
+
+/**
+ * nss_gre_redir_mark_get_stats
+ * Gets GRE redirect mark statistics.
+ *
+ * @datatypes
+ * nss_gre_redir_mark_stats
+ *
+ * @param[out] stats Pointer to the memory address, which must be large enough to
+ * hold all the statistics.
+ *
+ * @return
+ * TRUE or FALSE.
+ */
+extern bool nss_gre_redir_mark_get_stats(void *stats);
+
+/**
+ * nss_gre_redir_alloc_and_register_node
+ * Registers GRE redirect mark static node with NSS.
+ *
+ * @datatypes
+ * net_device \n
+ * nss_gre_redir_mark_data_callback_t \n
+ * nss_gre_redir_mark_msg_callback_t
+ *
+ * @param[in] netdev Pointer to the associated network device.
+ * @param[in] if_num NSS interface number.
+ * @param[in] cb_func_data Callback for the data.
+ * @param[in] cb_func_msg Callback for the message.
+ * @param[in] features Data socket buffer types supported by this interface.
+ *
+ * @return
+ * NSS interface number allocated.
+ */
+extern struct nss_ctx_instance *nss_gre_redir_mark_register_if(struct net_device *netdev, uint32_t if_num,
+ nss_gre_redir_mark_data_callback_t cb_func_data, nss_gre_redir_mark_msg_callback_t cb_func_msg,
+ uint32_t features);
+
+/**
+ * nss_gre_redir_mark_get_context
+ * Gets the GRE redirect mark context.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_gre_redir_mark_get_context(void);
+
+/**
+ * nss_gre_redir_mark_get_dentry
+ * Returns directory entry created in debug filesystem for statistics.
+ *
+ * @return
+ * Pointer to created directory entry for GRE redirect mark.
+ */
+extern struct dentry *nss_gre_redir_mark_get_dentry(void);
+
+/*
+ * nss_gre_redir_mark_get_device
+ * Gets the original device from probe.
+ *
+ * @return
+ * Pointer to the device.
+ */
+extern struct device *nss_gre_redir_mark_get_device(void);
+
+/**
+ * @}
+ */
+
+#endif /* __NSS_GRE_REDIR_MARK_H */
diff --git a/nss_core.h b/nss_core.h
index c217140..47e49cc 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -608,6 +608,7 @@
uint8_t qvpn_handler_id;
uint8_t pvxlan_handler_id;
uint8_t igs_handler_id;
+ uint8_t gre_redir_mark_handler_id;
/*
* Data/Message callbacks for various interfaces
@@ -913,6 +914,8 @@
/* Does this core handle pvxlan? */
enum nss_feature_enabled igs_enabled;
/* Does this core handle igs? */
+ enum nss_feature_enabled gre_redir_mark_enabled;
+ /* Does this core handle GRE redir mark? */
};
#endif
diff --git a/nss_gre_redir_mark.c b/nss_gre_redir_mark.c
new file mode 100644
index 0000000..e413030
--- /dev/null
+++ b/nss_gre_redir_mark.c
@@ -0,0 +1,403 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2019, 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_tx_rx_common.h"
+#include "nss_gre_redir_mark_stats.h"
+#include "nss_gre_redir_mark_log.h"
+#define NSS_GRE_REDIR_MARK_TX_TIMEOUT 3000 /* 3 Seconds */
+
+/*
+ * Private data structure for handling synchronous messaging.
+ */
+static struct {
+ struct semaphore sem;
+ struct completion complete;
+ int response;
+} nss_gre_redir_mark_pvt;
+
+/*
+ * Spinlock to update GRE redir mark stats.
+ */
+static DEFINE_SPINLOCK(nss_gre_redir_mark_stats_lock);
+
+/*
+ * Global GRE redir mark stats structure.
+ */
+static struct nss_gre_redir_mark_stats gre_mark_stats;
+
+/*
+ * nss_gre_redir_mark_msg_sync_callback()
+ * Callback to handle the completion of HLOS-->NSS messages.
+ */
+static void nss_gre_redir_mark_msg_sync_callback(void *app_data, struct nss_gre_redir_mark_msg *nim)
+{
+ nss_gre_redir_mark_pvt.response = NSS_TX_SUCCESS;
+ if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
+ nss_warning("GRE mark Error response %d\n", nim->cm.response);
+ nss_gre_redir_mark_pvt.response = NSS_TX_FAILURE;
+ }
+
+ complete(&nss_gre_redir_mark_pvt.complete);
+}
+
+/*
+ * nss_gre_redir_mark_stats_sync()
+ * Update GRE redir mark stats.
+ */
+static void nss_gre_redir_mark_stats_sync(struct nss_ctx_instance *nss_ctx, int if_num, struct nss_gre_redir_mark_stats_sync_msg *ngss)
+{
+ struct net_device *dev;
+ dev = nss_cmn_get_interface_dev(nss_ctx, if_num);
+ if (!dev) {
+ nss_warning("%p: Unable to find net device for the interface %d\n", nss_ctx, if_num);
+ return;
+ }
+
+ if (if_num != NSS_GRE_REDIR_MARK_INTERFACE) {
+ nss_warning("%p: Unknown type for interface %d\n", nss_ctx, if_num);
+ return;
+ }
+
+ /*
+ * Update the stats in exclusive mode to prevent the read from the process
+ * context through debug fs.
+ */
+ spin_lock_bh(&nss_gre_redir_mark_stats_lock);
+
+ /*
+ * Update the common node stats
+ */
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_TX_PKTS] += ngss->node_stats.tx_packets;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_TX_BYTES] += ngss->node_stats.tx_bytes;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_RX_PKTS] += ngss->node_stats.rx_packets;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_RX_BYTES] += ngss->node_stats.rx_bytes;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_RX_DROPS] += nss_cmn_rx_dropped_sum(&(ngss->node_stats));
+
+ /*
+ * Update the GRE redir mark specific stats
+ */
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_HLOS_MAGIC_FAILED] += ngss->hlos_magic_fail;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_INV_DST_IF_DROPS] += ngss->invalid_dst_drop;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_DST_IF_ENQUEUE] += ngss->dst_enqueue_success;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_DST_IF_ENQUEUE_DROPS] += ngss->dst_enqueue_drop;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_INV_APPID] += ngss->inv_appid;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_HEADROOM_UNAVAILABLE] += ngss->headroom_unavail;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_TX_COMPLETION_SUCCESS] += ngss->tx_completion_success;
+ gre_mark_stats.stats[NSS_GRE_REDIR_MARK_STATS_TX_COMPLETION_DROPS] += ngss->tx_completion_drop;
+
+ spin_unlock_bh(&nss_gre_redir_mark_stats_lock);
+}
+
+/*
+ * nss_gre_redir_mark_handler()
+ * Handle NSS to HLOS messages for GRE redir mark
+ */
+static void nss_gre_redir_mark_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, void *app_data)
+{
+ struct nss_gre_redir_mark_msg *ngrm = (struct nss_gre_redir_mark_msg *)ncm;
+ nss_gre_redir_mark_msg_callback_t cb;
+
+ NSS_VERIFY_CTX_MAGIC(nss_ctx);
+
+ /*
+ * Is this a valid request/response packet?
+ */
+ if (ncm->type >= NSS_GRE_REDIR_MARK_MSG_MAX) {
+ nss_warning("%p: received invalid message %d for GRE redir mark interface", nss_ctx, ncm->type);
+ return;
+ }
+
+ if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_gre_redir_mark_msg)) {
+ nss_warning("%p: length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
+ return;
+ }
+
+ /*
+ * Log failures
+ */
+ nss_core_log_msg_failures(nss_ctx, ncm);
+
+ /*
+ * Trace messages.
+ */
+ nss_gre_redir_mark_log_rx_msg((struct nss_gre_redir_mark_msg *)ncm);
+
+ if (ncm->type == NSS_GRE_REDIR_MARK_STATS_SYNC_MSG) {
+ nss_gre_redir_mark_stats_sync(nss_ctx, ncm->interface, &ngrm->msg.stats_sync);
+ }
+
+ /*
+ * Update the callback and app_data for NOTIFY messages, GRE redir mark sends all notify messages
+ * to the same callback/app_data. The app data here represent the netdevice of the GRE redir mark
+ * interface.
+ */
+ if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
+ ncm->cb = (nss_ptr_t)nss_top_main.if_rx_msg_callback[ncm->interface];
+ ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].ndev;
+ }
+
+ /*
+ * load and call the registered synchronous message callback.
+ */
+ cb = (nss_gre_redir_mark_msg_callback_t)ncm->cb;
+ if (unlikely(!cb)) {
+ return;
+ }
+
+ cb((void *)ncm->app_data, ncm);
+}
+
+/*
+ * nss_gre_redir_mark_get_stats()
+ * Get gre_redir tunnel stats.
+ */
+bool nss_gre_redir_mark_get_stats(void *stats_mem)
+{
+ struct nss_gre_redir_mark_stats *stats = (struct nss_gre_redir_mark_stats *)stats_mem;
+ if (!stats) {
+ nss_warning("No memory to copy GRE redir mark stats");
+ return false;
+ }
+
+ /*
+ * Copy the GRE redir mark stats in the memory.
+ */
+ spin_lock_bh(&nss_gre_redir_mark_stats_lock);
+ memcpy(stats, &gre_mark_stats, sizeof(struct nss_gre_redir_mark_stats));
+ spin_unlock_bh(&nss_gre_redir_mark_stats_lock);
+ return true;
+}
+EXPORT_SYMBOL(nss_gre_redir_mark_get_stats);
+
+/*
+ * nss_gre_redir_mark_reg_cb()
+ * Configure a callback on VAP.
+ */
+nss_tx_status_t nss_gre_redir_mark_reg_cb(int ifnum,
+ struct nss_gre_redir_mark_register_cb_msg *ngrcm)
+{
+ struct nss_gre_redir_mark_msg config;
+ struct nss_ctx_instance *nss_ctx __maybe_unused = nss_gre_redir_mark_get_context();
+ nss_tx_status_t status;
+ uint32_t vap_type;
+ uint32_t len = sizeof(struct nss_gre_redir_mark_register_cb_msg);
+
+ if (!nss_ctx) {
+ nss_warning("Unable to retrieve NSS context.\n");
+ return NSS_TX_FAILURE_BAD_PARAM;
+ }
+
+ vap_type = nss_dynamic_interface_get_type(nss_ctx, ngrcm->nss_if_num);
+ if ((vap_type != NSS_DYNAMIC_INTERFACE_TYPE_VAP)) {
+ nss_warning("%p: Incorrect type for vap interface type = %u", nss_ctx, vap_type);
+ return NSS_TX_FAILURE_BAD_PARAM;
+ }
+
+ /*
+ * Configure the node
+ */
+ nss_cmn_msg_init(&config.cm, NSS_GRE_REDIR_MARK_INTERFACE, NSS_GRE_REDIR_MARK_REG_CB_MSG, len, NULL, NULL);
+ config.msg.reg_cb_msg.nss_if_num = ngrcm->nss_if_num;
+
+ status = nss_gre_redir_mark_tx_msg_sync(nss_ctx, &config);
+ if (status != NSS_TX_SUCCESS) {
+ nss_warning("%p: Unable to register callback from GRE redir mark interface %d\n", nss_ctx, ifnum);
+ }
+
+ return status;
+}
+EXPORT_SYMBOL(nss_gre_redir_mark_reg_cb);
+
+/*
+ * nss_gre_redir_mark_tx_msg()
+ * Transmit a GRE MARK configuration message to NSS FW.
+ */
+nss_tx_status_t nss_gre_redir_mark_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_gre_redir_mark_msg *msg)
+{
+ struct nss_cmn_msg *ncm = &msg->cm;
+
+ /*
+ * Trace Messages
+ */
+ nss_gre_redir_mark_log_tx_msg(msg);
+
+ /*
+ * interface should be of type of redir mark
+ */
+ if (ncm->interface != NSS_GRE_REDIR_MARK_INTERFACE) {
+ nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
+ return NSS_TX_FAILURE;
+ }
+
+ if (ncm->type >= NSS_GRE_REDIR_MARK_MSG_MAX) {
+ nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+ return NSS_TX_FAILURE;
+ }
+
+ return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
+}
+EXPORT_SYMBOL(nss_gre_redir_mark_tx_msg);
+
+/*
+ * nss_gre_redir_mark_tx_msg_sync()
+ * Transmit a GRE redir mark message to NSS firmware synchronously.
+ */
+nss_tx_status_t nss_gre_redir_mark_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_redir_mark_msg *ngrm)
+{
+ nss_tx_status_t status;
+ int ret = 0;
+
+ /*
+ * Decrease the semaphore count to send the message exclusively.
+ */
+ down(&nss_gre_redir_mark_pvt.sem);
+ ngrm->cm.cb = (nss_ptr_t)nss_gre_redir_mark_msg_sync_callback;
+ ngrm->cm.app_data = (nss_ptr_t)NULL;
+ status = nss_gre_redir_mark_tx_msg(nss_ctx, ngrm);
+ if (status != NSS_TX_SUCCESS) {
+ nss_warning("%p: GRE redir mark tx_msg failed\n", nss_ctx);
+ up(&nss_gre_redir_mark_pvt.sem);
+ return status;
+ }
+
+ ret = wait_for_completion_timeout(&nss_gre_redir_mark_pvt.complete, msecs_to_jiffies(NSS_GRE_REDIR_MARK_TX_TIMEOUT));
+ if (!ret) {
+ nss_warning("%p: GRE redir mark message tx sync failed due to timeout\n", nss_ctx);
+ nss_gre_redir_mark_pvt.response = NSS_TX_FAILURE;
+ }
+
+ status = nss_gre_redir_mark_pvt.response;
+ up(&nss_gre_redir_mark_pvt.sem);
+ return status;
+}
+EXPORT_SYMBOL(nss_gre_redir_mark_tx_msg_sync);
+
+/*
+ * nss_gre_redir_mark_tx_buf()
+ * Send packet to GRE redir mark interface owned by NSS.
+ */
+nss_tx_status_t nss_gre_redir_mark_tx_buf(struct nss_ctx_instance *nss_ctx, struct sk_buff *os_buf, uint32_t if_num)
+{
+ nss_trace("%p: GRE redir mark If Tx packet, interface id:%d, data=%p", nss_ctx, if_num, os_buf->data);
+
+ /*
+ * We expect Tx packets to the GRE redir mark interface only.
+ */
+ if (if_num != NSS_GRE_REDIR_MARK_INTERFACE) {
+ nss_warning("%p: Invalid interface:%d for GRE redir mark packets\n", nss_ctx, if_num);
+ return NSS_TX_FAILURE_BAD_PARAM;
+ }
+
+ return nss_core_send_packet(nss_ctx, os_buf, if_num, 0);
+}
+EXPORT_SYMBOL(nss_gre_redir_mark_tx_buf);
+
+/*
+ * nss_gre_redir_mark_get_context()
+ * Return NSS GRE redir mark context.
+ */
+struct nss_ctx_instance *nss_gre_redir_mark_get_context(void)
+{
+ return &nss_top_main.nss[nss_top_main.gre_redir_mark_handler_id];
+}
+EXPORT_SYMBOL(nss_gre_redir_mark_get_context);
+
+/*
+ * nss_gre_redir_mark_unregister_if()
+ * Unregister dynamic node for GRE_REDIR_MARK redir.
+ */
+bool nss_gre_redir_mark_unregister_if(uint32_t if_num)
+{
+ struct nss_ctx_instance *nss_ctx __maybe_unused = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.gre_redir_handler_id];
+ struct net_device *dev;
+
+ nss_assert(nss_ctx);
+ nss_assert(if_num == NSS_GRE_REDIR_MARK_INTERFACE);
+
+ dev = nss_cmn_get_interface_dev(nss_ctx, if_num);
+
+ BUG_ON(!dev);
+
+ nss_core_unregister_subsys_dp(nss_ctx, if_num);
+ nss_top_main.if_rx_msg_callback[if_num] = NULL;
+ return true;
+}
+EXPORT_SYMBOL(nss_gre_redir_mark_unregister_if);
+
+/*
+ * nss_gre_redir_mark_register_if()
+ * Register staticr GRE redir mark interface with data-plane.
+ */
+struct nss_ctx_instance *nss_gre_redir_mark_register_if(struct net_device *netdev, uint32_t if_num,
+ nss_gre_redir_mark_data_callback_t cb_func_data, nss_gre_redir_mark_msg_callback_t cb_func_msg,
+ uint32_t features)
+{
+ struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.gre_redir_handler_id];
+
+ nss_assert(nss_ctx);
+ nss_assert(if_num == NSS_GRE_REDIR_MARK_INTERFACE);
+
+ /*
+ * Registering the interface with network data path.
+ */
+ nss_core_register_subsys_dp(nss_ctx, if_num, cb_func_data, NULL, NULL, netdev, features);
+ nss_top_main.if_rx_msg_callback[if_num] = cb_func_msg;
+ return nss_ctx;
+}
+EXPORT_SYMBOL(nss_gre_redir_mark_register_if);
+
+/*
+ * nss_gre_redir_mark_get_device()
+ * Gets the original device from probe.
+ */
+struct device *nss_gre_redir_mark_get_device(void)
+{
+ struct nss_ctx_instance *nss_ctx = nss_gre_redir_mark_get_context();
+ return nss_ctx->dev;
+}
+EXPORT_SYMBOL(nss_gre_redir_mark_get_device);
+
+/*
+ * nss_gre_redir_mark_register_handler()
+ * Register GRE redir mark and register handler
+ */
+void nss_gre_redir_mark_register_handler(void)
+{
+ struct nss_ctx_instance *nss_ctx = nss_gre_redir_mark_get_context();
+ struct dentry *gre_redir_mark_dentry = NULL;
+ uint32_t status = NSS_CORE_STATUS_FAILURE;
+
+ /*
+ * Create the debug fs entry for the stats.
+ */
+ gre_redir_mark_dentry = nss_gre_redir_mark_stats_dentry_create();
+ if (!gre_redir_mark_dentry) {
+ nss_warning("%p: Not able to create debugfs entry\n", nss_ctx);
+ return;
+ }
+
+ sema_init(&nss_gre_redir_mark_pvt.sem, 1);
+ init_completion(&nss_gre_redir_mark_pvt.complete);
+
+ nss_info("nss_gre_redir_mark_register_handler\n");
+ status = nss_core_register_handler(nss_ctx, NSS_GRE_REDIR_MARK_INTERFACE, nss_gre_redir_mark_handler, NULL);
+ if (status != NSS_CORE_STATUS_SUCCESS) {
+ debugfs_remove_recursive(gre_redir_mark_dentry);
+ gre_redir_mark_dentry = NULL;
+ nss_warning("%p: Not able to register handler for GRE redir mark with NSS core\n", nss_ctx);
+ return;
+ }
+}
diff --git a/nss_gre_redir_mark_log.c b/nss_gre_redir_mark_log.c
new file mode 100644
index 0000000..e99e6f2
--- /dev/null
+++ b/nss_gre_redir_mark_log.c
@@ -0,0 +1,121 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2019, 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_core.h"
+
+/*
+ * nss_gre_redir_mark_log_message_types_str
+ * GRE redir mark message strings
+ */
+static int8_t *nss_gre_redir_mark_log_message_types_str[NSS_GRE_REDIR_MARK_MSG_MAX] __maybe_unused = {
+ "GRE redir mark register callback message",
+ "GRE redir mark statistics synchronization"
+};
+
+/*
+ * nss_gre_redir_mark_log_error_response_types_str
+ * Strings for error types for GRE redir mark messages
+ */
+static int8_t *nss_gre_redir_mark_log_error_response_types_str[NSS_GRE_REDIR_MARK_ERROR_TYPE_MAX] __maybe_unused = {
+ "GRE redir mark No error",
+ "GRE redir mark Invalid interface for callback registration",
+ "GRE redir mark Invalid ethertype for Tx interface"
+};
+
+/*
+ * nss_gre_redir_mark_log_reg_cb_msg()
+ * Log NSS GRE redir mark configuration message
+ */
+static void nss_gre_redir_mark_log_reg_cb_msg(struct nss_gre_redir_mark_msg *ncm)
+{
+ struct nss_gre_redir_mark_register_cb_msg *reg_cb_msg __maybe_unused = &ncm->msg.reg_cb_msg;
+ nss_trace("%p: NSS GRE redir mark callback registration message \n"
+ "nss_if_num: %d\n", ncm, reg_cb_msg->nss_if_num);
+}
+
+/*
+ * nss_gre_redir_mark_log_verbose()
+ * Log message contents.
+ */
+static void nss_gre_redir_mark_log_verbose(struct nss_gre_redir_mark_msg *ncm)
+{
+ switch (ncm->cm.type) {
+ case NSS_GRE_REDIR_MARK_REG_CB_MSG:
+ nss_gre_redir_mark_log_reg_cb_msg(ncm);
+ break;
+
+ case NSS_GRE_REDIR_MARK_STATS_SYNC_MSG:
+ /*
+ * No log for valid stats message.
+ */
+ break;
+
+ default:
+ nss_trace("%p: Invalid message type\n", ncm);
+ break;
+ }
+}
+
+/*
+ * nss_gre_redir_mark_log_tx_msg()
+ * Log messages transmitted to FW.
+ */
+void nss_gre_redir_mark_log_tx_msg(struct nss_gre_redir_mark_msg *ngm)
+{
+ if (ngm->cm.type >= NSS_GRE_REDIR_MARK_MSG_MAX) {
+ nss_warning("%p: Invalid message type\n", ngm);
+ return;
+ }
+
+ nss_info("%p: type[%d]:%s\n", ngm, ngm->cm.type, nss_gre_redir_mark_log_message_types_str[ngm->cm.type]);
+ nss_gre_redir_mark_log_verbose(ngm);
+}
+/*
+ * nss_gre_redir_mark_log_rx_msg()
+ * Log messages received from FW.
+ */
+void nss_gre_redir_mark_log_rx_msg(struct nss_gre_redir_mark_msg *ncm)
+{
+ if (ncm->cm.response >= NSS_CMN_RESPONSE_LAST) {
+ nss_warning("%p: Invalid response\n", ncm);
+ return;
+ }
+
+ if (ncm->cm.response == NSS_CMN_RESPONSE_NOTIFY || (ncm->cm.response == NSS_CMN_RESPONSE_ACK)) {
+ nss_info("%p: type[%d]:%s, response[%d]:%s\n", ncm, ncm->cm.type,
+ nss_gre_redir_mark_log_message_types_str[ncm->cm.type],
+ ncm->cm.response, nss_cmn_response_str[ncm->cm.response]);
+ goto verbose;
+ }
+
+ if (ncm->cm.error >= NSS_GRE_REDIR_MARK_ERROR_TYPE_MAX) {
+ nss_warning("%p: msg failure - type[%d]:%s, response[%d]:%s, error[%d]:Invalid error\n",
+ ncm, ncm->cm.type, nss_gre_redir_mark_log_message_types_str[ncm->cm.type],
+ ncm->cm.response, nss_cmn_response_str[ncm->cm.response],
+ ncm->cm.error);
+ goto verbose;
+ }
+
+ nss_info("%p: msg nack - type[%d]:%s, response[%d]:%s, error[%d]:%s\n",
+ ncm, ncm->cm.type, nss_gre_redir_mark_log_message_types_str[ncm->cm.type],
+ ncm->cm.response, nss_cmn_response_str[ncm->cm.response],
+ ncm->cm.error, nss_gre_redir_mark_log_error_response_types_str[ncm->cm.error]);
+
+verbose:
+ nss_gre_redir_mark_log_verbose(ncm);
+}
+
diff --git a/nss_gre_redir_mark_log.h b/nss_gre_redir_mark_log.h
new file mode 100644
index 0000000..27e2ffb
--- /dev/null
+++ b/nss_gre_redir_mark_log.h
@@ -0,0 +1,37 @@
+/*
+ ******************************************************************************
+ * Copyright (c) 2019, 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_GRE_REDIR_MARK_LOG_H__
+#define __NSS_GRE_REDIR_MARK_LOG_H__
+
+/*
+ * nss_gre_redir_mark_log.h
+ * NSS GRE_REDIR_MARK Log Header File.
+ */
+
+/*
+ * nss_gre_redir_mark_log_tx_msg
+ * Logs GRE_REDIR_MARK message that is sent to the NSS firmware.
+ */
+void nss_gre_redir_mark_log_tx_msg(struct nss_gre_redir_mark_msg *ncm);
+
+/*
+ * nss_gre_redir_mark_log_rx_msg
+ * Logs GRE_REDIR_MARK message that is received from the NSS firmware.
+ */
+void nss_gre_redir_mark_log_rx_msg(struct nss_gre_redir_mark_msg *ncm);
+
+#endif /* __NSS_GRE_REDIR_MARK_LOG_H__ */
diff --git a/nss_gre_redir_mark_stats.c b/nss_gre_redir_mark_stats.c
new file mode 100644
index 0000000..11f1841
--- /dev/null
+++ b/nss_gre_redir_mark_stats.c
@@ -0,0 +1,163 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2019, 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_core.h"
+#include "nss_stats.h"
+#include "nss_gre_redir_mark.h"
+#include "nss_gre_redir_mark_stats.h"
+
+#define NSS_GRE_REDIR_MARK_STATS_STR_LEN 50
+#define NSS_GRE_REDIR_MARK_STATS_LEN ((NSS_GRE_REDIR_MARK_STATS_MAX + 7 ) * NSS_GRE_REDIR_MARK_STATS_STR_LEN)
+/*
+ * nss_gre_redir_mark_stats_str
+ * GRE redir mark statistics string
+ */
+static int8_t *nss_gre_redir_mark_stats_str[NSS_GRE_REDIR_MARK_STATS_MAX] = {
+ "TX Packets",
+ "TX Bytes",
+ "RX Packets",
+ "RX Bytes",
+ "RX Drops",
+ "HLOS magic failed",
+ "Tx inv_dst_if Drops",
+ "Tx dst_if Enqueue",
+ "Tx dst_if Enqueue Drops",
+ "Invalid appid",
+ "Headroom Unavailable",
+ "Tx Completion Host Enqueue Success",
+ "Tx Completion Host Enqueue Drops",
+};
+
+/*
+ * nss_gre_redir_mark_stats_cpy()
+ * Fill the stats.
+ */
+static ssize_t nss_gre_redir_mark_stats_cpy(char *lbuf, int len, int i, struct nss_gre_redir_mark_stats *s)
+{
+ uint64_t tcnt = 0;
+
+ switch (i) {
+ case NSS_GRE_REDIR_MARK_STATS_TX_PKTS:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_TX_PKTS];
+ return scnprintf(lbuf, len, "Common node stats start:\n\n%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_TX_BYTES:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_TX_BYTES];
+ return scnprintf(lbuf, len, "%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_RX_PKTS:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_RX_PKTS];
+ return scnprintf(lbuf, len, "%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_RX_BYTES:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_RX_BYTES];
+ return scnprintf(lbuf, len, "%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_RX_DROPS:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_RX_DROPS];
+ return scnprintf(lbuf, len, "%s = %llu\nCommon node stats end.\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_HLOS_MAGIC_FAILED:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_HLOS_MAGIC_FAILED];
+ return scnprintf(lbuf, len, "Offload stats start:\n\n%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_INV_DST_IF_DROPS:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_INV_DST_IF_DROPS];
+ return scnprintf(lbuf, len, "%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_DST_IF_ENQUEUE:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_DST_IF_ENQUEUE];
+ return scnprintf(lbuf, len, "%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_DST_IF_ENQUEUE_DROPS:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_DST_IF_ENQUEUE_DROPS];
+ return scnprintf(lbuf, len, "%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_INV_APPID:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_INV_APPID];
+ return scnprintf(lbuf, len, "%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_HEADROOM_UNAVAILABLE:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_HEADROOM_UNAVAILABLE];
+ return scnprintf(lbuf, len, "%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_TX_COMPLETION_SUCCESS:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_TX_COMPLETION_SUCCESS];
+ return scnprintf(lbuf, len, "%s = %llu\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ case NSS_GRE_REDIR_MARK_STATS_TX_COMPLETION_DROPS:
+ tcnt = s->stats[NSS_GRE_REDIR_MARK_STATS_TX_COMPLETION_DROPS];
+ return scnprintf(lbuf, len, "%s = %llu\nOffload stats end.\n", nss_gre_redir_mark_stats_str[i], tcnt);
+ default:
+ nss_warning("Unknown stats type %d.\n", i);
+ return 0;
+ }
+}
+
+/*
+ * nss_gre_redir_mark_stats_read()
+ * READ GRE redir mark stats.
+ */
+static ssize_t nss_gre_redir_mark_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+ struct nss_gre_redir_mark_stats stats;
+ size_t size_wr = 0;
+ int start, end;
+ ssize_t bytes_read = 0;
+ bool isthere;
+ size_t size_al = ((NSS_GRE_REDIR_MARK_STATS_MAX + 7 ) * NSS_GRE_REDIR_MARK_STATS_STR_LEN);
+
+ char *lbuf = kzalloc(size_al, GFP_KERNEL);
+ if (unlikely(!lbuf)) {
+ nss_warning("Could not allocate memory for local statistics buffer");
+ return 0;
+ }
+
+ /*
+ * If GRE redir mark does not exists, then (isthere) will be false.
+ */
+ isthere = nss_gre_redir_mark_get_stats((void*)&stats);
+ if (!isthere) {
+ nss_warning("Could not get GRE redirect stats");
+ kfree(lbuf);
+ return 0;
+ }
+
+ size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nGRE redir mark stats\n");
+
+ start = NSS_GRE_REDIR_MARK_STATS_TX_PKTS;
+ end = NSS_GRE_REDIR_MARK_STATS_MAX;
+ while (start < end) {
+ size_wr += nss_gre_redir_mark_stats_cpy(lbuf + size_wr, size_al - size_wr, start, &stats);
+ start++;
+ }
+
+ bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+ kfree(lbuf);
+ return bytes_read;
+}
+
+/*
+ * nss_gre_redir_mark_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(gre_redir_mark)
+
+/*
+ * nss_gre_redir_mark_stats_dentry_create()
+ * Create debugfs directory entry for stats.
+ */
+struct dentry *nss_gre_redir_mark_stats_dentry_create(void)
+{
+ struct dentry *gre_redir_mark;
+
+ gre_redir_mark = debugfs_create_file("gre_redir_mark", 0400, nss_top_main.stats_dentry,
+ &nss_top_main, &nss_gre_redir_mark_stats_ops);
+ if (unlikely(!gre_redir_mark)) {
+ nss_warning("Failed to create file entry qca-nss-drv/stats/gre_redir_mark/\n");
+ return NULL;
+ }
+
+ return gre_redir_mark;
+}
diff --git a/nss_gre_redir_mark_stats.h b/nss_gre_redir_mark_stats.h
new file mode 100644
index 0000000..8017f6d
--- /dev/null
+++ b/nss_gre_redir_mark_stats.h
@@ -0,0 +1,52 @@
+/*
+ ******************************************************************************
+ * Copyright (c) 2019, 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_GRE_REDIR_MARK_STATS_H__
+#define __NSS_GRE_REDIR_MARK_STATS_H__
+
+/*
+ * GRE REDIR statistics types
+ */
+enum nss_gre_redir_mark_stats_types {
+ NSS_GRE_REDIR_MARK_STATS_TX_PKTS,
+ NSS_GRE_REDIR_MARK_STATS_TX_BYTES,
+ NSS_GRE_REDIR_MARK_STATS_RX_PKTS,
+ NSS_GRE_REDIR_MARK_STATS_RX_BYTES,
+ NSS_GRE_REDIR_MARK_STATS_RX_DROPS,
+ NSS_GRE_REDIR_MARK_STATS_HLOS_MAGIC_FAILED,
+ NSS_GRE_REDIR_MARK_STATS_INV_DST_IF_DROPS,
+ NSS_GRE_REDIR_MARK_STATS_DST_IF_ENQUEUE,
+ NSS_GRE_REDIR_MARK_STATS_DST_IF_ENQUEUE_DROPS,
+ NSS_GRE_REDIR_MARK_STATS_INV_APPID,
+ NSS_GRE_REDIR_MARK_STATS_HEADROOM_UNAVAILABLE,
+ NSS_GRE_REDIR_MARK_STATS_TX_COMPLETION_SUCCESS,
+ NSS_GRE_REDIR_MARK_STATS_TX_COMPLETION_DROPS,
+ NSS_GRE_REDIR_MARK_STATS_MAX
+};
+
+/*
+ * NSS core stats -- for H2N/N2H gre_redir_mark debug stats
+ */
+struct nss_gre_redir_mark_stats {
+ uint64_t stats[NSS_GRE_REDIR_MARK_STATS_MAX];
+};
+
+/*
+ * NSS GRE REDIR Mark statistics APIs
+ */
+extern struct dentry *nss_gre_redir_mark_stats_dentry_create(void);
+
+#endif /* __NSS_GRE_REDIR_MARK_STATS_H__ */
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index 9315e30..75f68d6 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -107,6 +107,7 @@
npd->gre_enabled = of_property_read_bool(np, "qcom,gre-enabled");
npd->gre_redir_enabled = of_property_read_bool(np, "qcom,gre-redir-enabled");
npd->gre_tunnel_enabled = of_property_read_bool(np, "qcom,gre_tunnel_enabled");
+ npd->gre_redir_mark_enabled = of_property_read_bool(np, "qcom,gre-redir-mark-enabled");
npd->ipsec_enabled = of_property_read_bool(np, "qcom,ipsec-enabled");
npd->ipv4_enabled = of_property_read_bool(np, "qcom,ipv4-enabled");
npd->ipv4_reasm_enabled = of_property_read_bool(np, "qcom,ipv4-reasm-enabled");
@@ -536,6 +537,11 @@
nss_info("%d: NSS IGS is enabled", nss_dev->id);
}
+ if (npd->gre_redir_mark_enabled == NSS_FEATURE_ENABLED) {
+ nss_top->gre_redir_mark_handler_id = nss_dev->id;
+ nss_gre_redir_mark_register_handler();
+ }
+
if (nss_ctx->id == 0) {
#if (NSS_FREQ_SCALE_SUPPORT == 1)
nss_freq_register_handler();
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index 3397e20..d747279 100644
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -92,6 +92,7 @@
extern void nss_trustsec_tx_register_handler(void);
extern void nss_wifili_register_handler(void);
extern void nss_ppe_register_handler(void);
+extern void nss_gre_redir_mark_register_handler(void);
/*
* nss_if_msg_handler()