Merge "[qca-nss-drv] Fix tailroom for ipsec data"
diff --git a/Makefile b/Makefile
index 5de395e..8a43073 100644
--- a/Makefile
+++ b/Makefile
@@ -42,6 +42,7 @@
nss_sjack.o \
nss_stats.o \
nss_tun6rd.o \
+ nss_pptp.o \
nss_l2tpv2.o \
nss_tunipip6.o \
nss_virt_if.o \
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 186d296..95b3d05 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -40,6 +40,7 @@
#include "nss_cmn.h"
#include "nss_tun6rd.h"
#include "nss_l2tpv2.h"
+#include "nss_pptp.h"
#include "nss_tunipip6.h"
#include "nss_lag.h"
#include "nss_ipv4.h"
@@ -136,6 +137,7 @@
#define NSS_LAG3_INTERFACE_NUM (NSS_SPECIAL_IF_START + 33) /* Special IF number for LAG3 */
#define NSS_L2TPV2_INTERFACE (NSS_SPECIAL_IF_START + 34) /* Special L2TPv2 UDP encap interface */
#define NSS_TSTAMP_INTERFACE (NSS_SPECIAL_IF_START + 35) /* Special IF number for Tstamp interface */
+#define NSS_PPTP_INTERFACE (NSS_SPECIAL_IF_START + 36) /* Special PPTP-Decap interface */
/**
* This macro converts format for IPv6 address (from Linux to NSS)
diff --git a/exports/nss_dynamic_interface.h b/exports/nss_dynamic_interface.h
index 1724976..b93ed2a 100644
--- a/exports/nss_dynamic_interface.h
+++ b/exports/nss_dynamic_interface.h
@@ -39,6 +39,7 @@
NSS_DYNAMIC_INTERFACE_TYPE_RADIO_2, /* WIFI radio type2 */
NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED,
NSS_DYNAMIC_INTERFACE_TYPE_L2TPV2, /* L2TPV2 Interface Type */
+ NSS_DYNAMIC_INTERFACE_TYPE_PPTP, /* PPTP VPN Interface Type */
NSS_DYNAMIC_INTERFACE_TYPE_MAX
};
diff --git a/exports/nss_pptp.h b/exports/nss_pptp.h
new file mode 100644
index 0000000..ab27550
--- /dev/null
+++ b/exports/nss_pptp.h
@@ -0,0 +1,167 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_pptp.h
+ * NSS TO HLOS interface definitions.
+ */
+#ifndef _NSS_PPTP_H_
+#define _NSS_PPTP_H_
+
+/*
+ * Maximum no of pptp sessions supported
+ */
+#define NSS_MAX_PPTP_DYNAMIC_INTERFACES 4
+
+/**
+ * request/response types
+ */
+enum nss_pptp_metadata_types {
+ NSS_PPTP_MSG_SESSION_CONFIGURE, /**< session create message */
+ NSS_PPTP_MSG_SESSION_DECONFIGURE, /**< session delete message */
+ NSS_PPTP_MSG_SYNC_STATS, /**< session stats sync message */
+ NSS_PPTP_MSG_MAX
+};
+
+/**
+ * PPTP session configuration message structure
+ */
+struct nss_pptp_session_configure_msg {
+ uint16_t src_call_id; /**< local call id */
+ uint16_t dst_call_id; /**< peer call id */
+ uint32_t sip; /**< local tunnel end point */
+ uint32_t dip; /**< remote tunnel end point */
+};
+
+/**
+ * PPTP session deconfiguration message structure
+ */
+struct nss_pptp_session_deconfigure_msg {
+ uint16_t src_call_id; /**< local call id */
+};
+
+/**
+ * pptp statistics sync message structure.
+ */
+struct nss_pptp_sync_session_stats_msg {
+ struct nss_cmn_node_stats node_stats; /**< common node stats */
+ uint32_t rx_dropped; /**< rx dropped */
+ uint32_t tx_dropped; /**< tx dropped */
+ uint32_t rx_ppp_lcp_pkts; /**< PPP LCP packets received */
+ uint32_t rx_exception_data_pkts;/**< Data packets exceptioned to host */
+};
+
+/**
+ * Message structure to send/receive pptp messages
+ */
+struct nss_pptp_msg {
+ struct nss_cmn_msg cm; /**< Message Header */
+ union {
+ struct nss_pptp_session_configure_msg session_configure_msg; /**< session configure message */
+ struct nss_pptp_session_deconfigure_msg session_deconfigure_msg; /**< session deconfigure message */
+ struct nss_pptp_sync_session_stats_msg stats; /**< session stats message */
+ } msg;
+};
+
+/**
+ * @brief Callback to receive pptp messages
+ *
+ * @return void
+ */
+typedef void (*nss_pptp_msg_callback_t)(void *app_data, struct nss_pptp_msg *msg);
+
+/**
+ * @brief Send pptp messages
+ *
+ * @param nss_ctx NSS context
+ * @param msg NSS pptp tunnel message
+ *
+ * @return nss_tx_status_t Tx status
+ */
+extern nss_tx_status_t nss_pptp_tx(struct nss_ctx_instance *nss_ctx, struct nss_pptp_msg *msg);
+
+/**
+ * @brief Get the pptp context used in the nss_pptp_tx
+ *
+ * @return struct nss_ctx_instance *NSS context
+ */
+extern struct nss_ctx_instance *nss_pptp_get_context(void);
+
+/**
+ * @brief Callback when pptp tunnel data is received
+ *
+ * @param netdevice of pptp session
+ * @param skb Pointer to data buffer
+ * @param napi pointer
+ *
+ * @return void
+ */
+typedef void (*nss_pptp_callback_t)(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi);
+
+/**
+ * @brief Register to send/receive pptp tunnel messages to NSS
+ *
+ * @param if_num NSS interface number
+ * @param pptp_callback Callback for pptp tunnel data
+ * @param msg_callback Callback for pptp tunnel messages
+ * @param netdev netdevice associated with the pptp tunnel
+ * @param features denotes the skb types supported by this interface
+ *
+ * @return nss_ctx_instance* NSS context
+ */
+extern struct nss_ctx_instance *nss_register_pptp_if(uint32_t if_num, nss_pptp_callback_t pptp_callback,
+ nss_pptp_msg_callback_t msg_callback, struct net_device *netdev, uint32_t features);
+
+/**
+ * @brief Unregister pptp tunnel interface with NSS
+ *
+ * @param if_num NSS interface number
+ *
+ * @return void
+ */
+extern void nss_unregister_pptp_if(uint32_t if_num);
+
+/**
+ * @brief Initialize pptp msg
+ *
+ * @param nss_pptp_msg PPTP session info i.e Configure/Deconfigure
+ * @param if_num Interface number
+ * @param type Message type
+ * @param len Message length
+ * @param cb message callback
+ * @param app_data
+ *
+ * @return None
+ */
+extern void nss_pptp_msg_init(struct nss_pptp_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data);
+
+/**
+ * @brief register pptp nss debug stats handler
+ *
+ * @return None
+ */
+extern void nss_pptp_register_handler(void);
+
+/**
+ * @brief get pptp nss session debug stats. stats_mem should be large enought to hold all stats.
+ *
+ * @param memory address to be copied to
+ *
+ * @return None
+ */
+extern void nss_pptp_session_debug_stats_get(void *stats_mem);
+
+#endif /* _NSS_PPTP_H_ */
diff --git a/nss_core.h b/nss_core.h
index beac10b..edec550 100755
--- a/nss_core.h
+++ b/nss_core.h
@@ -543,6 +543,24 @@
};
/*
+ * PPTP debug stats
+ */
+enum nss_stats_pptp_session {
+ NSS_STATS_PPTP_SESSION_RX_DROPPED, /* Number of received packets dropped */
+ NSS_STATS_PPTP_SESSION_TX_DROPPED, /* Number of packets dropped in trasmit direction */
+ NSS_STATS_PPTP_SESSION_RX_PPP_LCP_PKTS, /* Number of ppp lcp packets received */
+ NSS_STATS_PPTP_SESSION_RX_EXP_DATA_PKTS, /* Number of RX exceptioned packets */
+ NSS_STATS_PPTP_SESSION_MAX
+};
+
+struct nss_stats_pptp_session_debug {
+ uint64_t stats[NSS_STATS_PPTP_SESSION_MAX];
+ int32_t if_index;
+ uint32_t if_num; /* nss interface number */
+ bool valid;
+};
+
+/*
* NSS core state
*/
enum nss_core_state {
@@ -696,6 +714,7 @@
struct dentry *lso_rx_dentry; /* LSO_RX stats dentry */
struct dentry *drv_dentry; /* HLOS driver stats dentry */
struct dentry *pppoe_dentry; /* PPPOE stats dentry */
+ struct dentry *pptp_dentry; /* PPTP stats dentry */
struct dentry *l2tpv2_dentry; /* L2TPV2 stats dentry */
struct dentry *gmac_dentry; /* GMAC ethnode stats dentry */
struct dentry *capwap_decap_dentry; /* CAPWAP decap ethnode stats dentry */
@@ -726,6 +745,7 @@
uint8_t wlan_handler_id;
uint8_t tun6rd_handler_id;
uint8_t wifi_handler_id;
+ uint8_t pptp_handler_id;
uint8_t l2tpv2_handler_id;
uint8_t tunipip6_handler_id;
uint8_t frequency_handler_id;
@@ -765,6 +785,8 @@
/* l2tP tunnel interface event callback function */
nss_tunipip6_msg_callback_t tunipip6_msg_callback;
/* ipip6 tunnel interface event callback function */
+ nss_pptp_msg_callback_t pptp_msg_callback;
+ /* PPTP tunnel interface event callback function */
struct nss_shaper_bounce_registrant bounce_interface_registrants[NSS_MAX_NET_INTERFACES];
/* Registrants for interface shaper bounce operations */
struct nss_shaper_bounce_registrant bounce_bridge_registrants[NSS_MAX_NET_INTERFACES];
@@ -957,6 +979,7 @@
enum nss_feature_enabled ipsec_enabled; /* Does this core handle IPsec? */
enum nss_feature_enabled wlanredirect_enabled; /* Does this core handle WLAN redirect? */
enum nss_feature_enabled tun6rd_enabled; /* Does this core handle 6rd Tunnel ? */
+ enum nss_feature_enabled pptp_enabled; /* Does this core handle pptp Tunnel ? */
enum nss_feature_enabled l2tpv2_enabled; /* Does this core handle l2tpv2 Tunnel ? */
enum nss_feature_enabled tunipip6_enabled; /* Does this core handle ipip6 Tunnel ? */
enum nss_feature_enabled gre_redir_enabled; /* Does this core handle gre_redir Tunnel ? */
diff --git a/nss_hal/ipq806x/nss_hal_pvt.c b/nss_hal/ipq806x/nss_hal_pvt.c
index dfa7420..8891e1b 100644
--- a/nss_hal/ipq806x/nss_hal_pvt.c
+++ b/nss_hal/ipq806x/nss_hal_pvt.c
@@ -883,7 +883,9 @@
|| of_property_read_u32(np, "qcom,ipsec_enabled", &npd->ipsec_enabled)
|| of_property_read_u32(np, "qcom,wlanredirect_enabled", &npd->wlanredirect_enabled)
|| of_property_read_u32(np, "qcom,tun6rd_enabled", &npd->tun6rd_enabled)
+ || of_property_read_u32(np, "qcom,l2tpv2_enabled", &npd->l2tpv2_enabled)
|| of_property_read_u32(np, "qcom,tunipip6_enabled", &npd->tunipip6_enabled)
+ || of_property_read_u32(np, "qcom,pptp_enabled", &npd->tunipip6_enabled)
|| of_property_read_u32(np, "qcom,shaping_enabled", &npd->shaping_enabled)) {
pr_warn("%s: error reading non-critical device node properties\n", np->name);
}
@@ -1420,6 +1422,11 @@
nss_top->tun6rd_handler_id = nss_dev->id;
}
+ if (npd->pptp_enabled == NSS_FEATURE_ENABLED) {
+ nss_top->pptp_handler_id = nss_dev->id;
+ nss_pptp_register_handler();
+ }
+
if (npd->l2tpv2_enabled == NSS_FEATURE_ENABLED) {
nss_top->l2tpv2_handler_id = nss_dev->id;
nss_l2tpv2_register_handler();
diff --git a/nss_l2tpv2.c b/nss_l2tpv2.c
index a37ee92..5b991e1 100644
--- a/nss_l2tpv2.c
+++ b/nss_l2tpv2.c
@@ -36,7 +36,6 @@
if (nss_l2tpv2_session_debug_stats[i].if_num == if_num) {
nss_l2tpv2_session_debug_stats[i].stats[NSS_STATS_L2TPV2_SESSION_RX_PPP_LCP_PKTS] += stats_msg->debug_stats.rx_ppp_lcp_pkts;
nss_l2tpv2_session_debug_stats[i].stats[NSS_STATS_L2TPV2_SESSION_RX_EXP_DATA_PKTS] += stats_msg->debug_stats.rx_exception_data_pkts;
- nss_l2tpv2_session_debug_stats[i].stats[NSS_STATS_L2TPV2_SESSION_RX_EXP_DATA_PKTS] += stats_msg->debug_stats.rx_exception_data_pkts;
nss_l2tpv2_session_debug_stats[i].stats[NSS_STATS_L2TPV2_SESSION_ENCAP_PBUF_ALLOC_FAIL_PKTS] += stats_msg->debug_stats.encap_pbuf_alloc_fail;
nss_l2tpv2_session_debug_stats[i].stats[NSS_STATS_L2TPV2_SESSION_DECAP_PBUF_ALLOC_FAIL_PKTS] += stats_msg->debug_stats.decap_pbuf_alloc_fail;
break;
diff --git a/nss_pptp.c b/nss_pptp.c
new file mode 100644
index 0000000..3a6fd98
--- /dev/null
+++ b/nss_pptp.c
@@ -0,0 +1,276 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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 <net/sock.h>
+#include "nss_tx_rx_common.h"
+
+/*
+ * Data structures to store pptp nss debug stats
+ */
+static DEFINE_SPINLOCK(nss_pptp_session_debug_stats_lock);
+static struct nss_stats_pptp_session_debug nss_pptp_session_debug_stats[NSS_MAX_PPTP_DYNAMIC_INTERFACES];
+
+/*
+ * nss_pptp_session_debug_stats_sync
+ * Per session debug stats for pptp
+ */
+void nss_pptp_session_debug_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pptp_sync_session_stats_msg *stats_msg, uint16_t if_num)
+{
+ int i;
+ spin_lock_bh(&nss_pptp_session_debug_stats_lock);
+ for (i = 0; i < NSS_MAX_PPTP_DYNAMIC_INTERFACES; i++) {
+ if (nss_pptp_session_debug_stats[i].if_num == if_num) {
+ nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_RX_DROPPED] += stats_msg->rx_dropped;
+ nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_TX_DROPPED] += stats_msg->tx_dropped;
+ nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_RX_PPP_LCP_PKTS] += stats_msg->rx_ppp_lcp_pkts;
+ nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_RX_EXP_DATA_PKTS] += stats_msg->rx_exception_data_pkts;
+ break;
+ }
+ }
+ spin_unlock_bh(&nss_pptp_session_debug_stats_lock);
+}
+
+/*
+ * nss_pptp_global_session_stats_get()
+ * Get session pptp statitics.
+ */
+void nss_pptp_session_debug_stats_get(void *stats_mem)
+{
+ struct nss_stats_pptp_session_debug *stats = (struct nss_stats_pptp_session_debug *)stats_mem;
+ int i;
+
+ if (!stats) {
+ nss_warning("No memory to copy pptp session stats");
+ return;
+ }
+
+ spin_lock_bh(&nss_pptp_session_debug_stats_lock);
+ for (i = 0; i < NSS_MAX_PPTP_DYNAMIC_INTERFACES; i++) {
+ if (nss_pptp_session_debug_stats[i].valid) {
+ memcpy(stats, &nss_pptp_session_debug_stats[i], sizeof(struct nss_stats_pptp_session_debug));
+ stats++;
+ }
+ }
+ spin_unlock_bh(&nss_pptp_session_debug_stats_lock);
+}
+
+/*
+ * nss_pptp_handler()
+ * Handle NSS -> HLOS messages for pptp tunnel
+ */
+static void nss_pptp_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
+{
+ struct nss_pptp_msg *ntm = (struct nss_pptp_msg *)ncm;
+ void *ctx;
+
+ nss_pptp_msg_callback_t cb;
+
+ BUG_ON(!(nss_is_dynamic_interface(ncm->interface) || ncm->interface == NSS_PPTP_INTERFACE));
+
+ /*
+ * Is this a valid request/response packet?
+ */
+ if (ncm->type >= NSS_PPTP_MSG_MAX) {
+ nss_warning("%p: received invalid message %d for PPTP interface", nss_ctx, ncm->type);
+ return;
+ }
+
+ if (ncm->len > sizeof(struct nss_pptp_msg)) {
+ nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
+ return;
+ }
+
+ switch (ntm->cm.type) {
+
+ case NSS_PPTP_MSG_SYNC_STATS:
+ /*
+ * session debug stats embeded in session stats msg
+ */
+ nss_pptp_session_debug_stats_sync(nss_ctx, &ntm->msg.stats, ncm->interface);
+ break;
+ }
+
+ /*
+ * Update the callback and app_data for NOTIFY messages, pptp sends all notify messages
+ * to the same callback/app_data.
+ */
+ if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+ ncm->cb = (uint32_t)nss_ctx->nss_top->pptp_msg_callback;
+ }
+
+ /*
+ * Log failures
+ */
+ nss_core_log_msg_failures(nss_ctx, ncm);
+
+ /*
+ * Do we have a call back
+ */
+ if (!ncm->cb) {
+ return;
+ }
+
+ /*
+ * callback
+ */
+ cb = (nss_pptp_msg_callback_t)ncm->cb;
+ ctx = nss_ctx->nss_top->subsys_dp_register[ncm->interface].ndev;
+
+ /*
+ * call pptp tunnel callback
+ */
+ if (!ctx) {
+ nss_warning("%p: Event received for pptp tunnel interface %d before registration", nss_ctx, ncm->interface);
+ return;
+ }
+
+ cb(ctx, ntm);
+}
+
+/*
+ * nss_pptp_tx()
+ * Transmit a pptp message to NSS firmware
+ */
+nss_tx_status_t nss_pptp_tx(struct nss_ctx_instance *nss_ctx, struct nss_pptp_msg *msg)
+{
+ struct nss_pptp_msg *nm;
+ struct nss_cmn_msg *ncm = &msg->cm;
+ struct sk_buff *nbuf;
+ int32_t status;
+
+ NSS_VERIFY_CTX_MAGIC(nss_ctx);
+ if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+ nss_warning("%p: pptp msg dropped as core not ready", nss_ctx);
+ return NSS_TX_FAILURE_NOT_READY;
+ }
+
+ /*
+ * Sanity check the message
+ */
+ if (!nss_is_dynamic_interface(ncm->interface)) {
+ nss_warning("%p: tx request for non dynamic interface: %d", nss_ctx, ncm->interface);
+ return NSS_TX_FAILURE;
+ }
+
+ if (ncm->type > NSS_PPTP_MSG_MAX) {
+ nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+ return NSS_TX_FAILURE;
+ }
+
+ if (ncm->len > sizeof(struct nss_pptp_msg)) {
+ nss_warning("%p: message length is invalid: %d", nss_ctx, ncm->len);
+ 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: msg dropped as command allocation failed", nss_ctx);
+ return NSS_TX_FAILURE;
+ }
+
+ /*
+ * Copy the message to our skb
+ */
+ nm = (struct nss_pptp_msg *)skb_put(nbuf, sizeof(struct nss_pptp_msg));
+ memcpy(nm, msg, sizeof(struct nss_pptp_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 'pptp message'\n", nss_ctx);
+ if (status == NSS_CORE_STATUS_FAILURE_QUEUE) {
+ return NSS_TX_FAILURE_QUEUE;
+ }
+ return NSS_TX_FAILURE;
+ }
+
+ nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
+ NSS_REGS_H2N_INTR_STATUS_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_register_pptp_if()
+ */
+struct nss_ctx_instance *nss_register_pptp_if(uint32_t if_num, nss_pptp_callback_t pptp_callback,
+ nss_pptp_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
+{
+
+ nss_assert(nss_is_dynamic_interface(if_num));
+
+ nss_top_main.subsys_dp_register[if_num].ndev = netdev;
+ nss_top_main.subsys_dp_register[if_num].cb = pptp_callback;
+ nss_top_main.subsys_dp_register[if_num].app_data = NULL;
+ nss_top_main.subsys_dp_register[if_num].features = features;
+
+ nss_top_main.pptp_msg_callback = event_callback;
+
+ nss_core_register_handler(if_num, nss_pptp_handler, NULL);
+
+ return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.pptp_handler_id];
+}
+
+/*
+ * nss_unregister_pptp_if()
+ */
+void nss_unregister_pptp_if(uint32_t if_num)
+{
+ nss_assert(nss_is_dynamic_interface(if_num));
+
+ nss_top_main.subsys_dp_register[if_num].ndev = NULL;
+ nss_top_main.subsys_dp_register[if_num].cb = NULL;
+ nss_top_main.subsys_dp_register[if_num].app_data = NULL;
+ nss_top_main.subsys_dp_register[if_num].features = 0;
+
+ nss_top_main.pptp_msg_callback = NULL;
+
+ nss_core_unregister_handler(if_num);
+}
+
+/*
+ * nss_get_pptp_context()
+ */
+struct nss_ctx_instance *nss_pptp_get_context()
+{
+ return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.pptp_handler_id];
+}
+
+/*
+ * nss_pptp_msg_init()
+ * Initialize nss_pptp msg.
+ */
+void nss_pptp_msg_init(struct nss_pptp_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data)
+{
+ nss_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data);
+}
+
+/* nss_pptp_register_handler()
+ * debugfs stats msg handler received on static pptp interface
+ */
+void nss_pptp_register_handler(void)
+{
+ nss_info("nss_pptp_register_handler");
+ nss_core_register_handler(NSS_PPTP_INTERFACE, nss_pptp_handler, NULL);
+}
+
+EXPORT_SYMBOL(nss_pptp_get_context);
+EXPORT_SYMBOL(nss_pptp_tx);
+EXPORT_SYMBOL(nss_unregister_pptp_if);
+EXPORT_SYMBOL(nss_pptp_msg_init);
+EXPORT_SYMBOL(nss_register_pptp_if);
diff --git a/nss_stats.c b/nss_stats.c
index 2558502..591294e 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -422,6 +422,17 @@
};
/*
+ * nss_stats_str_ppt_session_stats
+ * PPTP statistics strings for nss session stats
+ */
+static int8_t *nss_stats_str_pptp_session_debug_stats[NSS_STATS_PPTP_SESSION_MAX] = {
+ "RX_DROPPED",
+ "TX_DROPPED",
+ "ENCAP_PBUF_ALLOC_FAIL",
+ "DECAP_PBUF_ALLOC_FAIL"
+};
+
+/*
* nss_stats_ipv4_read()
* Read IPV4 stats
*/
@@ -1316,6 +1327,72 @@
}
/*
+ * nss_stats_pptp_read()
+ * Read pptp statistics
+ */
+static ssize_t nss_stats_pptp_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+
+ uint32_t max_output_lines = 2 /* header & footer for session stats */
+ + NSS_MAX_PPTP_DYNAMIC_INTERFACES * (NSS_STATS_PPTP_SESSION_MAX + 2) /*session stats */
+ + 2;
+ size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines ;
+ size_t size_wr = 0;
+ ssize_t bytes_read = 0;
+ struct net_device *dev;
+ struct nss_stats_pptp_session_debug pptp_session_stats[NSS_MAX_PPTP_DYNAMIC_INTERFACES];
+ int id, i;
+
+ char *lbuf = kzalloc(size_al, GFP_KERNEL);
+ if (unlikely(lbuf == NULL)) {
+ nss_warning("Could not allocate memory for local statistics buffer");
+ return 0;
+ }
+
+ memset(&pptp_session_stats, 0, sizeof(struct nss_stats_pptp_session_debug) * NSS_MAX_PPTP_DYNAMIC_INTERFACES);
+
+ /*
+ * Get all stats
+ */
+ nss_pptp_session_debug_stats_get((void *)&pptp_session_stats);
+
+ /*
+ * Session stats
+ */
+ size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npptp session stats start:\n\n");
+ for (id = 0; id < NSS_MAX_PPTP_DYNAMIC_INTERFACES; id++) {
+
+ if (!pptp_session_stats[id].valid) {
+ break;
+ }
+
+ dev = dev_get_by_index(&init_net, pptp_session_stats[id].if_index);
+ if (likely(dev)) {
+
+ size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. nss interface id=%d, netdevice=%s\n", id,
+ pptp_session_stats[id].if_num, dev->name);
+ dev_put(dev);
+ } else {
+ size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. nss interface id=%d\n", id,
+ pptp_session_stats[id].if_num);
+ }
+
+ for (i = 0; i < NSS_STATS_PPTP_SESSION_MAX; i++) {
+ size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+ "\t%s = %llu\n", nss_stats_str_pptp_session_debug_stats[i],
+ pptp_session_stats[id].stats[i]);
+ }
+ size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+ }
+
+ size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npptp session stats end\n");
+ bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+ kfree(lbuf);
+ return bytes_read;
+}
+
+/*
* nss_stats_sjack_read()
* Read SJACK stats
*/
@@ -2031,6 +2108,11 @@
NSS_STATS_DECLARE_FILE_OPERATIONS(l2tpv2)
/*
+ * pptp_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(pptp)
+
+/*
* gmac_stats_ops
*/
NSS_STATS_DECLARE_FILE_OPERATIONS(gmac)
@@ -2282,6 +2364,17 @@
nss_warning("Failed to create qca-nss-drv/stats/l2tpv2 file in debugfs");
return;
}
+
+ /*
+ * PPTP Stats
+ */
+ nss_top_main.pptp_dentry = debugfs_create_file("pptp", 0400,
+ nss_top_main.stats_dentry, &nss_top_main, &nss_stats_pptp_ops);
+ if (unlikely(nss_top_main.pptp_dentry == NULL)) {
+ nss_warning("Failed to create qca-nss-drv/stats/pptp file in debugfs");
+ return;
+ }
+
nss_log_init();
}