[qca-nss-drv] Add support for standard VxLAN

NSS Driver changes for VxLAN support.

Change-Id: I2f3ef6a05092f5d1cb717b2a5b40b83df00329cf
Signed-off-by: Cemil Coskun <ccoskun@codeaurora.org>
Signed-off-by: Apoorv Gupta <apoogupt@codeaurora.org>
diff --git a/Makefile b/Makefile
index 6b95d8b..01315d7 100644
--- a/Makefile
+++ b/Makefile
@@ -123,6 +123,9 @@
 			nss_virt_if_stats.o \
 			nss_vlan.o \
 			nss_vlan_log.o \
+			nss_vxlan.o \
+			nss_vxlan_log.o \
+			nss_vxlan_stats.o \
 			nss_tstamp.o \
 			nss_wifi.o \
 			nss_wifi_log.o \
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 09de8c2..6819243 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -75,6 +75,7 @@
 #include "nss_qvpn.h"
 #include "nss_unaligned.h"
 #include "nss_pvxlan.h"
+#include "nss_vxlan.h"
 #include "nss_pm.h"
 #include "nss_freq.h"
 #include "nss_tstamp.h"
@@ -98,7 +99,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 57	/**< Maximum number of special interfaces. */
+#define NSS_MAX_SPECIAL_INTERFACES 58	/**< Maximum number of special interfaces. */
 #define NSS_MAX_WIFI_RADIO_INTERFACES 3	/**< Maximum number of radio interfaces. */
 
 /*
@@ -221,7 +222,7 @@
 #define NSS_REDIR_RX_INTERFACE (NSS_SPECIAL_IF_START + 50)
 		/**< Special interface number for 802.3 redirect node. */
 #define NSS_QRFS_INTERFACE (NSS_SPECIAL_IF_START + 51)
-		/**<Special interface number for QRFS. */
+		/**< Special interface number for QRFS. */
 #define NSS_GRE_REDIR_LAG_INTERFACE (NSS_SPECIAL_IF_START + 52)
 		/**< Special interface number for GRE redirect Link Aggregation interface. */
 #define NSS_UNALIGNED_INTERFACE (NSS_SPECIAL_IF_START + 53)
@@ -232,6 +233,8 @@
 		/**< Special interface number for timestamp receive. */
 #define NSS_GRE_REDIR_MARK_INTERFACE (NSS_SPECIAL_IF_START + 56)
 		/**< Special interface number for GRE redirect mark. */
+#define NSS_VXLAN_INTERFACE (NSS_SPECIAL_IF_START + 57)
+		/**< Special interface number for VxLAN handler. */
 
 /**
  * Wireless Multimedia Extention Access Category to TID. @hideinitializer
diff --git a/exports/nss_dynamic_interface.h b/exports/nss_dynamic_interface.h
index ffda4ba..88b0517 100644
--- a/exports/nss_dynamic_interface.h
+++ b/exports/nss_dynamic_interface.h
@@ -90,6 +90,8 @@
 	NSS_DYNAMIC_INTERFACE_TYPE_IGS,
 	NSS_DYNAMIC_INTERFACE_TYPE_CLMAP_US,
 	NSS_DYNAMIC_INTERFACE_TYPE_CLMAP_DS,
+	NSS_DYNAMIC_INTERFACE_TYPE_VXLAN_INNER,
+	NSS_DYNAMIC_INTERFACE_TYPE_VXLAN_OUTER,
 	NSS_DYNAMIC_INTERFACE_TYPE_MAX
 };
 
@@ -206,7 +208,7 @@
 
 /**
  * nss_dynamic_interface_get_nss_ctx_by_type
- * 	Returns NSS context corresponding of that dynamic interface type.
+ *	Returns NSS context corresponding to the dynamic interface type.
  *
  * @datatypes
  * nss_dynamic_interface_type
diff --git a/exports/nss_vxlan.h b/exports/nss_vxlan.h
new file mode 100644
index 0000000..c90faeb
--- /dev/null
+++ b/exports/nss_vxlan.h
@@ -0,0 +1,349 @@
+/*
+ **************************************************************************
+ * 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_vxlan.h
+ *	NSS VxLAN interface definitions.
+ */
+
+#ifndef __NSS_VXLAN_H
+#define __NSS_VXLAN_H
+
+/**
+ * @addtogroup nss_vxlan_subsystem
+ * @{
+ */
+
+/**
+ * Maximum number of supported VxLAN tunnel sessions.
+ */
+#define NSS_VXLAN_MAX_TUNNELS 64
+
+/**
+ * Maximum number of supported VxLAN FDB entries.
+ */
+#define NSS_VXLAN_MACDB_ENTRIES_MAX 1024
+
+/**
+ * MAC database entries per message.
+ */
+#define NSS_VXLAN_MACDB_ENTRIES_PER_MSG 20
+
+/*
+ *  VxLAN Rule configure message flags
+ */
+#define NSS_VXLAN_RULE_FLAG_GBP_ENABLED 0x0001			/**< Group Policy ID is eanbled. */
+#define NSS_VXLAN_RULE_FLAG_INHERIT_TOS 0x0002			/**< Use inner TOS for encapsulation. */
+#define NSS_VXLAN_RULE_FLAG_ENCAP_L4_CSUM_REQUIRED 0x0004	/**< Generate transmit checksum. */
+#define NSS_VXLAN_RULE_FLAG_IPV4 0x0010				/**< IPv4 tunnel. */
+#define NSS_VXLAN_RULE_FLAG_IPV6 0x0020				/**< IPv6 tunnel. */
+#define NSS_VXLAN_RULE_FLAG_UDP 0x0100				/**< UDP tunnel. */
+
+/**
+ * nss_vxlan_msg_type
+ *	Message types for VxLAN tunnel.
+ */
+enum nss_vxlan_msg_type {
+	NSS_VXLAN_MSG_TYPE_STATS_SYNC,		/**< Statistics synchronization message. */
+	NSS_VXLAN_MSG_TYPE_TUN_CONFIGURE,	/**< Creating tunnel rule. */
+	NSS_VXLAN_MSG_TYPE_TUN_UNCONFIGURE,	/**< Destroying tunnel rule. */
+	NSS_VXLAN_MSG_TYPE_TUN_ENABLE,		/**< Enable the tunnel. */
+	NSS_VXLAN_MSG_TYPE_TUN_DISABLE,		/**< Disable the tunnel. */
+	NSS_VXLAN_MSG_TYPE_MAC_ADD,		/**< Add MAC rule to the database. */
+	NSS_VXLAN_MSG_TYPE_MAC_DEL,		/**< Remove MAC rule from the database. */
+	NSS_VXLAN_MSG_TYPE_MACDB_STATS,		/**< MAC database statistics synchronization message. */
+	NSS_VXLAN_MSG_TYPE_MAX,			/**< Maximum message type. */
+};
+
+/**
+ * nss_vxlan_error_response_types
+ *	Error types for VxLAN responses to messages from the host.
+ */
+enum nss_vxlan_error_type {
+	NSS_VXLAN_ERROR_TYPE_NONE = 1,			/**< Unknown type error. */
+	NSS_VXLAN_ERROR_TYPE_DECAP_REGISTER_FAIL,	/**< Decapsulation node registration failed. */
+	NSS_VXLAN_ERROR_TYPE_DEST_IP_MISMATCH,		/**< Destination IP address mismatch. */
+	NSS_VXLAN_ERROR_TYPE_INVALID_VNI,		/**< Invalid virtual network ID. */
+	NSS_VXLAN_ERROR_TYPE_INVALID_L3_PROTO,		/**< L3 Protocol is invalid error. */
+	NSS_VXLAN_ERROR_TYPE_INVALID_UDP_PROTO,		/**< UDP Protocol is invalid error. */
+	NSS_VXLAN_ERROR_TYPE_INVALID_SRC_PORT,		/**< Source port range is invalid. */
+	NSS_VXLAN_ERROR_TYPE_MAC_BAD_ENTRY,		/**< MAC table has a bad entry. */
+	NSS_VXLAN_ERROR_TYPE_MAC_EXISTS,		/**< MAC entry exists in the table error. */
+	NSS_VXLAN_ERROR_TYPE_MAC_NOT_EXIST,		/**< MAC does not exist in the table error. */
+	NSS_VXLAN_ERROR_TYPE_MAC_ENTRY_UNHASHED,	/**< MAC entry is not hashed in table. */
+	NSS_VXLAN_ERROR_TYPE_MAC_ENTRY_ALLOC_FAILED,	/**< MAC entry allocation failed. */
+	NSS_VXLAN_ERROR_TYPE_MAC_ENTRY_DELETE_FAILED,	/**< MAC entry deletion failed. */
+	NSS_VXLAN_ERROR_TYPE_MAC_TABLE_FULL,		/**< MAC table is full error. */
+	NSS_VXLAN_ERROR_TYPE_SIBLING_NODE_NOT_EXIST,	/**< Sibling node does not exist. */
+	NSS_VXLAN_ERROR_TYPE_TUNNEL_CONFIGURED,		/**< Tunnel is already configured. */
+	NSS_VXLAN_ERROR_TYPE_TUNNEL_UNCONFIGURED,	/**< Tunnel is not configured. */
+	NSS_VXLAN_ERROR_TYPE_TUNNEL_ADD_FAILED,		/**< Adding tunnel information failed. */
+	NSS_VXLAN_ERROR_TYPE_TUNNEL_DISABLED,		/**< Tunnel is already disabled error. */
+	NSS_VXLAN_ERROR_TYPE_TUNNEL_ENABLED,		/**< Tunnel is already enabled error. */
+	NSS_VXLAN_ERROR_TYPE_TUNNEL_ENTRY_EXISTS,	/**< Tunnel already exists. */
+	NSS_VXLAN_ERROR_TYPE_MAX,			/**< Maximum error type. */
+};
+
+/**
+ * nss_vxlan_stats_msg
+ *	Per-tunnel statistics messages from the NSS firmware.
+ */
+struct nss_vxlan_stats_msg {
+	struct nss_cmn_node_stats node_stats;	/**< Common firmware statistics. */
+	uint32_t except_mac_db_lookup_failed;	/**< MAC database look up failed. */
+	uint32_t except_mac_move;		/**< User is moved. */
+	uint32_t except_low_hroom;		/**< Transmit exception due to insufficient headroom. */
+	uint32_t except_no_policy_id;		/**< Policy ID does not exist. */
+	uint32_t except_extra_vxlan_hdr_flags;	/**< More flags are set than NSS can process. */
+	uint32_t except_vni_lookup_failed;	/**< Virtual network ID look up failed. */
+	uint32_t dropped_malformed;		/**< Packet is malformed. */
+	uint32_t dropped_next_node_queue_full;	/**< Next node dropped the packet. */
+};
+
+/**
+ * nss_vxlan_rule_msg
+ *	 VxLAN rule message.
+ *
+ * The same rule structure applies for both encapsulation and decapsulation
+ * in a tunnel.
+ */
+struct nss_vxlan_rule_msg {
+	/*
+	 * VxLAN Rules
+	 */
+	uint32_t sibling_if_num;	/**< Sibling node interface number. */
+	uint32_t vni;			/**< Virtual network ID. */
+	uint16_t tunnel_flags;		/**< VxLAN tunnel flags. */
+
+	/*
+	 * IP rules
+	 */
+	uint16_t flow_label;		/**< Flow label. */
+	uint8_t tos;			/**< Type of service/traffic class. */
+	uint8_t ttl;			/**< TTL/Hop Limit. */
+
+	/*
+	 * L4 rules
+	 */
+	uint16_t src_port_min;		/**< Minimum permissible port number. */
+	uint16_t src_port_max;		/**< Maximum permissible port number. */
+	uint16_t dest_port;		/**< UDP destination port. */
+};
+
+/**
+ * nss_vxlan_encap_rule
+ *	Encapsulation information for a VxLAN tunnel.
+ */
+struct nss_vxlan_encap_rule {
+	uint32_t src_ip[4];	/**< Source IP. */
+	uint32_t dest_ip[4];	/**< Destination IP. */
+};
+
+/**
+ * nss_vxlan_mac_msg
+ *	VxLAN MAC message structure.
+ */
+struct nss_vxlan_mac_msg {
+	struct nss_vxlan_encap_rule encap;
+					/**< Tunnel encapsulation header. */
+	uint32_t vni;			/**< VxLAN network identifier. */
+	uint16_t mac_addr[3];		/**< MAC address. */
+};
+
+/**
+ * nss_vxlan_macdb_stats_entry
+ *	MAC database statistics entry.
+ */
+struct nss_vxlan_macdb_stats_entry {
+	uint32_t hits;			/**< Total hash hits on this hash entry. */
+	uint16_t mac[3];		/**< MAC address. */
+};
+
+/**
+ * nss_vxlan_macdb_stats_msg
+ *	VxLAN MAC database statistics.
+ */
+struct nss_vxlan_macdb_stats_msg {
+	uint16_t cnt;			/**< Number of MAC database entries copied. */
+	uint16_t reserved;		/**< Reserved for future use. */
+	struct nss_vxlan_macdb_stats_entry entry[NSS_VXLAN_MACDB_ENTRIES_PER_MSG];
+					/**< MAC database entries. */
+};
+
+/**
+ * nss_vxlan_msg
+ *	Data structure for sending and receiving VxLAN messages.
+ */
+struct nss_vxlan_msg {
+	struct nss_cmn_msg cm;			/**< Common message header. */
+
+	/**
+	 * Payload of a VxLAN message.
+	 */
+	union {
+		struct nss_vxlan_stats_msg stats;
+				/**< Synchronized statistics for the VxLAN interface. */
+		struct nss_vxlan_rule_msg vxlan_create;
+				/**< Allocate VxLAN tunnel node. */
+		struct nss_vxlan_rule_msg vxlan_destroy;
+				/**< Destroy VxLAN tunnel node. */
+		struct nss_vxlan_mac_msg mac_add;
+				/**< MAC add message for UDP encapsulation. */
+		struct nss_vxlan_mac_msg mac_del;
+				/**< MAC delete message. */
+		struct nss_vxlan_macdb_stats_msg db_stats;
+				/**< MAC database statistics. */
+	} msg;			/**< Payload for VxLAN tunnel messages exchanged with the NSS core. */
+};
+
+/**
+ * Callback function for receiving VxLAN tunnel 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_vxlan_buf_callback_t)(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi);
+
+/**
+ * Callback function for receiving VxLAN 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_vxlan_msg_callback_t)(void *app_data, struct nss_cmn_msg *msg);
+
+/**
+ * nss_vxlan_tx_msg
+ *	Sends VxLAN tunnel messages to the NSS.
+ *
+ * Do not call this function from a softirq or interrupt because it
+ * might sleep if the NSS firmware is busy serving another host thread.
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * nss_vxlan_msg
+ *
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] nvm      Pointer to the message data.
+ *
+ * @return
+ * Status of the Tx operation.
+ */
+extern nss_tx_status_t nss_vxlan_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_vxlan_msg *nvm);
+
+/**
+ * nss_vxlan_tx_msg_sync
+ *	Sends a VxLAN message to the NSS synchronously.
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * nss_vxlan_msg
+ *
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] nvm      Pointer to the message data.
+ *
+ * @return
+ * Status of the Tx operation.
+ */
+extern nss_tx_status_t nss_vxlan_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_vxlan_msg *nvm);
+
+/**
+ * nss_vxlan_unregister_if
+ *	Deregisters the VxLAN interface from the NSS.
+ *
+ * @param[in] if_num  NSS interface number.
+ *
+ * @return
+ * None.
+ */
+extern bool nss_vxlan_unregister_if(uint32_t if_num);
+
+/**
+ * nss_vxlan_register_if
+ *	Registers the VxLAN interface with the NSS.
+ *
+ * @datatypes
+ * nss_vxlan_buf_callback_t \n
+ * nss_vxlan_msg_callback_t \n
+ * net_device
+ *
+ * @param[in] if_num             NSS interface number.
+ * @param[in] type               Dynamic interface type.
+ * @param[in] data_cb            Callback for the data.
+ * @param[in] notify_cb          Callback for the message.
+ * @param[in] netdev             Pointer to the associated network device.
+ * @param[in] features           Data socket buffer types supported by this interface.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_vxlan_register_if(uint32_t if_num, uint32_t type, nss_vxlan_buf_callback_t data_cb,
+					nss_vxlan_msg_callback_t notify_cb, struct net_device *netdev, uint32_t features);
+
+/**
+ * nss_vxlan_register_handler
+ *	Initializes VxLAN module in NSS
+ *
+ * @return
+ * None.
+ */
+extern void nss_vxlan_init(void);
+
+/**
+ * nss_vxlan_msg_init
+ *	Initializes a VxLAN message.
+ *
+ * @datatypes
+ * nss_vxlan_msg \n
+ * nss_vxlan_msg_callback_t
+ *
+ * @param[in,out] nvm       Pointer to the VxLAN tunnel message.
+ * @param[in]     if_num    NSS interface number.
+ * @param[in]     type      Type of message.
+ * @param[in]     len       Size of the message.
+ * @param[in]     cb        Pointer to the message callback.
+ * @param[in]     app_data  Pointer to the application context of the message.
+ *
+ * @return
+ * None.
+ */
+extern void nss_vxlan_msg_init(struct nss_vxlan_msg *nvm, uint16_t if_num, uint32_t type, uint32_t len,
+				nss_vxlan_msg_callback_t cb, void *app_data);
+
+/**
+ * nss_vxlan_get_ctx()
+ *	Get VxLAN context.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_vxlan_get_ctx(void);
+
+/**
+ * @}
+ */
+
+#endif
+/* __NSS_VXLAN_H */
diff --git a/nss_core.h b/nss_core.h
index ccccbb7..bfb6f93 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -615,6 +615,7 @@
 	uint8_t igs_handler_id;
 	uint8_t gre_redir_mark_handler_id;
 	uint8_t clmap_handler_id;
+	uint8_t vxlan_handler_id;
 
 	/*
 	 * Data/Message callbacks for various interfaces
@@ -938,6 +939,8 @@
 				/* Does this core handle GRE redir mark? */
 	enum nss_feature_enabled clmap_enabled;
 				/* Does this core handle clmap? */
+	enum nss_feature_enabled vxlan_enabled;
+				/* Does this core handle vxlan tunnel? */
 };
 #endif
 
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index f81f23e..0740e75 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -102,12 +102,14 @@
 	 */
 	npd->bridge_enabled = of_property_read_bool(np, "qcom,bridge-enabled");
 	npd->capwap_enabled = of_property_read_bool(np, "qcom,capwap-enabled");
+	npd->clmap_enabled = of_property_read_bool(np, "qcom,clmap-enabled");
 	npd->crypto_enabled = of_property_read_bool(np, "qcom,crypto-enabled");
 	npd->dtls_enabled = of_property_read_bool(np, "qcom,dtls-enabled");
 	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->igs_enabled = of_property_read_bool(np, "qcom,igs-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");
@@ -121,7 +123,6 @@
 	npd->pptp_enabled = of_property_read_bool(np, "qcom,pptp-enabled");
 	npd->portid_enabled = of_property_read_bool(np, "qcom,portid-enabled");
 	npd->pvxlan_enabled = of_property_read_bool(np, "qcom,pvxlan-enabled");
-	npd->clmap_enabled = of_property_read_bool(np, "qcom,clmap-enabled");
 	npd->qvpn_enabled = of_property_read_bool(np, "qcom,qvpn-enabled");
 	npd->shaping_enabled = of_property_read_bool(np, "qcom,shaping-enabled");
 	npd->tstamp_enabled = of_property_read_bool(np, "qcom,tstamp-enabled");
@@ -129,9 +130,9 @@
 	npd->tun6rd_enabled = of_property_read_bool(np, "qcom,tun6rd-enabled");
 	npd->tunipip6_enabled = of_property_read_bool(np, "qcom,tunipip6-enabled");
 	npd->vlan_enabled = of_property_read_bool(np, "qcom,vlan-enabled");
+	npd->vxlan_enabled = of_property_read_bool(np, "qcom,vxlan-enabled");
 	npd->wlanredirect_enabled = of_property_read_bool(np, "qcom,wlanredirect-enabled");
 	npd->wifioffload_enabled = of_property_read_bool(np, "qcom,wlan-dataplane-offload-enabled");
-	npd->igs_enabled = of_property_read_bool(np, "qcom,igs-enabled");
 }
 
 /*
@@ -549,6 +550,13 @@
 		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_CLMAP_DS] = nss_dev->id;
 	}
 
+	if (npd->vxlan_enabled == NSS_FEATURE_ENABLED) {
+		nss_top->vxlan_handler_id = nss_dev->id;
+		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_VXLAN_INNER] = nss_dev->id;
+		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_VXLAN_OUTER] = nss_dev->id;
+		nss_vxlan_init();
+	}
+
 	if (nss_ctx->id == 0) {
 #if (NSS_FREQ_SCALE_SUPPORT == 1)
 		nss_freq_register_handler();
diff --git a/nss_vxlan.c b/nss_vxlan.c
new file mode 100644
index 0000000..d8174de
--- /dev/null
+++ b/nss_vxlan.c
@@ -0,0 +1,320 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+/*
+ * nss_vxlan.c
+ *	NSS VxLAN driver interface APIs
+ */
+#include "nss_core.h"
+#include "nss_vxlan.h"
+#include "nss_cmn.h"
+#include "nss_tx_rx_common.h"
+#include "nss_vxlan_log.h"
+#include "nss_vxlan_stats.h"
+
+#define NSS_VXLAN_TX_TIMEOUT 3000
+
+/*
+ * Private data structure
+ */
+static struct {
+	struct semaphore sem;		/* Semaphore structure. */
+	struct completion complete;	/* Completion structure. */
+	int response;			/* Response from FW. */
+	void *cb;			/* Original cb for msgs. */
+	void *app_data;			/* Original app_data for msgs. */
+} nss_vxlan_pvt;
+
+/*
+ * nss_vxlan_verify_if_num()
+ *	Verify if_num passed to us.
+ */
+static bool nss_vxlan_verify_if_num(uint32_t if_num)
+{
+	uint32_t type;
+
+	if (if_num == NSS_VXLAN_INTERFACE) {
+		return true;
+	}
+
+	type = nss_dynamic_interface_get_type(nss_vxlan_get_ctx(), if_num);
+
+	return ((type == NSS_DYNAMIC_INTERFACE_TYPE_VXLAN_INNER) ||
+			(type == NSS_DYNAMIC_INTERFACE_TYPE_VXLAN_OUTER));
+}
+
+/*
+ * nss_vxlan_callback()
+ *	Callback to handle the completion of NSS->HLOS messages.
+ */
+static void nss_vxlan_callback(void *app_data, struct nss_cmn_msg *msg)
+{
+	nss_vxlan_msg_callback_t callback = (nss_vxlan_msg_callback_t)nss_vxlan_pvt.cb;
+	void *data = nss_vxlan_pvt.app_data;
+
+	nss_vxlan_pvt.response = NSS_TX_SUCCESS;
+	nss_vxlan_pvt.cb = NULL;
+	nss_vxlan_pvt.app_data = NULL;
+
+	if (msg->response != NSS_CMN_RESPONSE_ACK) {
+		nss_warning("Vxlan Error response %d\n", msg->response);
+		nss_vxlan_pvt.response = NSS_TX_FAILURE;
+	}
+
+	if (callback) {
+		callback(data, msg);
+	}
+	complete(&nss_vxlan_pvt.complete);
+}
+
+/*
+ * nss_vxlan_handler()
+ *	Handle NSS -> HLOS messages for vxlan.
+ */
+static void nss_vxlan_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
+{
+	struct nss_vxlan_msg *nvm = (struct nss_vxlan_msg *)ncm;
+	nss_vxlan_msg_callback_t cb;
+
+	BUG_ON(!nss_vxlan_verify_if_num(ncm->interface));
+
+	/*
+	 * Is this a valid request/response packet?
+	 */
+	if (ncm->type >= NSS_VXLAN_MSG_TYPE_MAX) {
+		nss_warning("%p: received invalid message %d for vxlan interface", nss_ctx, ncm->type);
+		return;
+	}
+
+	if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_vxlan_msg)) {
+		nss_warning("%p: Length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
+		return;
+	}
+
+	/*
+	 * Log messages.
+	 */
+	nss_core_log_msg_failures(nss_ctx, ncm);
+	nss_vxlan_log_rx_msg(nvm);
+
+	switch (nvm->cm.type) {
+	case NSS_VXLAN_MSG_TYPE_STATS_SYNC:
+		/*
+		 * Update common node statistics
+		 */
+		nss_vxlan_stats_sync(nss_ctx, nvm);
+	}
+
+	/*
+	 * Update the callback for NOTIFY messages
+	 */
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
+		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
+	}
+
+	cb = (nss_vxlan_msg_callback_t)ncm->cb;
+
+	/*
+	 * Do we have a callback?
+	 */
+	if (!cb) {
+		nss_trace("%p: cb is null for interface %d\n", nss_ctx, ncm->interface);
+		return;
+	}
+
+	cb((void *)nss_ctx->subsys_dp_register[ncm->interface].ndev, ncm);
+}
+
+/*
+ * nss_vxlan_tx_msg()
+ *	Transmit a vxlan message to NSS FW. Don't call this from softirq/interrupts.
+ */
+nss_tx_status_t nss_vxlan_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_vxlan_msg *nvm)
+{
+	struct nss_cmn_msg *ncm = &nvm->cm;
+
+	if (!nss_vxlan_verify_if_num(ncm->interface)) {
+		nss_warning("%p: wrong interface number %u\n", nss_ctx, nvm->cm.interface);
+		return NSS_TX_FAILURE_BAD_PARAM;
+	}
+
+	if (ncm->type >= NSS_VXLAN_MSG_TYPE_MAX) {
+		nss_warning("%p: wrong message type %u\n", nss_ctx, ncm->type);
+		return NSS_TX_FAILURE_BAD_PARAM;
+	}
+
+	/*
+	 * Trace messages.
+	 */
+	nss_vxlan_log_tx_msg(nvm);
+
+	return nss_core_send_cmd(nss_ctx, nvm, sizeof(*nvm), NSS_NBUF_PAYLOAD_SIZE);
+}
+EXPORT_SYMBOL(nss_vxlan_tx_msg);
+
+/*
+ * nss_vxlan_tx_msg_sync()
+ *	Transmit a vxlan message to NSS firmware synchronously.
+ */
+nss_tx_status_t nss_vxlan_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_vxlan_msg *nvm)
+{
+	nss_tx_status_t status;
+	int ret;
+
+	down(&nss_vxlan_pvt.sem);
+	nss_vxlan_pvt.cb = (void *)nvm->cm.cb;
+	nss_vxlan_pvt.app_data = (void *)nvm->cm.app_data;
+
+	nvm->cm.cb = (nss_ptr_t)nss_vxlan_callback;
+	nvm->cm.app_data = (nss_ptr_t)NULL;
+
+	status = nss_vxlan_tx_msg(nss_ctx, nvm);
+	if (status != NSS_TX_SUCCESS) {
+		nss_warning("%p: vxlan_tx_msg failed\n", nss_ctx);
+		up(&nss_vxlan_pvt.sem);
+		return status;
+	}
+
+	ret = wait_for_completion_timeout(&nss_vxlan_pvt.complete, msecs_to_jiffies(NSS_VXLAN_TX_TIMEOUT));
+	if (!ret) {
+		nss_warning("%p: vxlan tx sync failed due to timeout\n", nss_ctx);
+		nss_vxlan_pvt.response = NSS_TX_FAILURE;
+	}
+
+	status = nss_vxlan_pvt.response;
+	up(&nss_vxlan_pvt.sem);
+	return status;
+}
+EXPORT_SYMBOL(nss_vxlan_tx_msg_sync);
+
+/*
+ * nss_vxlan_msg_init()
+ *	Initialize VxLAN message.
+ */
+void nss_vxlan_msg_init(struct nss_vxlan_msg *nvm, uint16_t if_num, uint32_t type, uint32_t len,
+				nss_vxlan_msg_callback_t cb, void *app_data)
+{
+	nss_cmn_msg_init(&nvm->cm, if_num, type, len, (void*)cb, app_data);
+}
+EXPORT_SYMBOL(nss_vxlan_msg_init);
+
+/*
+ * nss_vxlan_unregister_if()
+ *	Unregister a data packet notifier with NSS FW.
+ */
+bool nss_vxlan_unregister_if(uint32_t if_num)
+{
+	struct nss_ctx_instance *nss_ctx;
+
+	nss_ctx = nss_vxlan_get_ctx();
+	if (!nss_vxlan_verify_if_num(if_num)) {
+		nss_warning("%p: data unregister received for invalid interface %d", nss_ctx, if_num);
+		return false;
+	}
+
+	nss_core_unregister_handler(nss_ctx, if_num);
+	nss_core_unregister_subsys_dp(nss_ctx, if_num);
+	return true;
+}
+EXPORT_SYMBOL(nss_vxlan_unregister_if);
+
+/*
+ * nss_vxlan_register_if()
+ *	Registers a data packet notifier with NSS FW.
+ */
+struct nss_ctx_instance *nss_vxlan_register_if(uint32_t if_num,
+						uint32_t type,
+						nss_vxlan_buf_callback_t data_cb,
+						nss_vxlan_msg_callback_t notify_cb,
+						struct net_device *netdev,
+						uint32_t features)
+{
+	struct nss_ctx_instance *nss_ctx;
+	int core_status;
+
+	nss_ctx = nss_vxlan_get_ctx();
+	if (!nss_vxlan_verify_if_num(if_num)) {
+		nss_warning("%p: data register received for invalid interface %d", nss_ctx, if_num);
+		return NULL;
+	}
+
+	core_status = nss_core_register_handler(nss_ctx, if_num, nss_vxlan_msg_handler, NULL);
+	if (core_status != NSS_CORE_STATUS_SUCCESS) {
+		nss_warning("%p: nss core register handler failed for if_num:%d with error :%d", nss_ctx, if_num, core_status);
+		return NULL;
+	}
+
+	nss_core_register_subsys_dp(nss_ctx, if_num, data_cb, NULL, NULL, netdev, features);
+	nss_core_set_subsys_dp_type(nss_ctx, netdev, if_num, type);
+	nss_top_main.if_rx_msg_callback[if_num] = (nss_if_rx_msg_callback_t)notify_cb;
+	return nss_ctx;
+}
+EXPORT_SYMBOL(nss_vxlan_register_if);
+
+/*
+ * nss_vxlan_ifnum_with_core_id()
+ *	Append core id to vxlan interface num.
+ */
+int nss_vxlan_ifnum_with_core_id(int if_num)
+{
+	struct nss_ctx_instance *nss_ctx = nss_vxlan_get_ctx();
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+
+	if (!nss_vxlan_verify_if_num(if_num)) {
+		nss_warning("%p: Invalid if_num: %d, must be a dynamic interface\n", nss_ctx, if_num);
+		return 0;
+	}
+	return NSS_INTERFACE_NUM_APPEND_COREID(nss_ctx, if_num);
+}
+EXPORT_SYMBOL(nss_vxlan_ifnum_with_core_id);
+
+/*
+ * nss_vxlan_get_ctx()
+ *	Return a VxLAN NSS context.
+ */
+struct nss_ctx_instance *nss_vxlan_get_ctx()
+{
+	struct nss_ctx_instance *nss_ctx;
+
+	nss_ctx = &nss_top_main.nss[nss_top_main.vxlan_handler_id];
+	return nss_ctx;
+}
+EXPORT_SYMBOL(nss_vxlan_get_ctx);
+
+/*
+ * nss_vxlan_init()
+ *	Initializes Vxlan. Gets called from nss_init.c.
+ */
+void nss_vxlan_init()
+{
+	uint32_t core_status;
+	struct nss_ctx_instance *nss_ctx = nss_vxlan_get_ctx();
+	if (!nss_ctx) {
+		nss_warning("%p: VxLAN is not registered", nss_ctx);
+		return;
+	}
+
+	nss_vxlan_stats_dentry_create();
+	sema_init(&nss_vxlan_pvt.sem, 1);
+	init_completion(&nss_vxlan_pvt.complete);
+	core_status = nss_core_register_handler(nss_ctx, NSS_VXLAN_INTERFACE, nss_vxlan_msg_handler, NULL);
+
+	if (core_status != NSS_CORE_STATUS_SUCCESS) {
+		nss_warning("%p: nss core register handler failed for if_num:%d with error :%d", nss_ctx, NSS_VXLAN_INTERFACE, core_status);
+	}
+
+}
diff --git a/nss_vxlan_log.c b/nss_vxlan_log.c
new file mode 100644
index 0000000..9fe7087
--- /dev/null
+++ b/nss_vxlan_log.c
@@ -0,0 +1,257 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+/*
+ * nss_vxlan_log.c
+ *	NSS VXLAN logger file.
+ */
+
+#include "nss_core.h"
+
+/*
+ * nss_vxlan_log_message_types_str
+ *	VXLAN message strings
+ */
+static int8_t *nss_vxlan_log_message_types_str[NSS_VXLAN_MSG_TYPE_MAX] __maybe_unused = {
+	"VxLAN Sync Stats",
+	"VxLAN Tunnel Configure Rule",
+	"VxLAN Tunnel Unconfigure Rule",
+	"VxLAN Enable Tunnel",
+	"VxLAN Disable Tunnel",
+	"VxLAN Add MAC rule",
+	"VxLAN Delete MAC rule",
+	"VxLAN MAC DB Stats"
+};
+
+/*
+ * nss_vxlan_log_error_response_types_str
+ *	Strings for error types for VXLAN messages
+ */
+static int8_t *nss_vxlan_log_error_response_types_str[NSS_VXLAN_ERROR_TYPE_MAX] __maybe_unused = {
+	"VxLAN Unknown Error",
+	"VXLAN Decap Register fail",
+	"VXLAN Dest IP mismatch",
+	"VXLAN Invalid VNI",
+	"VXLAN Invalid L3 Proto",
+	"VXLAN Invalid UDP Proto",
+	"VXLAN Invalid Src Port",
+	"VXLAN MAC Bad entry",
+	"VXLAN MAC Entry exists",
+	"VXLAN MAC Entry does not exist",
+	"VXLAN MAC Entry unhashed",
+	"VXLAN MAC Entry alloc failed",
+	"VXLAN MAC Entry delete failed",
+	"VXLAN MAC Table full",
+	"VXLAN Sibling Node does not exist",
+	"VXLAN Tunnel Configured",
+	"VXLAN Tunnel Unconfigured",
+	"VXLAN Tunnel addition failed",
+	"VXLAN Tunnel Disabled",
+	"VXLAN Tunnel Enabled",
+	"VXLAN Tunnel Entry exists"
+};
+
+/*
+ * nss_vxlan_log_rule_msg()
+ *	Log NSS VXLAN rule message.
+ */
+static void nss_vxlan_log_rule_msg(struct nss_vxlan_rule_msg *nvrm)
+{
+	nss_trace("%p: NSS VXLAN Rule message \n"
+		"VxLAN Tunnel Flags: %x\n"
+		"VNET ID: %u\n"
+		"Flowlabel: %u\n"
+		"TOS: %u\n"
+		"TTL: %u\n"
+		"source port min: %u max: %u"
+		"destination port: %u",
+		nvrm,
+		nvrm->tunnel_flags,
+		nvrm->vni,
+		nvrm->flow_label,
+		nvrm->tos,
+		nvrm->ttl,
+		nvrm->src_port_min,
+		nvrm->src_port_max,
+		nvrm->dest_port);
+}
+
+/*
+ * nss_vxlan_mac_rule_msg()
+ *	Log NSS Vxlan MAC rule message.
+ */
+static void nss_vxlan_log_mac_msg(struct nss_vxlan_mac_msg *nvmm)
+{
+	nss_trace("%p: NSS VXLAN MAC message \n"
+		"Encap Rule Src IP: %p\n"
+		"Encap Rule Dst Ip: %p\n"
+		"Vxlan VNet ID: %u\n"
+		"Vxlan Mac Addr: %pM",
+		nvmm,
+		&nvmm->encap.src_ip,
+		&nvmm->encap.dest_ip,
+		nvmm->vni,
+		nvmm->mac_addr);
+}
+
+/*
+ * nss_vxlan_log_rule_create_msg()
+ *	Log NSS Vxlan rule create message.
+ */
+static void nss_vxlan_log_rule_create_msg(struct nss_vxlan_msg *nvm)
+{
+	struct nss_vxlan_rule_msg *nvrm __maybe_unused = &nvm->msg.vxlan_create;
+	nss_vxlan_log_rule_msg(nvrm);
+}
+
+/*
+ * nss_vxlan_log_rule_destroy_msg()
+ *	Log NSS Vxlan rule destroy message.
+ */
+static void nss_vxlan_log_rule_destroy_msg(struct nss_vxlan_msg *nvm)
+{
+	struct nss_vxlan_rule_msg *nvrm __maybe_unused = &nvm->msg.vxlan_destroy;
+	nss_vxlan_log_rule_msg(nvrm);
+}
+
+/*
+ * nss_vxlan_log_enable_msg()
+ *	Log NSS Vxlan rule enable message.
+ */
+static void nss_vxlan_log_enable_msg(struct nss_vxlan_msg *nvm)
+{
+	nss_trace("%p: NSS VXLAN Tunnel state message: Enable \n", nvm);
+}
+
+/*
+ * nss_vxlan_log_disable_msg()
+ *	Log NSS Vxlan rule disable message.
+ */
+static void nss_vxlan_log_disable_msg(struct nss_vxlan_msg *nvm)
+{
+	nss_trace("%p: NSS VXLAN Tunnel state message: Disable \n", nvm);
+}
+
+/*
+ * nss_vxlan_log_mac_add_msg()
+ *	Log NSS VXLAN mac rule add message.
+ */
+static void nss_vxlan_log_mac_add_msg(struct nss_vxlan_msg *nvm)
+{
+	struct nss_vxlan_mac_msg *nvmm __maybe_unused = &nvm->msg.mac_add;
+	nss_vxlan_log_mac_msg(nvmm);
+}
+
+/*
+ * nss_vxlan_log_mac_del_msg()
+ *	Log NSS VXLAN mac rule del message.
+ */
+static void nss_vxlan_log_mac_del_msg(struct nss_vxlan_msg *nvm)
+{
+	struct nss_vxlan_mac_msg *nvmm __maybe_unused = &nvm->msg.mac_del;
+	nss_vxlan_log_mac_msg(nvmm);
+}
+
+/*
+ * nss_vxlan_log_verbose()
+ *	Log message contents.
+ */
+static void nss_vxlan_log_verbose(struct nss_vxlan_msg *nvm)
+{
+	switch (nvm->cm.type) {
+	case NSS_VXLAN_MSG_TYPE_TUN_CONFIGURE:
+		nss_vxlan_log_rule_create_msg(nvm);
+		break;
+
+	case NSS_VXLAN_MSG_TYPE_TUN_UNCONFIGURE:
+		nss_vxlan_log_rule_destroy_msg(nvm);
+		break;
+
+	case NSS_VXLAN_MSG_TYPE_TUN_ENABLE:
+		nss_vxlan_log_enable_msg(nvm);
+		break;
+
+	case NSS_VXLAN_MSG_TYPE_TUN_DISABLE:
+		nss_vxlan_log_disable_msg(nvm);
+		break;
+
+	case NSS_VXLAN_MSG_TYPE_MAC_ADD:
+		nss_vxlan_log_mac_add_msg(nvm);
+		break;
+
+	case NSS_VXLAN_MSG_TYPE_MAC_DEL:
+		nss_vxlan_log_mac_del_msg(nvm);
+		break;
+
+	case NSS_VXLAN_MSG_TYPE_STATS_SYNC:
+	case NSS_VXLAN_MSG_TYPE_MACDB_STATS:
+		break;
+
+	default:
+		nss_trace("%p: Invalid message type\n", nvm);
+		break;
+	}
+}
+
+/*
+ * nss_vxlan_log_tx_msg()
+ *	Log messages transmitted to FW.
+ */
+void nss_vxlan_log_tx_msg(struct nss_vxlan_msg *nvm)
+{
+	if (nvm->cm.type >= NSS_VXLAN_MSG_TYPE_MAX) {
+		nss_warning("%p: Invalid message type\n", nvm);
+		return;
+	}
+
+	nss_info("%p: type[%d]:%s\n", nvm, nvm->cm.type, nss_vxlan_log_message_types_str[nvm->cm.type]);
+	nss_vxlan_log_verbose(nvm);
+}
+
+/*
+ * nss_vxlan_log_rx_msg()
+ *	Log messages received from FW.
+ */
+void nss_vxlan_log_rx_msg(struct nss_vxlan_msg *nvm)
+{
+	if (nvm->cm.response >= NSS_CMN_RESPONSE_LAST) {
+		nss_warning("%p: Invalid response\n", nvm);
+		return;
+	}
+
+	if (nvm->cm.response == NSS_CMN_RESPONSE_NOTIFY || (nvm->cm.response == NSS_CMN_RESPONSE_ACK)) {
+		nss_info("%p: type[%d]:%s, response[%d]:%s\n", nvm, nvm->cm.type,
+			nss_vxlan_log_message_types_str[nvm->cm.type],
+			nvm->cm.response, nss_cmn_response_str[nvm->cm.response]);
+		goto verbose;
+	}
+
+	if (nvm->cm.error >= NSS_VXLAN_ERROR_TYPE_MAX) {
+		nss_warning("%p: msg failure - type[%d]:%s, response[%d]:%s, error[%d]:Invalid error\n",
+			nvm, nvm->cm.type, nss_vxlan_log_message_types_str[nvm->cm.type],
+			nvm->cm.response, nss_cmn_response_str[nvm->cm.response],
+			nvm->cm.error);
+		goto verbose;
+	}
+
+	nss_info("%p: msg nack - type[%d]:%s, response[%d]:%s, error[%d]:%s\n",
+		nvm, nvm->cm.type, nss_vxlan_log_message_types_str[nvm->cm.type],
+		nvm->cm.response, nss_cmn_response_str[nvm->cm.response],
+		nvm->cm.error, nss_vxlan_log_error_response_types_str[nvm->cm.error]);
+
+verbose:
+	nss_vxlan_log_verbose(nvm);
+}
diff --git a/nss_vxlan_log.h b/nss_vxlan_log.h
new file mode 100644
index 0000000..2db12be
--- /dev/null
+++ b/nss_vxlan_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_VXLAN_LOG_H__
+#define __NSS_VXLAN_LOG_H__
+
+/*
+ * nss_vxlan_log.h
+ *	NSS VXLAN Log Header File.
+ */
+
+/*
+ * nss_vxlan_log_tx_msg
+ *	Logs a Vxlan message that is sent to the NSS firmware.
+ */
+void nss_vxlan_log_tx_msg(struct nss_vxlan_msg *nvm);
+
+/*
+ * nss_vxlan_log_rx_msg
+ *	Logs a Vxlan message that is received from the NSS firmware.
+ */
+void nss_vxlan_log_rx_msg(struct nss_vxlan_msg *nvm);
+
+#endif /* __NSS_VXLAN_LOG_H__ */
diff --git a/nss_vxlan_stats.c b/nss_vxlan_stats.c
new file mode 100644
index 0000000..670a092
--- /dev/null
+++ b/nss_vxlan_stats.c
@@ -0,0 +1,122 @@
+/*
+ **************************************************************************
+ * 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_vxlan_stats.h"
+#include <nss_vxlan.h>
+
+#define NSS_VXLAN_STATS_MAX_LINES (NSS_STATS_NODE_MAX + 32)
+					/**< Maximum number of lines for VXLAN statistics dump. */
+#define NSS_VXLAN_STATS_SIZE_PER_IF (NSS_STATS_MAX_STR_LENGTH * NSS_VXLAN_STATS_MAX_LINES)
+					/**< Total number of statistics per VXLAN interface. */
+
+/*
+ * nss_vxlan_stats_read()
+ *	Read vxlan node statiistics.
+ */
+static ssize_t nss_vxlan_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	struct nss_ctx_instance *nss_ctx = nss_vxlan_get_ctx();
+	enum nss_dynamic_interface_type type;
+	ssize_t bytes_read = 0;
+	size_t len = 0, size;
+	uint32_t if_num;
+	char *buf;
+
+	size = NSS_VXLAN_STATS_SIZE_PER_IF;
+	buf = kzalloc(size, GFP_KERNEL);
+	if (!buf) {
+		nss_warning("Could not allocate memory for local statistics buffer\n");
+		return 0;
+	}
+
+	/*
+	 * Common node stats for each VxLAN dynamic interface.
+	 */
+	for(if_num = 0; if_num < NSS_MAX_NET_INTERFACES; if_num++) {
+		if (if_num == NSS_VXLAN_INTERFACE) {
+			len += scnprintf(buf + len, size - len, "\nBase node if_num:%03u", if_num);
+			len += scnprintf(buf + len, size - len, "\n-------------------\n");
+			len = nss_stats_fill_common_stats(if_num, buf, len, size - len);
+			continue;
+		}
+
+		type = nss_dynamic_interface_get_type(nss_ctx, if_num);
+		switch (type) {
+		case NSS_DYNAMIC_INTERFACE_TYPE_VXLAN_INNER:
+			len += scnprintf(buf + len, size - len, "\nInner if_num:%03u", if_num);
+			break;
+
+		case NSS_DYNAMIC_INTERFACE_TYPE_VXLAN_OUTER:
+			len += scnprintf(buf + len, size - len, "\nOuter if_num:%03u", if_num);
+			break;
+
+		default:
+			continue;
+		}
+
+		len += scnprintf(buf + len, size - len, "\n-------------------\n");
+		len = nss_stats_fill_common_stats(if_num, buf, len, size - len);
+	}
+
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, buf, len);
+	kfree(buf);
+	return bytes_read;
+}
+
+/*
+ * nss_vxlan_stats_sync()
+ *	Update vxlan common node statistics.
+ */
+void nss_vxlan_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_vxlan_msg *nvm)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	struct nss_vxlan_stats_msg *msg_stats = &nvm->msg.stats;
+	uint64_t *if_stats;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * Update common node stats
+	 */
+	if_stats = nss_top->stats_node[nvm->cm.interface];
+	if_stats[NSS_STATS_NODE_RX_PKTS] += msg_stats->node_stats.rx_packets;
+	if_stats[NSS_STATS_NODE_RX_BYTES] += msg_stats->node_stats.rx_bytes;
+	if_stats[NSS_STATS_NODE_RX_QUEUE_0_DROPPED] += msg_stats->node_stats.rx_dropped[0];
+	if_stats[NSS_STATS_NODE_RX_QUEUE_1_DROPPED] += msg_stats->node_stats.rx_dropped[1];
+	if_stats[NSS_STATS_NODE_RX_QUEUE_2_DROPPED] += msg_stats->node_stats.rx_dropped[2];
+	if_stats[NSS_STATS_NODE_RX_QUEUE_3_DROPPED] += msg_stats->node_stats.rx_dropped[3];
+
+	if_stats[NSS_STATS_NODE_TX_PKTS] += msg_stats->node_stats.tx_packets;
+	if_stats[NSS_STATS_NODE_TX_BYTES] += msg_stats->node_stats.tx_bytes;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_vxlan_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(vxlan)
+
+/*
+ * nss_vxlan_stats_dentry_create()
+ *	Create vxlan statistics debug entry.
+ */
+void nss_vxlan_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("vxlan", &nss_vxlan_stats_ops);
+}
diff --git a/nss_vxlan_stats.h b/nss_vxlan_stats.h
new file mode 100644
index 0000000..b4748f4
--- /dev/null
+++ b/nss_vxlan_stats.h
@@ -0,0 +1,32 @@
+/*
+ **************************************************************************
+ * 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_VXLAN_STATS_H_
+#define _NSS_VXLAN_STATS_H_
+
+/*
+ * nss_vxlan_stats_dentry_create
+ *	Creates vxlan interface statistics debug entry.
+ */
+void nss_vxlan_stats_dentry_create(void);
+
+/*
+ * nss_vxlan_stats_sync
+ *	Update vxlan common node statistics.
+ */
+void nss_vxlan_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_vxlan_msg *nvm);
+
+#endif /* _NSS_VXLAN_STATS_H_ */