[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_ */