Merge "[qca-nss-drv] New commands for NSS EXTAP."
diff --git a/Makefile b/Makefile
index 41b9ebf..30f9c5b 100644
--- a/Makefile
+++ b/Makefile
@@ -62,6 +62,7 @@
nss_pptp.o \
nss_pptp_stats.o \
nss_rps.o \
+ nss_qrfs.o \
nss_shaper.o \
nss_sjack.o \
nss_sjack_stats.o \
diff --git a/exports/arch/nss_fsm9010.h b/exports/arch/nss_fsm9010.h
index dcddc63..f5cadbf 100644
--- a/exports/arch/nss_fsm9010.h
+++ b/exports/arch/nss_fsm9010.h
@@ -22,12 +22,12 @@
#define __NSS_FSM9010_H
/**
- * @addtogroup nss_fsm9010_subsystem
+ * @addtogroup nss_arch_macros
* @{
*/
-#define NSS_MAX_NUM_PRI 1 /**< Maximum number of priority queues in NSS. */
-#define NSS_HOST_CORES 4 /**< Number of host cores. */
+#define NSS_MAX_NUM_PRI 1 /**< Maximum number of priority queues in NSS for the FSM9010 chipset. */
+#define NSS_HOST_CORES 4 /**< Number of host cores for the FSM9010 chipset. */
/**
* @}
diff --git a/exports/arch/nss_ipq40xx.h b/exports/arch/nss_ipq40xx.h
index e96f15a..dc84984 100644
--- a/exports/arch/nss_ipq40xx.h
+++ b/exports/arch/nss_ipq40xx.h
@@ -22,12 +22,12 @@
#define __NSS_IPQ40XX_H
/**
- * @addtogroup nss_ipq40xx_subsystem
+ * @addtogroup nss_arch_macros
* @{
*/
-#define NSS_MAX_NUM_PRI 1 /**< Maximum number of priority queues in NSS. */
-#define NSS_HOST_CORES 4 /**< Number of host cores. */
+#define NSS_MAX_NUM_PRI 1 /**< Maximum number of priority queues in NSS for the IPQ40xx chipsets. */
+#define NSS_HOST_CORES 4 /**< Number of host cores for the IPQ40xx chipsets. */
/**
* @}
diff --git a/exports/arch/nss_ipq806x.h b/exports/arch/nss_ipq806x.h
index ffcd4da..b8f4d05 100644
--- a/exports/arch/nss_ipq806x.h
+++ b/exports/arch/nss_ipq806x.h
@@ -22,12 +22,12 @@
#define __NSS_IPQ806X_H
/**
- * @addtogroup nss_ipq806x_subsystem
+ * @addtogroup nss_arch_macros
* @{
*/
-#define NSS_MAX_NUM_PRI 1 /**< Maximum number of priority queues in NSS. */
-#define NSS_HOST_CORES 2 /**< Number of host cores. */
+#define NSS_MAX_NUM_PRI 1 /**< Maximum number of priority queues in NSS for the IPQ806x chipsets. */
+#define NSS_HOST_CORES 2 /**< Number of host cores for the IPQ806x chipsets. */
/**
* @}
diff --git a/exports/arch/nss_ipq807x.h b/exports/arch/nss_ipq807x.h
index e910658..05122bc 100644
--- a/exports/arch/nss_ipq807x.h
+++ b/exports/arch/nss_ipq807x.h
@@ -22,12 +22,12 @@
#define __NSS_IPQ807X_H
/**
- * @addtogroup nss_ipq807x_subsystem
+ * @addtogroup nss_arch_macros
* @{
*/
-#define NSS_MAX_NUM_PRI 4 /**< Maximum number of priority queues in NSS. */
-#define NSS_HOST_CORES 4 /**< Number of host cores. */
+#define NSS_MAX_NUM_PRI 4 /**< Maximum number of priority queues in NSS for the IPQ807x chipsets. */
+#define NSS_HOST_CORES 4 /**< Number of host cores for the IPQ807x chipsets. */
/**
* @}
diff --git a/exports/arch/nss_ipq807x_64.h b/exports/arch/nss_ipq807x_64.h
index f75f2fe..ca6d07f 100644
--- a/exports/arch/nss_ipq807x_64.h
+++ b/exports/arch/nss_ipq807x_64.h
@@ -22,12 +22,12 @@
#define __NSS_IPQ807x_64_H
/**
- * @addtogroup nss_ipq807x_subsystem
+ * @addtogroup nss_arch_macros
* @{
*/
-#define NSS_MAX_NUM_PRI 4 /**< Maximum number of priority queues in NSS. */
-#define NSS_HOST_CORES 4 /**< Number of host cores. */
+#define NSS_MAX_NUM_PRI 4 /**< Maximum number of priority queues in NSS for the IPQ807x 64-bit chipsets. */
+#define NSS_HOST_CORES 4 /**< Number of host cores for the IPQ807x 64-bit chipsets. */
/**
* @}
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index ec97f4b..554f55c 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, 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.
@@ -68,6 +68,7 @@
#include "nss_vlan.h"
#include "nss_wifili_if.h"
#include "nss_project.h"
+#include "nss_qrfs.h"
#endif
/**
@@ -86,7 +87,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 50 /**< Maximum number of special interfaces. */
+#define NSS_MAX_SPECIAL_INTERFACES 52 /**< Maximum number of special interfaces. */
#define NSS_MAX_WIFI_RADIO_INTERFACES 3 /**< Maximum number of radio interfaces. */
/*
@@ -201,11 +202,15 @@
#define NSS_GRE_INTERFACE (NSS_SPECIAL_IF_START + 46)
/**< Special interface number for GRE. */
#define NSS_WIFILI_INTERFACE (NSS_SPECIAL_IF_START + 47)
- /**< Special interface number for WIFILI. */
+ /**< Special interface number for wifili. */
#define NSS_PROJECT_INTERFACE (NSS_SPECIAL_IF_START + 48)
/**< Special interface number for project node. */
#define NSS_PBUF_MGR_FREE_INTERFACE (NSS_SPECIAL_IF_START + 49)
/**< Special interface number for PBUF_MGR_FREE node. */
+#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. */
/**
* Wireless Multimedia Extention Access Category to TID. @hideinitializer
diff --git a/exports/nss_dtls_cmn.h b/exports/nss_dtls_cmn.h
index 640f487..7571bb9 100644
--- a/exports/nss_dtls_cmn.h
+++ b/exports/nss_dtls_cmn.h
@@ -285,12 +285,13 @@
* nss_dtls_cmn_data_callback_t \n
* nss_dtls_cmn_msg_callback_t
*
- * @param[in] if_num NSS interface number.
- * @param[in] data_cb Callback function for the message.
- * @param[in] msg_cb Callback for DTLS tunnel message.
- * @param[in] netdev Pointer to the associated network device.
- * @param[in] features Data socket buffer types supported by this interface.
- * @param[in] app_ctx Pointer to the application context.
+ * @param[in] if_num NSS interface number.
+ * @param[in] data_cb Callback function for the message.
+ * @param[in] msg_cb Callback for DTLS tunnel message.
+ * @param[in] netdev Pointer to the associated network device.
+ * @param[in] features Data socket buffer types supported by this interface.
+ * @param[in] type Type of message.
+ * @param[in] app_ctx Pointer to the application context.
*
* @return
* Pointer to the NSS core context.
@@ -321,9 +322,9 @@
* nss_dtls_cmn_notify_register
* Register an event callback to handle notification from DTLS firmware package.
*
- * @param[in] if_num NSS interface number.
- * @param[in] ev_cb Callback for DTLS tunnel message.
- * @param[in] app_data Pointer to the application context.
+ * @param[in] ifnum NSS interface number.
+ * @param[in] ev_cb Callback for DTLS tunnel message.
+ * @param[in] app_data Pointer to the application context.
*
* @return
* Pointer to NSS core context.
@@ -335,7 +336,7 @@
* nss_dtls_cmn_notify_unregister
* Unregister an event callback.
*
- * @param[in] if_num NSS interface number.
+ * @param[in] ifnum NSS interface number.
*
* @return
* None.
diff --git a/exports/nss_dynamic_interface.h b/exports/nss_dynamic_interface.h
index 0c037d4..97fafa8 100644
--- a/exports/nss_dynamic_interface.h
+++ b/exports/nss_dynamic_interface.h
@@ -38,7 +38,7 @@
NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR,
NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP,
NSS_DYNAMIC_INTERFACE_TYPE_TUN6RD,
- NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR,
+ NSS_DYNAMIC_INTERFACE_TYPE_RESERVED_0,
NSS_DYNAMIC_INTERFACE_TYPE_WIFI,
NSS_DYNAMIC_INTERFACE_TYPE_VAP,
NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6,
@@ -66,6 +66,8 @@
NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER,
NSS_DYNAMIC_INTERFACE_TYPE_GRE_TUNNEL_INLINE_INNER,
NSS_DYNAMIC_INTERFACE_TYPE_GRE_TUNNEL_INLINE_OUTER,
+ NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_N2H,
+ NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_H2N,
NSS_DYNAMIC_INTERFACE_TYPE_MAX
};
diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h
index e779ff2..c1de678 100644
--- a/exports/nss_ipv4.h
+++ b/exports/nss_ipv4.h
@@ -89,6 +89,9 @@
#define NSS_IPV4_RULE_CREATE_FLAG_EXCEPTION 0x200
/**< Rule to except packets. */
+#define NSS_IPV4_RULE_CREATE_FLAG_SRC_INTERFACE_CHECK 0x400
+ /**< Check the source interface for the rule. */
+
/*
* Validity flags for rule creation.
*/
@@ -642,7 +645,7 @@
NSS_IPV4_EXCEPTION_EVENT_6RD_NEEDS_FRAGMENTATION,
NSS_IPV4_EXCEPTION_EVENT_DSCP_MARKING_MISMATCH,
NSS_IPV4_EXCEPTION_EVENT_VLAN_MARKING_MISMATCH,
- NSS_IPV4_EXCEPTION_EVENT_DEPRECATED,
+ NSS_IPV4_EXCEPTION_EVENT_INTERFACE_MISMATCH,
NSS_IPV4_EXCEPTION_EVENT_GRE_HEADER_INCOMPLETE,
NSS_IPV4_EXCEPTION_EVENT_GRE_NO_ICME,
NSS_IPV4_EXCEPTION_EVENT_GRE_IP_OPTION,
diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h
index ad531ee..2d1d6bd 100644
--- a/exports/nss_ipv6.h
+++ b/exports/nss_ipv6.h
@@ -87,6 +87,9 @@
#define NSS_IPV6_RULE_CREATE_FLAG_EXCEPTION 0x200
/**< Rule to except packets. */
+#define NSS_IPV6_RULE_CREATE_FLAG_SRC_INTERFACE_CHECK 0x400
+ /**< Check the source interface for the rule. */
+
/*
* IPv6 rule creation validity flags.
*/
@@ -188,7 +191,7 @@
NSS_IPV6_EXCEPTION_EVENT_IVID_MISSING,
NSS_IPV6_EXCEPTION_EVENT_DSCP_MARKING_MISMATCH,
NSS_IPV6_EXCEPTION_EVENT_VLAN_MARKING_MISMATCH,
- NSS_IPV6_EXCEPTION_EVENT_DEPRECATED,
+ NSS_IPV6_EXCEPTION_EVENT_INTERFACE_MISMATCH,
NSS_IPV6_EXCEPTION_EVENT_GRE_NO_ICME,
NSS_IPV6_EXCEPTION_EVENT_GRE_NEEDS_FRAGMENTATION,
NSS_IPV6_EXCEPTION_EVENT_GRE_SMALL_HOP_LIMIT,
diff --git a/exports/nss_qrfs.h b/exports/nss_qrfs.h
new file mode 100644
index 0000000..cf1ed0a
--- /dev/null
+++ b/exports/nss_qrfs.h
@@ -0,0 +1,183 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017-2018, 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_qrfs.h
+ * NSS QRFS interface definitions.
+ */
+
+#ifndef __NSS_QRFS_H
+#define __NSS_QRFS_H
+
+/**
+ * @addtogroup nss_qrfs_subsystem
+ * @{
+ */
+
+/**
+ * nss_qrfs_msg_types
+ * Message types for the NSS QRFS.
+ */
+enum nss_qrfs_msg_types {
+ NSS_QRFS_MSG_FLOW_ADD,
+ NSS_QRFS_MSG_FLOW_DELETE,
+ NSS_QRFS_MSG_MAC_ADD,
+ NSS_QRFS_MSG_MAC_DELETE,
+ NSS_QRFS_MSG_MAX,
+};
+
+/**
+ * nss_qrfs_error_types
+ * Error types for the NSS QRFS.
+ */
+enum nss_qrfs_error_types {
+ NSS_QRFS_ERROR_INVALID_MSG_TYPE,
+ NSS_QRFS_ERROR_INVALID_MSG_SIZE,
+ NSS_QRFS_ERROR_INVALID_IP_VERSION,
+ NSS_QRFS_ERROR_V4_FLOW_TABLE_FULL,
+ NSS_QRFS_ERROR_V6_FLOW_TABLE_FULL,
+ NSS_QRFS_ERROR_MAC_TABLE_FULL,
+ NSS_QRFS_ERROR_MAX,
+};
+
+/**
+ * nss_qrfs_flow_rule_msg
+ * Information for the NSS QRFS flow rule message.
+ */
+struct nss_qrfs_flow_rule_msg {
+ uint16_t src_port; /**< Source port. */
+ uint16_t dst_port; /**< Destination port. */
+ uint32_t ip_version; /**< IPv4:4 IPv6:6. */
+ uint32_t src_addr[4]; /**< Source IP address. */
+ uint32_t dst_addr[4]; /**< Destination IP address. */
+ uint16_t protocol; /**< IP protocol. */
+ uint16_t cpu; /**< CPU core ID. */
+ uint32_t if_num; /**< Physical interface number. */
+};
+
+/**
+ * nss_qrfs_mac_rule_msg
+ * Information for the NSS QRFS MAC rule message.
+ */
+struct nss_qrfs_mac_rule_msg {
+ uint8_t mac[ETH_ALEN]; /**< Ethernet address. */
+ uint16_t cpu; /**< CPU core ID. */
+ uint32_t if_num; /**< Physical interface number. */
+};
+
+/**
+ * nss_qrfs_msg
+ * Data for sending and receiving NSS QRFS rule messages.
+ */
+struct nss_qrfs_msg {
+ struct nss_cmn_msg cm; /**< Common message header. */
+
+ /**
+ * Payload of a NSS QRFS rule message.
+ */
+ union {
+ struct nss_qrfs_flow_rule_msg flow_add; /**< Add flow rule. */
+ struct nss_qrfs_flow_rule_msg flow_delete; /**< Delete flow rule. */
+ struct nss_qrfs_mac_rule_msg mac_add; /**< Add MAC rule. */
+ struct nss_qrfs_mac_rule_msg mac_delete; /**< Delete MAC rule. */
+ } msg; /**< Message payload. */
+};
+
+/**
+ * Callback function for receiving QRFS messages.
+ *
+ * @datatypes
+ * nss_qrfs_msg
+ *
+ * @param[in] app_data Pointer to the application context of the message.
+ * @param[in] msg Pointer to the message data.
+ */
+typedef void (*nss_qrfs_msg_callback_t)(void *app_data, struct nss_qrfs_msg *msg);
+
+/**
+ * nss_qrfs_register_handler
+ * Registers the QRFS interface with the NSS for sending and receiving
+ * messages.
+ *
+ * @datatypes
+ * nss_ctx_instance
+ *
+ * @return
+ * None.
+ */
+void nss_qrfs_register_handler(struct nss_ctx_instance *nss_ctx);
+
+/**
+ * nss_qrfs_notify_register
+ * Registers a notifier callback for QRFS messages with the NSS.
+ *
+ * @datatypes
+ * nss_qrfs_msg_callback_t
+ *
+ * @param[in] core NSS core number index to the notifier callback table.
+ * @param[in] cb Callback function for the message.
+ * @param[in] app_data Pointer to the application context of the message.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+struct nss_ctx_instance *nss_qrfs_notify_register(int core, nss_qrfs_msg_callback_t cb, void *app_data);
+
+/**
+ * nss_qrfs_notify_unregister
+ * Deregisters a QRFS message notifier callback from the NSS.
+ *
+ * @param[in] core NSS core number index to the notifier callback table.
+ *
+ * @return
+ * None.
+ */
+void nss_qrfs_notify_unregister(int core);
+
+/**
+ * nss_qrfs_set_flow_rule
+ * Sends a QRFS message to the NSS core to set the flow rule.
+ *
+ * @datatypes
+ * net_device \n
+ * flow_keys
+ *
+ * @param[in] netdev Pointer to the network device.
+ * @param[in] if_num Physical interface number.
+ * @param[in] skb Pointer to the SKB buffer.
+ * @param[in] cpu CPU number to set in the flow table.
+ * @param[in] action Action to perform on the flow table.
+ *
+ * @return
+ * Status of the Tx operation.
+ */
+nss_tx_status_t nss_qrfs_set_flow_rule(struct net_device *netdev, uint32_t if_num,
+ struct sk_buff *skb, uint32_t cpu, uint32_t action);
+
+/**
+ * nss_qrfs_init
+ * Initializes the QRFS.
+ *
+ * @return
+ * None.
+ */
+void nss_qrfs_init(void);
+
+/**
+ * @}
+ */
+
+#endif /* __NSS_QRFS_H */
diff --git a/exports/nss_tunipip6.h b/exports/nss_tunipip6.h
index 6755055..3c19c4b 100644
--- a/exports/nss_tunipip6.h
+++ b/exports/nss_tunipip6.h
@@ -27,7 +27,7 @@
* @{
*/
-#define NSS_TUNIPIP6_MAX_FMR_NUMBER 4
+#define NSS_TUNIPIP6_MAX_FMR_NUMBER 4 /**< Maximum number of forward mapping rule (FMR). */
/**
* nss_tunipip6_fmr
diff --git a/exports/nss_virt_if.h b/exports/nss_virt_if.h
index b3f8c2d..f83e527 100644
--- a/exports/nss_virt_if.h
+++ b/exports/nss_virt_if.h
@@ -48,8 +48,7 @@
NSS_VIRT_IF_BSHAPER_CONFIG = NSS_IF_BSHAPER_CONFIG,
NSS_VIRT_IF_VSI_ASSIGN = NSS_IF_VSI_ASSIGN,
NSS_VIRT_IF_VSI_UNASSIGN = NSS_IF_VSI_UNASSIGN,
- NSS_VIRT_IF_TX_CREATE_MSG = NSS_IF_MAX_MSG_TYPES + 1,
- NSS_VIRT_IF_TX_DESTROY_MSG,
+ NSS_VIRT_IF_TX_CONFIG_MSG = NSS_IF_MAX_MSG_TYPES + 1,
NSS_VIRT_IF_STATS_SYNC_MSG,
NSS_VIRT_IF_MAX_MSG_TYPES,
};
@@ -79,23 +78,17 @@
};
/**
- * nss_virt_if_create_msg
- * Configuration information for the virtual interface.
+ * nss_virt_if_config_msg
+ * Message information for configuring the virtual interface.
*/
-struct nss_virt_if_create_msg {
+struct nss_virt_if_config_msg {
uint32_t flags; /**< Interface flags. */
+ uint32_t sibling; /**< Sibling interface number. */
+ uint32_t nexthop; /**< Next hop interface number. */
uint8_t mac_addr[ETH_ALEN]; /**< MAC address. */
};
/**
- * nss_virt_if_destroy_msg
- * Deletion information for the virtual interface.
- */
-struct nss_virt_if_destroy_msg {
- int32_t reserved; /**< Reserved for future use. */
-};
-
-/**
* nss_virt_if_msg
* Data for sending and receiving virtual interface messages.
*/
@@ -108,10 +101,8 @@
union {
union nss_if_msgs if_msgs;
/**< NSS interface base message. */
- struct nss_virt_if_create_msg if_create;
+ struct nss_virt_if_config_msg if_config;
/**< Rule for creating a virtual interface. */
- struct nss_virt_if_destroy_msg if_destroy;
- /**< Rule for destroying a virtual interface. */
struct nss_virt_if_stats stats;
/**< Virtual interface statistics. */
} msg; /**< Message payload. */
@@ -161,7 +152,8 @@
*/
struct nss_virt_if_handle {
struct nss_ctx_instance *nss_ctx; /**< NSS context. */
- int32_t if_num; /**< Interface number. */
+ int32_t if_num_n2h; /**< Redirect interface number on NSS-to-host path. */
+ int32_t if_num_h2n; /**< Redirect interface number on host-to-NSS path. */
struct net_device *ndev; /**< Associated network device. */
struct nss_virt_if_pvt *pvt; /**< Private data structure. */
struct nss_virt_if_stats stats; /**< Virtual interface statistics. */
@@ -171,6 +163,15 @@
};
/**
+ * nss_virt_if_dp_type
+ * Virtual interface datapath types. Redirect interface on NSS-to-host path will be seen by ECM for rules.
+ */
+enum nss_virt_if_dp_type {
+ NSS_VIRT_IF_DP_REDIR_N2H, /**< Redirect interface on NSS-to-host path has zero value. */
+ NSS_VIRT_IF_DP_REDIR_H2N, /**< Redirect interface on host-to-NSS path has non-zero value. */
+};
+
+/**
* nss_virt_if_create
* Creates a virtual interface asynchronously.
*
@@ -327,6 +328,17 @@
extern int32_t nss_virt_if_get_interface_num(struct nss_virt_if_handle *handle);
/**
+ * nss_virt_if_verify_if_num
+ * Verifies if the interface is 802.3 redirect type.
+ *
+ * @param[in] if_num Interface number to be verified.
+ *
+ * @return
+ * True if if_num is 802.3 redirect type.
+ */
+bool nss_virt_if_verify_if_num(uint32_t if_num);
+
+/**
* @}
*/
diff --git a/nss_cmn.c b/nss_cmn.c
index 3f4a9fd..50c3834 100644
--- a/nss_cmn.c
+++ b/nss_cmn.c
@@ -173,9 +173,12 @@
*/
bool nss_cmn_interface_is_redirect(struct nss_ctx_instance *nss_ctx, int32_t interface_num)
{
- return (nss_dynamic_interface_get_type(nss_ctx, interface_num) == NSS_DYNAMIC_INTERFACE_TYPE_WIFI)
- || (nss_dynamic_interface_get_type(nss_ctx, interface_num) == NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR)
- || (nss_dynamic_interface_get_type(nss_ctx, interface_num) == NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED);
+ enum nss_dynamic_interface_type type = nss_dynamic_interface_get_type(nss_ctx, interface_num);
+
+ return type == NSS_DYNAMIC_INTERFACE_TYPE_WIFI
+ || type == NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_N2H
+ || type == NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_H2N
+ || type == NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED;
}
EXPORT_SYMBOL(nss_cmn_interface_is_redirect);
diff --git a/nss_core.c b/nss_core.c
index f74aa5f..adfb6e6 100644
--- a/nss_core.c
+++ b/nss_core.c
@@ -255,6 +255,7 @@
reg->app_data = NULL;
reg->ndev = NULL;
reg->features = 0;
+ reg->type = 0;
}
/*
@@ -832,8 +833,18 @@
return;
}
+ /*
+ * Check if core_id value is valid.
+ */
+ if (core_id > NSS_MAX_CORES) {
+ nss_warning("%p: Invalid core id: %d", nss_ctx, core_id);
+ return;
+ }
+
+ /*
+ * Check if need to convert to local core value.
+ */
if (core_id) {
- nss_assert(core_id < NSS_MAX_CORES);
nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[core_id - 1];
}
diff --git a/nss_core.h b/nss_core.h
index c860df2..77dbda3 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -528,7 +528,7 @@
* Network processing handler core ids (CORE0/CORE1) for various interfaces
*/
uint8_t phys_if_handler_id[NSS_MAX_PHYSICAL_INTERFACES];
- uint8_t virt_if_handler_id[NSS_MAX_VIRTUAL_INTERFACES];
+ uint8_t virt_if_handler_id;
uint8_t gre_redir_handler_id;
uint8_t gre_tunnel_handler_id;
uint8_t shaping_handler_id;
diff --git a/nss_data_plane/nss_data_plane_edma.c b/nss_data_plane/nss_data_plane_edma.c
index 9f90f75..29fd81c 100644
--- a/nss_data_plane/nss_data_plane_edma.c
+++ b/nss_data_plane/nss_data_plane_edma.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 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.
@@ -154,6 +154,24 @@
}
/*
+ * __nss_data_plane_rx_flow_steer()
+ * Called by nss-dp to set flow rule of a data plane
+ */
+static int __nss_data_plane_rx_flow_steer(struct nss_dp_data_plane_ctx *dpc, struct sk_buff *skb,
+ uint32_t cpu, bool is_add)
+{
+ struct nss_data_plane_edma_param *dp = (struct nss_data_plane_edma_param *)dpc;
+
+ if (is_add) {
+ return nss_qrfs_set_flow_rule(dpc->dev, dp->if_num, skb, cpu,
+ NSS_QRFS_MSG_FLOW_ADD);
+ }
+
+ return nss_qrfs_set_flow_rule(dpc->dev, dp->if_num, skb, cpu,
+ NSS_QRFS_MSG_FLOW_DELETE);
+}
+
+/*
* __nss_data_plane_buf()
* Called by nss-dp to pass a sk_buff for xmit
*/
@@ -220,6 +238,7 @@
.pause_on_off = __nss_data_plane_pause_on_off,
.vsi_assign = __nss_data_plane_vsi_assign,
.vsi_unassign = __nss_data_plane_vsi_unassign,
+ .rx_flow_steer = __nss_data_plane_rx_flow_steer,
};
/*
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index d3e31e5..38ffd50 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 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.
@@ -332,6 +332,7 @@
nss_dynamic_interface_register_handler(nss_ctx);
nss_n2h_register_handler(nss_ctx);
nss_project_register_handler(nss_ctx);
+ nss_qrfs_register_handler(nss_ctx);
/*
* Check functionalities are supported by this NSS core
@@ -355,11 +356,10 @@
nss_top->trustsec_tx_handler_id = nss_dev->id;
nss_trustsec_tx_register_handler();
- for (i = 0; i < NSS_MAX_VIRTUAL_INTERFACES; i++) {
- nss_top->virt_if_handler_id[i] = nss_dev->id;
- }
+ nss_top->virt_if_handler_id = nss_dev->id;
- nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR] = nss_dev->id;
+ nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_N2H] = nss_dev->id;
+ nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_H2N] = nss_dev->id;
}
if (npd->capwap_enabled == NSS_FEATURE_ENABLED) {
diff --git a/nss_init.c b/nss_init.c
index 870990d..738c9eb 100644
--- a/nss_init.c
+++ b/nss_init.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, 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.
@@ -702,6 +702,11 @@
nss_capwap_init();
/*
+ * Init QRFS
+ */
+ nss_qrfs_init();
+
+ /*
* INIT ppe on supported platform
*/
if (of_machine_is_compatible("qcom,ipq807x")) {
diff --git a/nss_ipv4_stats.c b/nss_ipv4_stats.c
index 7317f6a..81ef46a 100644
--- a/nss_ipv4_stats.c
+++ b/nss_ipv4_stats.c
@@ -74,7 +74,7 @@
"IPV4_6RD_NEEDS_FRAGMENTATION",
"IPV4_DSCP_MARKING_MISMATCH",
"IPV4_VLAN_MARKING_MISMATCH",
- "IPV4_DEPRECATED",
+ "IPV4_INTERFACE_MISMATCH",
"IPV4_GRE_HEADER_INCOMPLETE",
"IPV4_GRE_NO_ICME",
"IPV4_GRE_IP_OPTION",
diff --git a/nss_ipv6_stats.c b/nss_ipv6_stats.c
index 24b1e77..c4b2fab 100644
--- a/nss_ipv6_stats.c
+++ b/nss_ipv6_stats.c
@@ -55,7 +55,7 @@
"IPV6_INGRESS_VID_MISSING",
"IPV6_DSCP_MARKING_MISMATCH",
"IPV6_VLAN_MARKING_MISMATCH",
- "IPV6_DEPRECATED",
+ "IPV6_INTERFACE_MISMATCH",
"IPV6_GRE_NO_ICME",
"IPV6_GRE_NEEDS_FRAGMENTATION",
"IPV6_GRE_SMALL_HOP_LIMIT",
diff --git a/nss_qrfs.c b/nss_qrfs.c
new file mode 100644
index 0000000..d1125ed
--- /dev/null
+++ b/nss_qrfs.c
@@ -0,0 +1,482 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017-2018, 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"
+
+/*
+ * Notify data structure
+ */
+struct nss_qrfs_notify_data {
+ nss_qrfs_msg_callback_t qrfs_callback;
+ void *app_data;
+};
+
+static struct nss_qrfs_notify_data nss_qrfs_notify[NSS_CORE_MAX];
+
+/*
+ * nss_qrfs_verify_if_num()
+ * Verify if_num passed to us.
+ */
+static bool nss_qrfs_verify_if_num(uint32_t if_num)
+{
+ return if_num == NSS_QRFS_INTERFACE;
+}
+
+/*
+ * nss_qrfs_msg_handler()
+ * Handle NSS -> HLOS messages for QRFS
+ */
+static void nss_qrfs_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, void *app_data)
+{
+ struct nss_qrfs_msg *nqm = (struct nss_qrfs_msg *)ncm;
+ nss_qrfs_msg_callback_t cb;
+
+ if (!nss_qrfs_verify_if_num(ncm->interface)) {
+ nss_warning("%p: invalid interface %d for QRFS\n", nss_ctx, ncm->interface);
+ return;
+ }
+
+ /*
+ * Is this a valid request/response?
+ */
+ if (ncm->type >= NSS_QRFS_MSG_MAX) {
+ nss_warning("%p: invalid message %d for QRFS\n", nss_ctx, ncm->type);
+ return;
+ }
+
+ if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_qrfs_msg)) {
+ nss_warning("%p: message length is greater than required: %d\n", nss_ctx, nss_cmn_get_msg_len(ncm));
+ return;
+ }
+
+ /*
+ * Log failures
+ */
+ nss_core_log_msg_failures(nss_ctx, ncm);
+
+ /*
+ * Update the callback and app_data for NOTIFY messages
+ */
+ if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+ ncm->cb = (nss_ptr_t)nss_qrfs_notify[nss_ctx->id].qrfs_callback;
+ ncm->app_data = (nss_ptr_t)nss_qrfs_notify[nss_ctx->id].app_data;
+ }
+
+ /*
+ * Do we have a callback?
+ */
+ if (!ncm->cb) {
+ return;
+ }
+
+ /*
+ * callback
+ */
+ cb = (nss_qrfs_msg_callback_t)ncm->cb;
+ cb((void *)ncm->app_data, nqm);
+}
+
+/*
+ * nss_qrfs_get_ctx()
+ */
+static struct nss_ctx_instance *nss_qrfs_get_ctx(int core_id)
+{
+ return &nss_top_main.nss[core_id];
+}
+
+/*
+ * nss_qrfs_get_flow_keys()
+ * Get 5 tuple information from flow keys and set in flow rule message.
+ */
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 18, 21))
+static bool nss_qrfs_get_flow_keys(struct nss_ctx_instance *nss_ctx, struct sk_buff *skb,
+ struct nss_qrfs_flow_rule_msg *nqfrm)
+{
+ struct flow_keys keys;
+ uint16_t protocol = skb->protocol;
+ bool res;
+ struct ipv6hdr *ip6hdr;
+
+ res = skb_flow_dissect(skb, &keys);
+ if (!res) {
+ nss_warning("%p: failed to get flow keys\n", nss_ctx);
+ return res;
+ }
+
+ nqfrm->protocol = keys.ip_proto;
+ nqfrm->src_port = keys.port16[0];
+ nqfrm->dst_port = keys.port16[1];
+
+ if (protocol == htons(ETH_P_IP)) {
+ nqfrm->ip_version = 4;
+ nqfrm->src_addr[0] = keys.src;
+ nqfrm->dst_addr[0] = keys.dst;
+ return true;
+ }
+
+ nqfrm->ip_version = 6;
+ ip6hdr = (struct ipv6hdr *)skb_network_header(skb);
+ if (!ip6hdr) {
+ nss_warning("%p: failed to get IPv6 address\n", nss_ctx);
+ return false;
+ }
+
+ memcpy(nqfrm->src_addr, &ip6hdr->saddr, sizeof(struct in6_addr));
+ memcpy(nqfrm->dst_addr, &ip6hdr->daddr, sizeof(struct in6_addr));
+
+ return true;
+}
+#else
+static bool nss_qrfs_get_flow_keys(struct nss_ctx_instance *nss_ctx, struct sk_buff *skb,
+ struct nss_qrfs_flow_rule_msg *nqfrm)
+{
+ struct flow_keys keys;
+ bool res;
+
+ res = skb_flow_dissect_flow_keys(skb, &keys, 0);
+ if (!res) {
+ nss_warning("%p: failed to get flow keys\n", nss_ctx);
+ return res;
+ }
+
+ nqfrm->protocol = (uint16_t)keys.basic.ip_proto;
+ nqfrm->src_port = keys.ports.src;
+ nqfrm->dst_port = keys.ports.dst;
+
+ if (keys.basic.n_proto == htons(ETH_P_IP)) {
+ nqfrm->ip_version = 4;
+ nqfrm->src_addr[0] = keys.addrs.v4addrs.src;
+ nqfrm->dst_addr[0] = keys.addrs.v4addrs.dst;
+ return true;
+ }
+
+ nqfrm->ip_version = 6;
+ memcpy(nqfrm->src_addr, &keys.addrs.v6addrs.src, sizeof(struct in6_addr));
+ memcpy(nqfrm->dst_addr, &keys.addrs.v6addrs.dst, sizeof(struct in6_addr));
+
+ return true;
+}
+#endif
+
+/*
+ * nss_qrfs_flow_add_msg_callback()
+ * Callback function for receiving flow add response messages.
+ */
+static void nss_qrfs_flow_add_msg_callback(void *app_data, struct nss_qrfs_msg *nqm)
+{
+ struct nss_ctx_instance *nss_ctx __maybe_unused = (struct nss_ctx_instance *)app_data;
+ struct nss_qrfs_flow_rule_msg *nqfrm;
+
+ if (nqm->cm.type != NSS_QRFS_MSG_FLOW_ADD) {
+ nss_warning("%p: invalid flow response message %d\n", nss_ctx, nqm->cm.type);
+ return;
+ }
+
+ nqfrm = &nqm->msg.flow_add;
+
+ if ((nqfrm->ip_version != 4) && (nqfrm->ip_version != 6)) {
+ nss_warning("%p: invalid IP version %d\n", nss_ctx, nqfrm->ip_version);
+ return;
+ }
+
+ if (nqm->cm.response != NSS_CMN_RESPONSE_ACK) {
+ nss_warning("%p: flow add configuration error: %d for NSS core %d\n",
+ nss_ctx, nqm->cm.error, nss_ctx->id);
+ }
+}
+
+/*
+ * nss_qrfs_flow_delete_msg_callback()
+ * Callback function for receiving flow delete response messages.
+ */
+static void nss_qrfs_flow_delete_msg_callback(void *app_data, struct nss_qrfs_msg *nqm)
+{
+ struct nss_ctx_instance *nss_ctx __maybe_unused = (struct nss_ctx_instance *)app_data;
+ struct nss_qrfs_flow_rule_msg *nqfrm;
+
+ if (nqm->cm.type != NSS_QRFS_MSG_FLOW_DELETE) {
+ nss_warning("%p: invalid flow response message %d\n", nss_ctx, nqm->cm.type);
+ return;
+ }
+
+ nqfrm = &nqm->msg.flow_delete;
+
+ if ((nqfrm->ip_version != 4) && (nqfrm->ip_version != 6)) {
+ nss_warning("%p: invalid IP version %d\n", nss_ctx, nqfrm->ip_version);
+ return;
+ }
+
+ if (nqm->cm.response != NSS_CMN_RESPONSE_ACK) {
+ nss_warning("%p: flow delete configuration error: %d for NSS core %d\n",
+ nss_ctx, nqm->cm.error, nss_ctx->id);
+ }
+}
+
+/*
+ * nss_qrfs_msg_init()
+ * Initialize the common header of QRFS message
+ */
+static void nss_qrfs_msg_init(struct nss_qrfs_msg *nqm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data)
+{
+ nss_cmn_msg_init(&nqm->cm, if_num, type, len, cb, app_data);
+}
+
+/*
+ * nss_qrfs_tx_msg()
+ * Transmit a QRFS message to NSS firmware
+ */
+static nss_tx_status_t nss_qrfs_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_qrfs_msg *msg)
+{
+ struct nss_qrfs_msg *nqm;
+ struct nss_cmn_msg *ncm = &msg->cm;
+ struct sk_buff *nbuf;
+ int32_t status;
+
+ if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+ nss_warning("%p: message dropped as core not ready\n", nss_ctx);
+ return NSS_TX_FAILURE_NOT_READY;
+ }
+
+ /*
+ * Sanity check the message
+ */
+ if (!nss_qrfs_verify_if_num(ncm->interface)) {
+ nss_warning("%p: interface is not QRFS interface: %d\n", nss_ctx, ncm->interface);
+ return NSS_TX_FAILURE;
+ }
+
+ if (ncm->type >= NSS_QRFS_MSG_MAX) {
+ nss_warning("%p: message type is out of range: %d\n", nss_ctx, ncm->type);
+ return NSS_TX_FAILURE;
+ }
+
+ if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_qrfs_msg)) {
+ nss_warning("%p: message length is invalid: %d\n", nss_ctx, nss_cmn_get_msg_len(ncm));
+ return NSS_TX_FAILURE;
+ }
+
+ nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+ if (unlikely(!nbuf)) {
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
+ nss_warning("%p: message allocation failed\n", nss_ctx);
+ return NSS_TX_FAILURE;
+ }
+
+ /*
+ * Copy the message to our skb
+ */
+ nqm = (struct nss_qrfs_msg *)skb_put(nbuf, sizeof(struct nss_qrfs_msg));
+ memcpy(nqm, msg, sizeof(struct nss_qrfs_msg));
+
+ status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
+ if (status != NSS_CORE_STATUS_SUCCESS) {
+ dev_kfree_skb_any(nbuf);
+ nss_warning("%p: unable to enqueue QRFS message\n", nss_ctx);
+ return NSS_TX_FAILURE;
+ }
+
+ nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
+
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
+
+ return NSS_TX_SUCCESS;
+}
+
+/*
+ * nss_qrfs_add_flow_rule()
+ * Set a QRFS flow rule add message and transmit the message to NSS core.
+ */
+static nss_tx_status_t nss_qrfs_add_flow_rule(struct nss_ctx_instance *nss_ctx, uint32_t if_num,
+ struct sk_buff *skb, uint32_t cpu, bool need_cb)
+{
+ struct nss_qrfs_msg nqm;
+ struct nss_qrfs_flow_rule_msg *nqfrm;
+ nss_tx_status_t status;
+ nss_qrfs_msg_callback_t cb = NULL;
+ void *app_data = NULL;
+ bool res;
+
+ memset(&nqm, 0, sizeof(struct nss_qrfs_msg));
+
+ if (need_cb) {
+ cb = nss_qrfs_flow_add_msg_callback;
+ app_data = (void *)nss_ctx;
+ }
+
+ /*
+ * Initialize common header of QRFS flow rule add message.
+ */
+ nss_qrfs_msg_init(&nqm, NSS_QRFS_INTERFACE, NSS_QRFS_MSG_FLOW_ADD,
+ sizeof(struct nss_qrfs_flow_rule_msg), cb, app_data);
+
+ /*
+ * Set flow rule of QRFS flow rule add message
+ */
+ nqfrm = &nqm.msg.flow_add;
+ res = nss_qrfs_get_flow_keys(nss_ctx, skb, nqfrm);
+ if (!res) {
+ return NSS_TX_FAILURE;
+ }
+
+ nqfrm->cpu = (uint16_t)cpu;
+ nqfrm->if_num = if_num;
+
+ /*
+ * Send QRFS flow rule add message to NSS core
+ */
+ status = nss_qrfs_tx_msg(nss_ctx, &nqm);
+ if (status == NSS_TX_SUCCESS) {
+ return status;
+ }
+
+ return NSS_TX_FAILURE;
+}
+
+/*
+ * nss_qrfs_delete_flow_rule()
+ * Set a QRFS delete flow rule message and transmit the message to all NSS core.
+ */
+static nss_tx_status_t nss_qrfs_delete_flow_rule(struct nss_ctx_instance *nss_ctx, uint32_t if_num,
+ struct sk_buff *skb, uint32_t cpu, bool need_cb)
+{
+ struct nss_qrfs_msg nqm;
+ struct nss_qrfs_flow_rule_msg *nqfrm;
+ nss_tx_status_t status;
+ nss_qrfs_msg_callback_t cb = NULL;
+ void *app_data = NULL;
+ bool res;
+
+ memset(&nqm, 0, sizeof(struct nss_qrfs_msg));
+
+ if (need_cb) {
+ cb = nss_qrfs_flow_delete_msg_callback;
+ app_data = (void *)nss_ctx;
+ }
+
+ /*
+ * Initialize common header of QRFS flow rule delete message.
+ */
+ nss_qrfs_msg_init(&nqm, NSS_QRFS_INTERFACE, NSS_QRFS_MSG_FLOW_DELETE,
+ sizeof(struct nss_qrfs_flow_rule_msg), cb, app_data);
+
+ /*
+ * Set flow rule of QRFS flow rule delete message
+ */
+ nqfrm = &nqm.msg.flow_delete;
+ res = nss_qrfs_get_flow_keys(nss_ctx, skb, nqfrm);
+ if (!res) {
+ return NSS_TX_FAILURE;
+ }
+
+ nqfrm->cpu = (uint16_t)cpu;
+ nqfrm->if_num = if_num;
+
+ /*
+ * Send QRFS flow rule delete message to NSS core
+ */
+ status = nss_qrfs_tx_msg(nss_ctx, &nqm);
+ if (status == NSS_TX_SUCCESS) {
+ return status;
+ }
+
+ return NSS_TX_FAILURE;
+}
+
+/*
+ * nss_qrfs_set_flow_rule()
+ * Set a QRFS flow rule message and transmit the message to all NSS cores.
+ */
+nss_tx_status_t nss_qrfs_set_flow_rule(struct net_device *netdev, uint32_t if_num,
+ struct sk_buff *skb, uint32_t cpu, uint32_t action)
+{
+ struct nss_ctx_instance *nss_ctx;
+ nss_tx_status_t status;
+ int i;
+
+ for (i = 0; i < NSS_CORE_MAX; i++) {
+ nss_ctx = nss_qrfs_get_ctx(i);
+
+ /*
+ * Set QRFS flow rule message and transmit the message to NSS core.
+ */
+ if (action == NSS_QRFS_MSG_FLOW_ADD) {
+ status = nss_qrfs_add_flow_rule(nss_ctx, if_num, skb, cpu, true);
+ } else {
+ status = nss_qrfs_delete_flow_rule(nss_ctx, if_num, skb, cpu, true);
+ }
+
+ if (status != NSS_TX_SUCCESS) {
+ nss_warning("%p: failed to send flow rule to NSS core %d\n", nss_ctx, i);
+ return NSS_TX_FAILURE;
+ }
+ }
+
+ return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_qrfs_set_flow_rule);
+
+/*
+ * nss_qrfs_register_handler()
+ */
+void nss_qrfs_register_handler(struct nss_ctx_instance *nss_ctx)
+{
+ nss_core_register_handler(nss_ctx, NSS_QRFS_INTERFACE, nss_qrfs_msg_handler, NULL);
+}
+EXPORT_SYMBOL(nss_qrfs_register_handler);
+
+/*
+ * nss_qrfs_notify_register()
+ * Register to receive QRFS notify messages.
+ */
+struct nss_ctx_instance *nss_qrfs_notify_register(int core, nss_qrfs_msg_callback_t cb, void *app_data)
+{
+ if (core >= NSS_CORE_MAX) {
+ nss_warning("Input core number %d is wrong\n", core);
+ return NULL;
+ }
+
+ nss_qrfs_notify[core].qrfs_callback = cb;
+ nss_qrfs_notify[core].app_data = app_data;
+
+ return (struct nss_ctx_instance *)&nss_top_main.nss[core];
+}
+
+/*
+ * nss_qrfs_notify_unregister()
+ * Unregister to receive QRFS notify messages.
+ */
+void nss_qrfs_notify_unregister(int core)
+{
+ if (core >= NSS_CORE_MAX) {
+ nss_warning("Input core number %d is wrong\n", core);
+ return;
+ }
+
+ nss_qrfs_notify[core].qrfs_callback = NULL;
+ nss_qrfs_notify[core].app_data = NULL;
+}
+
+/*
+ * nss_qrfs_init()
+ */
+void nss_qrfs_init(void)
+{
+ int core;
+
+ for (core = 0; core < NSS_CORE_MAX; core++) {
+ nss_qrfs_notify_register(core, NULL, NULL);
+ }
+}
diff --git a/nss_virt_if.c b/nss_virt_if.c
index ec3b48d..4c4fa8b 100644
--- a/nss_virt_if.c
+++ b/nss_virt_if.c
@@ -39,6 +39,27 @@
DEFINE_SPINLOCK(nss_virt_if_lock);
/*
+ * nss_virt_if_get_context()
+ */
+struct nss_ctx_instance *nss_virt_if_get_context(void)
+{
+ return &nss_top_main.nss[nss_top_main.virt_if_handler_id];
+}
+
+/*
+ * nss_virt_if_verify_if_num()
+ * Verify if_num passed to us.
+ */
+bool nss_virt_if_verify_if_num(uint32_t if_num)
+{
+ enum nss_dynamic_interface_type type = nss_dynamic_interface_get_type(nss_virt_if_get_context(), if_num);
+
+ return type == NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_N2H
+ || type == NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_H2N;
+}
+EXPORT_SYMBOL(nss_virt_if_verify_if_num);
+
+/*
* nss_virt_if_msg_handler()
* Handle msg responses from the FW on virtual interfaces
*/
@@ -67,7 +88,7 @@
return nss_if_msg_handler(nss_ctx, ncm, app_data);
}
- if (!NSS_IS_IF_TYPE(DYNAMIC, ncm->interface)) {
+ if (!nss_virt_if_verify_if_num(ncm->interface)) {
nss_warning("%p: response for another interface: %d", nss_ctx, ncm->interface);
return;
}
@@ -187,114 +208,40 @@
}
/*
- * nss_virt_if_get_context()
- */
-struct nss_ctx_instance *nss_virt_if_get_context(int i)
-{
- return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.virt_if_handler_id[i]];
-}
-
-/*
- * nss_virt_if_register_handler()
- * register msg handler for virtual interface.
- */
-static uint32_t nss_virt_if_register_handler(struct nss_ctx_instance *nss_ctx, struct nss_virt_if_handle *handle)
-{
- uint32_t ret;
- int32_t if_num = handle->if_num;
-
- ret = nss_core_register_handler(nss_ctx, if_num, nss_virt_if_msg_handler, NULL);
- if (ret != NSS_CORE_STATUS_SUCCESS) {
- nss_warning("%d: Message handler failed to be registered for interface\n", if_num);
- return NSS_VIRT_IF_CORE_FAILURE;
- }
-
- return NSS_VIRT_IF_SUCCESS;
-}
-
-/*
- * nss_virt_if_handle_destroy_cb()
- * Callback to handle the response of destroy message.
- */
-static void nss_virt_if_handle_destroy_cb(void *app_data, struct nss_dynamic_interface_msg *ndim)
-{
- nss_virt_if_msg_callback_t cb;
- void *data;
- uint32_t index;
- struct nss_virt_if_handle *handle = (struct nss_virt_if_handle *)app_data;
-
- cb = handle->cb;
- data = handle->app_data;
-
- if (ndim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_warning("%p: Received NACK from DI\n", handle->nss_ctx);
- goto callback;
- }
-
- index = NSS_VIRT_IF_GET_INDEX(handle->if_num);
- spin_lock_bh(&nss_virt_if_lock);
- nss_virt_if_handle_t[index] = NULL;
- spin_unlock_bh(&nss_virt_if_lock);
-
- kfree(handle);
-callback:
- if (!cb) {
- nss_warning("callback is NULL\n");
- return;
- }
-
- cb(data, &ndim->cm);
-}
-
-/*
- * nss_virt_if_handle_destroy()
- * Destroy the virt handle either due to request from WLAN or due to error.
- */
-static int nss_virt_if_handle_destroy(struct nss_virt_if_handle *handle)
-{
- nss_tx_status_t status;
- int32_t if_num = handle->if_num;
- struct nss_ctx_instance *nss_ctx = handle->nss_ctx;
- struct nss_dynamic_interface_msg ndim;
- struct nss_dynamic_interface_dealloc_node_msg *ndid;
-
- nss_dynamic_interface_msg_init(&ndim, NSS_DYNAMIC_INTERFACE, NSS_DYNAMIC_INTERFACE_DEALLOC_NODE,
- sizeof(struct nss_dynamic_interface_dealloc_node_msg), nss_virt_if_handle_destroy_cb, (void *)handle);
-
- ndid = &ndim.msg.dealloc_node;
- ndid->type = NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR;
- ndid->if_num = if_num;
-
- /*
- * Send an asynchronous message to the firmware.
- */
- status = nss_dynamic_interface_tx(nss_ctx, &ndim);
- if (status != NSS_TX_SUCCESS) {
- nss_warning("%p: Dynamic interface destroy failed status %d\n", nss_ctx, status);
- return status;
- }
-
- return status;
-}
-
-/*
* nss_virt_if_handle_destroy_sync()
* Destroy the virt handle either due to request from user or due to error, synchronously.
*/
static int nss_virt_if_handle_destroy_sync(struct nss_virt_if_handle *handle)
{
nss_tx_status_t status;
- int32_t if_num = handle->if_num;
- int32_t index = NSS_VIRT_IF_GET_INDEX(if_num);
+ int32_t if_num_n2h = handle->if_num_n2h;
+ int32_t if_num_h2n = handle->if_num_h2n;
+ int32_t index_n2h;
+ int32_t index_h2n;
- status = nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR);
+ if (!nss_virt_if_verify_if_num(if_num_n2h) || !nss_virt_if_verify_if_num(if_num_h2n)) {
+ nss_warning("%p: bad interface numbers %d %d\n", handle->nss_ctx, if_num_n2h, if_num_h2n);
+ return NSS_TX_FAILURE_BAD_PARAM;
+ }
+
+ index_n2h = NSS_VIRT_IF_GET_INDEX(if_num_n2h);
+ index_h2n = NSS_VIRT_IF_GET_INDEX(if_num_h2n);
+
+ status = nss_dynamic_interface_dealloc_node(if_num_n2h, NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_N2H);
+ if (status != NSS_TX_SUCCESS) {
+ nss_warning("%p: Dynamic interface destroy failed status %d\n", handle->nss_ctx, status);
+ return status;
+ }
+
+ status = nss_dynamic_interface_dealloc_node(if_num_h2n, NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_H2N);
if (status != NSS_TX_SUCCESS) {
nss_warning("%p: Dynamic interface destroy failed status %d\n", handle->nss_ctx, status);
return status;
}
spin_lock_bh(&nss_virt_if_lock);
- nss_virt_if_handle_t[index] = NULL;
+ nss_virt_if_handle_t[index_n2h] = NULL;
+ nss_virt_if_handle_t[index_h2n] = NULL;
spin_unlock_bh(&nss_virt_if_lock);
kfree(handle->pvt);
@@ -304,131 +251,22 @@
}
/*
- * nss_virt_if_handle_create_cb()
- * Callback to handle the response from dynamic interface for an alloc node msg.
- */
-static void nss_virt_if_handle_create_cb(void *app_data, struct nss_dynamic_interface_msg *ndim)
-{
- struct nss_virt_if_handle *handle = (struct nss_virt_if_handle *)app_data;
- struct nss_ctx_instance *nss_ctx = handle->nss_ctx;
- nss_virt_if_msg_callback_t cb;
- struct nss_virt_if_msg nvim;
- struct nss_virt_if_create_msg *nvcm;
- void *data;
- int32_t if_num;
- uint32_t index;
- int ret;
-
- cb = handle->cb;
- data = handle->app_data;
-
- if (ndim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_warning("%p: received NACK from NSS %d\n", handle->nss_ctx, ndim->cm.response);
- kfree(handle);
- goto fail;
- }
-
- if_num = ndim->msg.alloc_node.if_num;
-
- spin_lock_bh(&nss_virt_if_lock);
- handle->if_num = if_num;
- index = NSS_VIRT_IF_GET_INDEX(if_num);
- nss_virt_if_handle_t[index] = handle;
- spin_unlock_bh(&nss_virt_if_lock);
-
- /* Register the msg handler for if_num */
- ret = nss_virt_if_register_handler(nss_ctx, handle);
- if (ret != NSS_VIRT_IF_SUCCESS) {
- nss_warning("%p: Registration handler failed reason: %d\n", handle->nss_ctx, ret);
- nss_virt_if_handle_destroy(handle);
- goto fail;
- }
-
- /*
- * Send virt_if message to the Firmware to copy the netdev's macaddr
- */
- nss_virt_if_msg_init(&nvim, handle->if_num, NSS_VIRT_IF_TX_CREATE_MSG,
- sizeof(struct nss_virt_if_create_msg), NULL, NULL);
-
- nvcm = &nvim.msg.if_create;
- nvcm->flags = 0;
- memcpy(nvcm->mac_addr, handle->ndev->dev_addr, ETH_ALEN);
-
- ret = nss_virt_if_tx_msg(handle->nss_ctx, &nvim);
- if (ret != NSS_TX_SUCCESS) {
- nss_warning("%p: nss_virt_if_tx_msg failed %u\n", handle->nss_ctx, ret);
- nss_virt_if_handle_destroy(handle);
- goto fail;
- }
-
- nss_core_register_subsys_dp(nss_ctx, handle->if_num, NULL, NULL, NULL, handle->ndev, 0);
-
- /*
- * Hold a reference to the net_device
- */
- dev_hold(handle->ndev);
-
- /*
- * The context returned is the handle which contains all the info related to
- * the interface if_num.
- */
-
-fail:
- if (!cb) {
- nss_warning("cb is NULL\n");
- return;
- }
-
- cb(data, &ndim->cm);
-}
-
-/*
- * nss_virt_if_handle_create()
- * Create and initialize virt_if handle.
- */
-static struct nss_virt_if_handle *nss_virt_if_handle_create(struct nss_ctx_instance *nss_ctx,
- struct net_device *ndev,
- nss_virt_if_msg_callback_t cb,
- void *app_data,
- int *cmd_rsp)
-{
- struct nss_virt_if_handle *handle;
-
- handle = (struct nss_virt_if_handle *)kzalloc(sizeof(struct nss_virt_if_handle),
- GFP_ATOMIC);
- if (!handle) {
- nss_warning("%p: handle memory alloc failed\n", nss_ctx);
- *cmd_rsp = NSS_VIRT_IF_ALLOC_FAILURE;
- goto error;
- }
-
- /*
- * Save the callback & appdata of the user. The callback will be invoked from
- * nss_virt_if_handle_create_cb.
- */
- handle->nss_ctx = nss_ctx;
- handle->ndev = ndev;
- handle->cb = cb;
- handle->app_data = app_data;
-
- *cmd_rsp = NSS_VIRT_IF_SUCCESS;
-
- return handle;
-
-error:
- return NULL;
-}
-
-/*
* nss_virt_if_handle_create_sync()
* Initialize virt handle which holds the if_num and stats per interface.
*/
-static struct nss_virt_if_handle *nss_virt_if_handle_create_sync(struct nss_ctx_instance *nss_ctx, int32_t if_num, int32_t *cmd_rsp)
+static struct nss_virt_if_handle *nss_virt_if_handle_create_sync(struct nss_ctx_instance *nss_ctx, int32_t if_num_n2h, int32_t if_num_h2n, int32_t *cmd_rsp)
{
- int32_t index;
+ int32_t index_n2h;
+ int32_t index_h2n;
struct nss_virt_if_handle *handle;
- index = NSS_VIRT_IF_GET_INDEX(if_num);
+ if (!nss_virt_if_verify_if_num(if_num_n2h) || !nss_virt_if_verify_if_num(if_num_h2n)) {
+ nss_warning("%p: bad interface numbers %d %d\n", nss_ctx, if_num_n2h, if_num_h2n);
+ return NULL;
+ }
+
+ index_n2h = NSS_VIRT_IF_GET_INDEX(if_num_n2h);
+ index_h2n = NSS_VIRT_IF_GET_INDEX(if_num_h2n);
handle = (struct nss_virt_if_handle *)kzalloc(sizeof(struct nss_virt_if_handle),
GFP_KERNEL);
@@ -439,7 +277,8 @@
}
handle->nss_ctx = nss_ctx;
- handle->if_num = if_num;
+ handle->if_num_n2h = if_num_n2h;
+ handle->if_num_h2n = if_num_h2n;
handle->pvt = (struct nss_virt_if_pvt *)kzalloc(sizeof(struct nss_virt_if_pvt),
GFP_KERNEL);
if (!handle->pvt) {
@@ -452,7 +291,8 @@
handle->app_data = NULL;
spin_lock_bh(&nss_virt_if_lock);
- nss_virt_if_handle_t[index] = handle;
+ nss_virt_if_handle_t[index_n2h] = handle;
+ nss_virt_if_handle_t[index_h2n] = handle;
spin_unlock_bh(&nss_virt_if_lock);
*cmd_rsp = NSS_VIRT_IF_SUCCESS;
@@ -473,11 +313,19 @@
{
uint32_t ret;
struct nss_virt_if_pvt *nvip = NULL;
- int32_t if_num = handle->if_num;
+ int32_t if_num_n2h = handle->if_num_n2h;
+ int32_t if_num_h2n = handle->if_num_h2n;
- ret = nss_core_register_handler(nss_ctx, if_num, nss_virt_if_msg_handler, NULL);
+ ret = nss_core_register_handler(nss_ctx, if_num_n2h, nss_virt_if_msg_handler, NULL);
if (ret != NSS_CORE_STATUS_SUCCESS) {
- nss_warning("%d: Message handler failed to be registered for interface\n", if_num);
+ nss_warning("%p: Failed to register message handler for redir_n2h interface %d\n", nss_ctx, if_num_n2h);
+ return NSS_VIRT_IF_CORE_FAILURE;
+ }
+
+ ret = nss_core_register_handler(nss_ctx, if_num_h2n, nss_virt_if_msg_handler, NULL);
+ if (ret != NSS_CORE_STATUS_SUCCESS) {
+ nss_core_unregister_handler(nss_ctx, if_num_n2h);
+ nss_warning("%p: Failed to register message handler for redir_h2n interface %d\n", nss_ctx, if_num_h2n);
return NSS_VIRT_IF_CORE_FAILURE;
}
@@ -493,104 +341,83 @@
}
/*
- * nss_virt_if_create()
- * Create a virtual interface and associate it with the netdev, asynchronously.
- */
-int nss_virt_if_create(struct net_device *netdev, nss_virt_if_msg_callback_t cb, void *app_data)
-{
- struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[nss_top_main.wlan_handler_id];
- struct nss_dynamic_interface_msg ndim;
- struct nss_dynamic_interface_alloc_node_msg *ndia;
- int ret;
- struct nss_virt_if_handle *handle = NULL;
-
- if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
- nss_warning("%p: Interface could not be created as core not ready\n", nss_ctx);
- return NSS_VIRT_IF_CORE_FAILURE;
- }
-
- /*
- * Create the virt_if handle and associate the cb and app_data with it.
- */
- handle = nss_virt_if_handle_create(nss_ctx, netdev, cb, app_data, &ret);
- if (!handle) {
- nss_warning("%p:virt_if handle create failed ret %d\n", nss_ctx, ret);
- return ret;
- }
-
- ndia = &ndim.msg.alloc_node;
- ndia->type = NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR;
-
- /*
- * Construct a dynamic interface message and send it to the firmware.
- */
- nss_dynamic_interface_msg_init(&ndim, NSS_DYNAMIC_INTERFACE, NSS_DYNAMIC_INTERFACE_ALLOC_NODE,
- sizeof(struct nss_dynamic_interface_alloc_node_msg), nss_virt_if_handle_create_cb, (void *)handle);
-
- ret = nss_dynamic_interface_tx(nss_ctx, &ndim);
- if (ret != NSS_TX_SUCCESS) {
- nss_warning("%p: failure allocating virt if\n", nss_ctx);
- ret = NSS_VIRT_IF_DYNAMIC_IF_FAILURE;
- kfree(handle);
- return ret;
- }
-
- return ret;
-}
-EXPORT_SYMBOL(nss_virt_if_create);
-
-/*
* nss_virt_if_create_sync()
- * Create a virt interface, synchronously and associate it with the netdev
+ * Create redir_n2h and redir_h2n interfaces, synchronously and associate it with same netdev
*/
struct nss_virt_if_handle *nss_virt_if_create_sync(struct net_device *netdev)
{
- struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[nss_top_main.wlan_handler_id];
+ struct nss_ctx_instance *nss_ctx = nss_virt_if_get_context();
struct nss_virt_if_msg nvim;
- struct nss_virt_if_create_msg *nvcm;
+ struct nss_virt_if_config_msg *nvcm;
uint32_t ret;
struct nss_virt_if_handle *handle = NULL;
- int32_t if_num;
+ int32_t if_num_n2h, if_num_h2n;
if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
nss_warning("%p: Interface could not be created as core not ready\n", nss_ctx);
return NULL;
}
- if_num = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR);
- if (if_num < 0) {
- nss_warning("%p: failure allocating virt if\n", nss_ctx);
+ if_num_n2h = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_N2H);
+ if (if_num_n2h < 0) {
+ nss_warning("%p: failure allocating redir_n2h\n", nss_ctx);
return NULL;
}
- handle = nss_virt_if_handle_create_sync(nss_ctx, if_num, &ret);
+ if_num_h2n = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_H2N);
+ if (if_num_h2n < 0) {
+ nss_warning("%p: failure allocating redir_h2n\n", nss_ctx);
+ nss_dynamic_interface_dealloc_node(if_num_n2h, NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_N2H);
+ return NULL;
+ }
+
+ handle = nss_virt_if_handle_create_sync(nss_ctx, if_num_n2h, if_num_h2n, &ret);
if (!handle) {
- nss_warning("%p:virt_if handle creation failed ret %d\n", nss_ctx, ret);
- nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR);
+ nss_warning("%p: virt_if handle creation failed ret %d\n", nss_ctx, ret);
+ nss_dynamic_interface_dealloc_node(if_num_n2h, NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_N2H);
+ nss_dynamic_interface_dealloc_node(if_num_h2n, NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_H2N);
return NULL;
}
- /* Initializes the semaphore and also sets the msg handler for if_num */
+ /*
+ * Initializes the semaphore and also sets the msg handler for if_num.
+ */
ret = nss_virt_if_register_handler_sync(nss_ctx, handle);
if (ret != NSS_VIRT_IF_SUCCESS) {
nss_warning("%p: Registration handler failed reason: %d\n", nss_ctx, ret);
- goto error;
+ goto error1;
}
- nss_virt_if_msg_init(&nvim, handle->if_num, NSS_VIRT_IF_TX_CREATE_MSG,
- sizeof(struct nss_virt_if_create_msg), nss_virt_if_callback, handle);
+ nss_virt_if_msg_init(&nvim, handle->if_num_n2h, NSS_VIRT_IF_TX_CONFIG_MSG,
+ sizeof(struct nss_virt_if_config_msg), nss_virt_if_callback, handle);
- nvcm = &nvim.msg.if_create;
+ nvcm = &nvim.msg.if_config;
nvcm->flags = 0;
+ nvcm->sibling = if_num_h2n;
+ nvcm->nexthop = NSS_N2H_INTERFACE;
memcpy(nvcm->mac_addr, netdev->dev_addr, ETH_ALEN);
ret = nss_virt_if_tx_msg_sync(handle, &nvim);
if (ret != NSS_TX_SUCCESS) {
nss_warning("%p: nss_virt_if_tx_msg_sync failed %u\n", nss_ctx, ret);
- goto error;
+ goto error2;
}
- nss_core_register_subsys_dp(nss_ctx, handle->if_num, NULL, NULL, NULL, netdev, 0);
+ nvim.cm.interface = if_num_h2n;
+ nvcm->sibling = if_num_n2h;
+ nvcm->nexthop = NSS_ETH_RX_INTERFACE;
+
+ ret = nss_virt_if_tx_msg_sync(handle, &nvim);
+ if (ret != NSS_TX_SUCCESS) {
+ nss_warning("%p: nss_virt_if_tx_msg_sync failed %u\n", nss_ctx, ret);
+ goto error2;
+ }
+
+ nss_core_register_subsys_dp(nss_ctx, handle->if_num_n2h, NULL, NULL, NULL, netdev, 0);
+ nss_core_register_subsys_dp(nss_ctx, handle->if_num_h2n, NULL, NULL, NULL, netdev, 0);
+
+ nss_core_set_subsys_dp_type(nss_ctx, netdev, if_num_n2h, NSS_VIRT_IF_DP_REDIR_N2H);
+ nss_core_set_subsys_dp_type(nss_ctx, netdev, if_num_h2n, NSS_VIRT_IF_DP_REDIR_H2N);
/*
* Hold a reference to the net_device
@@ -604,69 +431,17 @@
return handle;
-error:
+error2:
+ nss_core_unregister_handler(nss_ctx, if_num_n2h);
+ nss_core_unregister_handler(nss_ctx, if_num_h2n);
+
+error1:
nss_virt_if_handle_destroy_sync(handle);
return NULL;
}
EXPORT_SYMBOL(nss_virt_if_create_sync);
/*
- * nss_virt_if_destroy()
- * Destroy the virt interface associated with the interface number, by sending
- * sending an asynchronous message to dynamic interface.
- */
-nss_tx_status_t nss_virt_if_destroy(struct nss_virt_if_handle *handle, nss_virt_if_msg_callback_t cb, void *app_data)
-{
- nss_tx_status_t status;
- struct net_device *dev;
- int32_t if_num;
- struct nss_ctx_instance *nss_ctx;
- uint32_t ret;
-
- if (!handle) {
- nss_warning("handle is NULL\n");
- return NSS_TX_FAILURE_BAD_PARAM;
- }
-
- if_num = handle->if_num;
- nss_ctx = handle->nss_ctx;
- handle->cb = cb;
- handle->app_data = app_data;
-
- if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
- nss_warning("%p: Interface could not be destroyed as core not ready\n", nss_ctx);
- return NSS_TX_FAILURE_NOT_READY;
- }
-
- spin_lock_bh(&nss_top_main.lock);
- if (!nss_ctx->subsys_dp_register[if_num].ndev) {
- spin_unlock_bh(&nss_top_main.lock);
- nss_warning("%p: Unregister virt interface %d: no context\n", nss_ctx, if_num);
- return NSS_TX_FAILURE_BAD_PARAM;
- }
-
- dev = nss_ctx->subsys_dp_register[if_num].ndev;
- nss_core_unregister_subsys_dp(nss_ctx, if_num);
- spin_unlock_bh(&nss_top_main.lock);
- dev_put(dev);
-
- status = nss_virt_if_handle_destroy(handle);
- if (status != NSS_TX_SUCCESS) {
- nss_warning("%p: handle destroy tx failed %d\n", nss_ctx, status);
- return NSS_TX_FAILURE;
- }
-
- ret = nss_core_unregister_handler(nss_ctx, if_num);
- if (ret != NSS_CORE_STATUS_SUCCESS) {
- nss_warning("Not able to unregister handler for virt_if interface %d with NSS core\n", if_num);
- return NSS_TX_FAILURE_BAD_PARAM;
- }
-
- return status;
-}
-EXPORT_SYMBOL(nss_virt_if_destroy);
-
-/*
* nss_virt_if_destroy_sync()
* Destroy the virt interface associated with the interface number, synchronously.
*/
@@ -674,7 +449,8 @@
{
nss_tx_status_t status;
struct net_device *dev;
- int32_t if_num;
+ int32_t if_num_n2h;
+ int32_t if_num_h2n;
struct nss_ctx_instance *nss_ctx;
uint32_t ret;
@@ -683,7 +459,8 @@
return NSS_TX_FAILURE_BAD_PARAM;
}
- if_num = handle->if_num;
+ if_num_n2h = handle->if_num_n2h;
+ if_num_h2n = handle->if_num_h2n;
nss_ctx = handle->nss_ctx;
if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
@@ -692,26 +469,34 @@
}
spin_lock_bh(&nss_top_main.lock);
- if (!nss_ctx->subsys_dp_register[if_num].ndev) {
+ if (!nss_ctx->subsys_dp_register[if_num_n2h].ndev || !nss_ctx->subsys_dp_register[if_num_h2n].ndev) {
spin_unlock_bh(&nss_top_main.lock);
- nss_warning("%p: Unregister virt interface %d: no context\n", nss_ctx, if_num);
+ nss_warning("%p: Unregister virt interface %d %d: no context\n", nss_ctx, if_num_n2h, if_num_h2n);
return NSS_TX_FAILURE_BAD_PARAM;
}
- dev = nss_ctx->subsys_dp_register[if_num].ndev;
- nss_core_unregister_subsys_dp(nss_ctx, if_num);
+ dev = nss_ctx->subsys_dp_register[if_num_n2h].ndev;
+ nss_assert(dev == nss_ctx->subsys_dp_register[if_num_h2n].ndev);
+ nss_core_unregister_subsys_dp(nss_ctx, if_num_n2h);
+ nss_core_unregister_subsys_dp(nss_ctx, if_num_h2n);
spin_unlock_bh(&nss_top_main.lock);
dev_put(dev);
status = nss_virt_if_handle_destroy_sync(handle);
if (status != NSS_TX_SUCCESS) {
- nss_warning("%p: handle destroy failed for if_num %d\n", nss_ctx, if_num);
+ nss_warning("%p: handle destroy failed for if_num_n2h %d and if_num_h2n %d\n", nss_ctx, if_num_n2h, if_num_h2n);
return NSS_TX_FAILURE;
}
- ret = nss_core_unregister_handler(nss_ctx, if_num);
+ ret = nss_core_unregister_handler(nss_ctx, if_num_n2h);
if (ret != NSS_CORE_STATUS_SUCCESS) {
- nss_warning("%p: Not able to unregister handler for virt_if interface %d with NSS core\n", nss_ctx, if_num);
+ nss_warning("%p: Not able to unregister handler for redir_n2h interface %d with NSS core\n", nss_ctx, if_num_n2h);
+ return NSS_TX_FAILURE_BAD_PARAM;
+ }
+
+ ret = nss_core_unregister_handler(nss_ctx, if_num_h2n);
+ if (ret != NSS_CORE_STATUS_SUCCESS) {
+ nss_warning("%p: Not able to unregister handler for redir_h2n interface %d with NSS core\n", nss_ctx, if_num_h2n);
return NSS_TX_FAILURE_BAD_PARAM;
}
@@ -727,7 +512,7 @@
struct sk_buff *skb)
{
int32_t status;
- int32_t if_num = handle->if_num;
+ int32_t if_num = handle->if_num_h2n;
struct nss_ctx_instance *nss_ctx = handle->nss_ctx;
if (unlikely(nss_ctl_redirect == 0)) {
@@ -738,7 +523,11 @@
return NSS_TX_FAILURE_NOT_SUPPORTED;
}
- nss_assert(NSS_IS_IF_TYPE(DYNAMIC, if_num));
+ if (!nss_virt_if_verify_if_num(if_num)) {
+ nss_warning("%p: bad interface number %d\n", nss_ctx, if_num);
+ return NSS_TX_FAILURE_BAD_PARAM;
+ }
+
nss_trace("%p: Virtual Rx packet, if_num:%d, skb:%p", nss_ctx, if_num, skb);
/*
@@ -804,7 +593,7 @@
/*
* Sanity check the message
*/
- if (!NSS_IS_IF_TYPE(DYNAMIC, ncm->interface)) {
+ if (!nss_virt_if_verify_if_num(ncm->interface)) {
nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
return NSS_TX_FAILURE;
}
@@ -863,7 +652,13 @@
}
nss_ctx = handle->nss_ctx;
- if_num = handle->if_num;
+
+ if (!nss_virt_if_verify_if_num(handle->if_num_h2n)) {
+ nss_warning("if_num is invalid\n");
+ return;
+ }
+
+ if_num = handle->if_num_h2n;
nss_core_register_subsys_dp(nss_ctx, if_num, data_callback, NULL, NULL, netdev, (uint32_t)netdev->features);
nss_top_main.if_rx_msg_callback[if_num] = NULL;
@@ -884,7 +679,13 @@
}
nss_ctx = handle->nss_ctx;
- if_num = handle->if_num;
+
+ if (!nss_virt_if_verify_if_num(handle->if_num_h2n)) {
+ nss_warning("if_num is invalid\n");
+ return;
+ }
+
+ if_num = handle->if_num_h2n;
nss_core_unregister_subsys_dp(nss_ctx, if_num);
@@ -894,7 +695,7 @@
/*
* nss_virt_if_get_interface_num()
- * Get interface number for a virtual interface
+ * Get interface number for a virtual interface
*/
int32_t nss_virt_if_get_interface_num(struct nss_virt_if_handle *handle)
{
@@ -903,6 +704,9 @@
return -1;
}
- return handle->if_num;
+ /*
+ * Return if_num_n2h whose datapath type is 0.
+ */
+ return handle->if_num_n2h;
}
EXPORT_SYMBOL(nss_virt_if_get_interface_num);
diff --git a/nss_virt_if_stats.c b/nss_virt_if_stats.c
index 28ed8fb..7b2f7ba 100644
--- a/nss_virt_if_stats.c
+++ b/nss_virt_if_stats.c
@@ -39,7 +39,7 @@
uint32_t len = 80;
struct nss_virt_if_handle *handle = NULL;
- if (if_num < 0) {
+ if (!nss_virt_if_verify_if_num(if_num)) {
nss_warning("invalid if_num\n");
return 0;
}
@@ -123,7 +123,10 @@
}
for (; if_num < max_if_num; if_num++) {
- if (nss_dynamic_interface_get_type(nss_ctx, if_num) != NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR)
+ /*
+ * redir_h2n will collect stats from redir_n2h and redir_h2n in nss.
+ */
+ if (nss_dynamic_interface_get_type(nss_ctx, if_num) != NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR_H2N)
continue;
bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num);