Merge "[qca-nss-drv] Do not reset the sent skb's fraglist"
diff --git a/Makefile b/Makefile
index c9bacb6..08ce191 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
##########################################################################
-# Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+# Copyright (c) 2013-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.
@@ -48,7 +48,6 @@
nss_eth_rx.o \
nss_n2h.o \
nss_data_plane.o \
- nss_freq.o \
nss_log.o
#
@@ -57,31 +56,30 @@
qca-nss-drv-objs += \
nss_tx_rx_virt_if.o
-obj-m += qca-nss-tunipip6.o
-obj-m += qca-nss-ipsecmgr.o
+PM_SUPPORT := 0
-ifeq "$(CONFIG_IPV6_SIT_6RD)" "y"
-obj-m += qca-nss-tun6rd.o
-qca-nss-tun6rd-objs := nss_connmgr_tun6rd.o
-ccflags-y += -DNSS_TUN6RD_DEBUG_LEVEL=0
+ccflags-y += -I$(obj)/nss_hal/include -I$(obj)/exports -DNSS_DEBUG_LEVEL=0 -DNSS_EMPTY_BUFFER_SIZE=1792 -DNSS_PKT_STATS_ENABLED=1
+ccflags-y += -DNSS_PM_DEBUG_LEVEL=0
+
+ifneq ($(findstring 3.4, $(KERNELVERSION)),)
+NSS_CCFLAGS = -DNSS_DT_SUPPORT=0 -DNSS_PPP_SUPPORT=1 -DNSS_FW_DBG_SUPPORT=1 -DNSS_PM_SUPPORT=1
+PM_SUPPORT = 1
+else
+NSS_CCFLAGS = -DNSS_DT_SUPPORT=1 -DNSS_PPP_SUPPORT=0 -DNSS_FW_DBG_SUPPORT=0 -DNSS_PM_SUPPORT=0
+ccflags-y += -I$(obj)
endif
-qca-nss-tunipip6-objs := nss_connmgr_tunipip6.o
-qca-nss-ipsecmgr-objs := nss_ipsecmgr.o
+ccflags-y += $(NSS_CCFLAGS)
-ccflags-y += -I$(obj)/nss_hal/include -I$(obj)/exports -DNSS_DEBUG_LEVEL=0 -DNSS_EMPTY_BUFFER_SIZE=1792 -DNSS_PKT_STATS_ENABLED=0
-ccflags-y += -DNSS_TUNIPIP6_DEBUG_LEVEL=0
-ccflags-y += -DNSS_PM_DEBUG_LEVEL=0
-ccflags-y += -DNSS_IPSECMGR_DEBUG_LEVEL=3
+export NSS_CCFLAGS
qca-nss-drv-objs += nss_profiler.o
-obj-y+= profiler/
-obj-y+= nss_qdisc/
-obj-y+= capwapmgr/
+
+ifeq ($(PM_SUPPORT), 1)
+qca-nss-drv-objs += nss_freq.o
+endif
obj ?= .
-ifeq "$(CONFIG_ARCH_IPQ806X)" "y"
qca-nss-drv-objs += nss_hal/ipq806x/nss_hal_pvt.o
ccflags-y += -I$(obj)/nss_hal/ipq806x
-endif
diff --git a/capwapmgr/Makefile b/capwapmgr/Makefile
deleted file mode 100755
index 1850282..0000000
--- a/capwapmgr/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-##########################################################################
-# Copyright (c) 2014, 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.
-##########################################################################
-
-ccflags-y := -I$(obj)/../exports -I$(obj)/.. -I$(obj)/nss_hal/include
-
-#
-# If you want only one netdev for all the CAPWAP tunnels, then
-# set NSS_CAPWAPMGR_ONE_NETDEV.
-# ccflags-y += -DNSS_CAPWAPMGR_ONE_NETDEV
-#
-# If you want one netdevice per-CAPWAP tunnel, then don't set
-# NSS_CAPWAPMGR_ONE_NETDEV.
-#
-obj-m += qca-nss-capwapmgr.o
-qca-nss-capwapmgr-objs := nss_capwapmgr.o
-ccflags-y += -DNSS_CAPWAPMGR_ONE_NETDEV -DNSS_CAPWAPMGR_TESTING_NETLINK -DNSS_CAPWAPMGR_DEBUG_LEVEL=6 -DNSS_DEBUG_LEVEL=0 -DNSS_PKT_STATS_ENABLED=0
diff --git a/capwapmgr/nss_capwapmgr.c b/capwapmgr/nss_capwapmgr.c
deleted file mode 100644
index 67a7523..0000000
--- a/capwapmgr/nss_capwapmgr.c
+++ /dev/null
@@ -1,1310 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_capwapmgr.c
- * NSS to HLOS CAPWAP manager
- */
-#include <linux/types.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <net/ipv6.h>
-#include <net/ipip.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <nss_api_if.h>
-#include <linux/in.h>
-#include <nss_api_if.h>
-#include "nss_core.h"
-#include <nss_cmn.h>
-#include <nss_capwap.h>
-#include <nss_capwapmgr.h>
-
-/*
- * This file is responsible for interacting with qca-nss-drv's
- * CAPWAP API to manage CAPWAP tunnels.
- *
- * This driver also exposes few APIs which can be used by
- * another module to perform operations on CAPWAP tunnels. However, we create
- * one netdevice for all the CAPWAP tunnels which is done at the module's
- * init time if NSS_CAPWAPMGR_ONE_NETDEV is set in the Makefile.
- *
- * If your requirement is to create one netdevice per-CAPWAP tunnel, then
- * netdevice needs to be created before CAPWAP tunnel create. Netdevice are
- * created using nss_capwapmgr_netdev_create() API.
- *
- */
-
-/*
- * NSS capwap mgr debug macros
- */
-#if (NSS_CAPWAPMGR_DEBUG_LEVEL < 1)
-#define nss_capwapmgr_assert(fmt, args...)
-#else
-#define nss_capwapmgr_assert(c) if (!(c)) { BUG_ON(!(c)); }
-#endif /* NSS_CAPWAPMGR_DEBUG_LEVEL */
-
-/*
- * Compile messages for dynamic enable/disable
- */
-#if defined(CONFIG_DYNAMIC_DEBUG)
-#define nss_capwapmgr_warn(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define nss_capwapmgr_info(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define nss_capwapmgr_trace(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else /* CONFIG_DYNAMIC_DEBUG */
-/*
- * Statically compile messages at different levels
- */
-#if (NSS_CAPWAPMGR_DEBUG_LEVEL < 2)
-#define nss_capwapmgr_warn(s, ...)
-#else
-#define nss_capwapmgr_warn(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
-
-#if (NSS_CAPWAPMGR_DEBUG_LEVEL < 3)
-#define nss_capwapmgr_info(s, ...)
-#else
-#define nss_capwapmgr_info(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
-
-#if (NSS_CAPWAPMGR_DEBUG_LEVEL < 4)
-#define nss_capwapmgr_trace(s, ...)
-#else
-#define nss_capwapmgr_trace(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
-#endif /* CONFIG_DYNAMIC_DEBUG */
-
-/*
- * Stats of tunnels which don't exists anymore.
- */
-static struct nss_capwap_tunnel_stats tunneld;
-
-static void nss_capwapmgr_receive_pkt(struct net_device *dev, struct sk_buff *skb, struct napi_struct *napi);
-
-#if defined(NSS_CAPWAPMGR_ONE_NETDEV)
-/*
- * If you want only one netdev for all the tunnels. If you don't want
- * to create one netdev for all the tunnels, then netdev must be
- * created using nss_capwapmgr_netdev_create() before every tunnel create
- * operation.
- */
-static struct net_device *nss_capwapmgr_ndev = NULL;
-#endif
-
-/*
- * nss_capwapmgr_open()
- * Netdev's open call.
- */
-static int nss_capwapmgr_open(struct net_device *dev)
-{
- netif_start_queue(dev);
- return 0;
-}
-
-/*
- * nss_capwapmgr_close()
- * Netdev's close call.
- */
-static int nss_capwapmgr_close(struct net_device *dev)
-{
- netif_stop_queue(dev);
- return 0;
-}
-
-/*
- * nss_capwapmgr_decongestion_callback()
- * Wakeup netif queue if we were stopped by start_xmit
- */
-static void nss_capwapmgr_decongestion_callback(void *arg)
-{
- struct net_device *dev = arg;
-
- if (netif_queue_stopped(dev)) {
- netif_wake_queue(dev);
- }
-}
-
-/*
- * nss_capwapmgr_start_xmit()
- * Transmit's skb to NSS FW over CAPWAP if_num.
- *
- * Please make sure to leave headroom of NSS_CAPWAP_HEADROOM with every
- * packet so that NSS can encap eth,vlan,ip,udp,capwap headers.
- * Also, skb->len must include size of metaheader. Essentially skb->len is
- * size of CAPWAP Payload (including wireless info sections) and metaheader.
- */
-static netdev_tx_t nss_capwapmgr_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct net_device_stats *stats = &dev->stats;
- struct nss_capwapmgr_priv *priv;
- struct nss_capwap_metaheader *pre;
- uint32_t if_num;
- nss_tx_status_t status;
-
- priv = netdev_priv(dev);
- pre = (struct nss_capwap_metaheader *)skb->data;
-
- if (pre->tunnel_id > NSS_CAPWAPMGR_MAX_TUNNELS) {
- nss_capwapmgr_warn("%p: (CAPWAP packet) tunnel-id invalid: %d\n", dev, pre->tunnel_id);
- kfree_skb(skb);
- stats->tx_dropped++;
- return NETDEV_TX_OK;
- }
-
- if_num = priv->tunnel[pre->tunnel_id].if_num;
- if (if_num == 0) {
- nss_capwapmgr_warn("%p: (CAPWAP packet) if_num in the tunnel not set\n", dev);
- kfree_skb(skb);
- stats->tx_dropped++;
- return NETDEV_TX_OK;
- }
-
- status = nss_capwap_tx_data(priv->nss_ctx, skb, if_num);
- if (status != NSS_TX_SUCCESS) {
- if (status == NSS_TX_FAILURE_QUEUE) {
- nss_capwapmgr_warn("%p: netdev :%p queue is full", dev, dev);
- if (!netif_queue_stopped(dev)) {
- netif_stop_queue(dev);
- }
- }
-
- kfree_skb(skb);
- nss_capwapmgr_warn("%p: (CAPWAP packet) Failed to xmit the packet : %d\n", dev, status);
- stats->tx_dropped++;
- return NETDEV_TX_BUSY;
- }
-
- return NETDEV_TX_OK;
-}
-
-/*
- * nss_capwapmgr_fill_up_stats()
- * Fills up stats in netdev's stats.
- */
-static void nss_capwapmgr_fill_up_stats(struct rtnl_link_stats64 *stats, struct nss_capwap_tunnel_stats *tstats)
-{
- stats->rx_packets += tstats->pnode_stats.rx_packets;
- stats->rx_dropped += tstats->pnode_stats.rx_dropped;
- /* rx_fifo_errors will appear as rx overruns in ifconfig */
- stats->rx_fifo_errors += (tstats->rx_queue_full_drops + tstats->rx_n2h_queue_full_drops);
- stats->rx_errors += (tstats->rx_mem_failure_drops + tstats->oversize_drops + tstats->frag_timeout_drops);
- stats->rx_bytes += tstats->pnode_stats.rx_bytes;
-
- stats->tx_packets += tstats->pnode_stats.tx_packets;
- /* tx_fifo_errors will appear as tx overruns in ifconfig */
- stats->tx_fifo_errors += tstats->tx_queue_full_drops;
- stats->tx_errors += tstats->tx_mem_failure_drops;
- stats->tx_bytes += tstats->pnode_stats.tx_bytes;
-}
-
-/*
- * nss_capwapmgr_get_tunnel_stats()
- * Netdev get stats function to get tunnel stats
- */
-static struct rtnl_link_stats64 *nss_capwapmgr_get_tunnel_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
-{
- struct nss_capwap_tunnel_stats tstats;
- int i;
-
- if (!stats) {
- return stats;
- }
-
- /*
- * Netdev seems to be incrementing rx_dropped because we don't give IP header.
- * So reset it as it's of no use for us.
- */
- atomic_long_set(&dev->rx_dropped, 0);
-
- memset(stats, 0, sizeof (struct rtnl_link_stats64));
- nss_capwapmgr_fill_up_stats(stats, &tunneld);
-
- for (i = NSS_DYNAMIC_IF_START; i <= (NSS_DYNAMIC_IF_START + NSS_MAX_DYNAMIC_INTERFACES); i++) {
- if (nss_capwap_get_stats(i, &tstats) == false) {
- continue;
- }
-
- nss_capwapmgr_fill_up_stats(stats, &tstats);
- }
-
- return stats;
-}
-
-/*
- * nss_capwapmgr_netdev_ops
- * Netdev operations.
- */
-static const struct net_device_ops nss_capwapmgr_netdev_ops = {
- .ndo_open = nss_capwapmgr_open,
- .ndo_stop = nss_capwapmgr_close,
- .ndo_start_xmit = nss_capwapmgr_start_xmit,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
- .ndo_get_stats64 = nss_capwapmgr_get_tunnel_stats,
-};
-
-/*
- * nss_capwapmgr_dummpy_netdev_setup()
- * Netdev setup function.
- */
-static void nss_capwapmgr_dummpy_netdev_setup(struct net_device *dev)
-{
- dev->addr_len = ETH_ALEN;
- dev->mtu = ETH_DATA_LEN;
- dev->needed_headroom = NSS_CAPWAP_HEADROOM;
- dev->needed_tailroom = 4;
- dev->type = ARPHRD_VOID;
- dev->ethtool_ops = NULL;
- dev->header_ops = NULL;
- dev->netdev_ops = &nss_capwapmgr_netdev_ops;
- dev->destructor = NULL;
- memcpy(dev->dev_addr, "\x00\x00\x00\x00\x00\x00", dev->addr_len);
- memset(dev->broadcast, 0xff, dev->addr_len);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-}
-
-/*
- * nss_capwapmgr_msg_event_receive()
- * CAPWAP message callback for responses to commands sent to NSS FW
- *
- * This is command hanlder for all the messages since all we do is wake-up
- * the caller who is sending message to NSS FW.
- */
-static void nss_capwapmgr_msg_event_receive(void *app_data, struct nss_capwap_msg *nim)
-{
- struct net_device *dev = app_data;
- struct nss_cmn_msg *ncm = (struct nss_cmn_msg *)nim;
- struct nss_capwapmgr_response *r;
- struct nss_capwapmgr_priv *priv;
- uint32_t if_num;
-
- if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
- return;
- }
-
- /*
- * Since all CAPWAP messages are sync in nature we need to wake-up caller.
- */
- if_num = ncm->interface - NSS_DYNAMIC_IF_START;
- dev_hold(dev);
- priv = netdev_priv(dev);
- r = &priv->resp[if_num];
-
- /*
- * If somebody is waiting...
- */
- if (atomic_read(&r->seq) != 0) {
- if (ncm->response != NSS_CMN_RESPONSE_ACK) {
- r->error = ncm->error;
- }
-
- r->response = ncm->response;
- atomic_dec(&r->seq);
- wake_up(&r->wq);
- }
-
- dev_put(dev);
-}
-
-/*
- * nss_capwap_remap_error()
- * Remaps NSS FW response error to nss_capwapmgr_status_t
- */
-static nss_capwapmgr_status_t nss_capwap_remap_error(nss_capwap_msg_response_t error)
-{
- nss_capwapmgr_status_t status;
-
- switch (error) {
- case NSS_CAPWAP_ERROR_MSG_INVALID_REASSEMBLY_TIMEOUT:
- status = NSS_CAPWAPMGR_FAILURE_INVALID_REASSEMBLY_TIMEOUT;
- break;
- case NSS_CAPWAP_ERROR_MSG_INVALID_PATH_MTU:
- status = NSS_CAPWAPMGR_FAILURE_INVALID_PATH_MTU;
- break;
- case NSS_CAPWAP_ERROR_MSG_INVALID_MAX_FRAGMENT:
- status = NSS_CAPWAPMGR_FAILURE_INVALID_MAX_FRAGMENT;
- break;
- case NSS_CAPWAP_ERROR_MSG_INVALID_BUFFER_SIZE:
- status = NSS_CAPWAPMGR_FAILURE_INVALID_BUFFER_SIZE;
- break;
- case NSS_CAPWAP_ERROR_MSG_INVALID_L3_PROTO:
- status = NSS_CAPWAPMGR_FAILURE_INVALID_L3_PROTO;
- break;
- case NSS_CAPWAP_ERROR_MSG_INVALID_UDP_PROTO:
- status = NSS_CAPWAPMGR_FAILURE_INVALID_UDP_PROTO;
- break;
- case NSS_CAPWAP_ERROR_MSG_INVALID_VERSION:
- status = NSS_CAPWAPMGR_FAILURE_INVALID_VERSION;
- break;
- case NSS_CAPWAP_ERROR_MSG_TUNNEL_DISABLED:
- status = NSS_CAPWAPMGR_FAILURE_TUNNEL_DISABLED;
- break;
- case NSS_CAPWAP_ERROR_MSG_TUNNEL_ENABLED:
- status = NSS_CAPWAPMGR_FAILURE_TUNNEL_ENABLED;
- break;
- case NSS_CAPWAP_ERROR_MSG_TUNNEL_NOT_CFG:
- status = NSS_CAPWAPMGR_FAILURE_TUNNEL_NOT_CFG;
- break;
- default:
- status = NSS_CAPWAPMGR_FAILURE;
- }
-
- return status;
-}
-
-/*
- * nss_capwapmgr_verify_tunnel_param()
- * Common function to verify tunnel_id and returns pointer to tunnel.
- */
-static struct nss_capwapmgr_tunnel *nss_capwapmgr_verify_tunnel_param(struct net_device *dev, uint8_t tunnel_id)
-{
- struct nss_capwapmgr_priv *priv;
- struct nss_capwapmgr_tunnel *t;
-
- if (!dev) {
- return NULL;
- }
-
- if (tunnel_id > NSS_CAPWAPMGR_MAX_TUNNELS) {
- return NULL;
- }
-
- dev_hold(dev);
- priv = netdev_priv(dev);
- t = &priv->tunnel[tunnel_id];
- if (t->if_num == 0) {
- dev_put(dev);
- return NULL;
- }
-
- dev_put(dev);
- return t;
-}
-
-/*
- * nss_capwapmgr_netdev_create()
- * API to create a CAPWAP netdev
- */
-struct net_device *nss_capwapmgr_netdev_create()
-{
- struct nss_capwapmgr_priv *priv;
- struct nss_capwapmgr_response *r;
- struct net_device *ndev;
- int i;
- int err;
-
- ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
- "nsscapwap%d", nss_capwapmgr_dummpy_netdev_setup);
- if (!ndev) {
- nss_capwapmgr_warn("Error allocating netdev\n");
- return NULL;
- }
-
- err = register_netdev(ndev);
- if (err) {
- nss_capwapmgr_warn("register_netdev() fail with error :%d\n", err);
- free_netdev(ndev);
- return NULL;
- }
-
- priv = netdev_priv(ndev);
- priv->nss_ctx = nss_capwap_get_ctx();
- priv->tunnel = kmalloc(sizeof(struct nss_capwapmgr_tunnel) * NSS_CAPWAPMGR_MAX_TUNNELS, GFP_ATOMIC);
- if (!priv->tunnel) {
- nss_capwapmgr_warn("failed to allocate tunnel memory");
- goto fail1;
- }
- memset(priv->tunnel, 0, sizeof(struct nss_capwapmgr_tunnel) * NSS_CAPWAPMGR_MAX_TUNNELS);
-
- priv->resp = kmalloc(sizeof(struct nss_capwapmgr_response) * NSS_MAX_DYNAMIC_INTERFACES, GFP_ATOMIC);
- if (!priv->resp) {
- nss_capwapmgr_warn("failed to allocate tunnel response memory");
- goto fail2;
- }
- for (i = 0; i < NSS_MAX_DYNAMIC_INTERFACES; i++) {
- r = &priv->resp[i];
- init_waitqueue_head(&r->wq);
-
- /*
- * CAPWAP interface is limited to one command per-tunnel.
- */
- sema_init(&r->sem, 1);
- }
-
- priv->if_num_to_tunnel_id = kmalloc(sizeof(uint8_t) * NSS_MAX_NET_INTERFACES, GFP_ATOMIC);
- if (!priv->if_num_to_tunnel_id) {
- nss_capwapmgr_warn("failed to allocate if_num to tunnel_id memory");
- goto fail3;
- }
- memset(priv->if_num_to_tunnel_id, 0, sizeof(uint8_t) * NSS_MAX_NET_INTERFACES);
-
- if (nss_cmn_register_queue_decongestion(priv->nss_ctx, nss_capwapmgr_decongestion_callback, ndev) != NSS_CB_REGISTER_SUCCESS) {
- nss_capwapmgr_warn("failed to register decongestion callback");
- goto fail4;
- }
-
- return ndev;
-fail4:
- kfree(priv->if_num_to_tunnel_id);
-fail3:
- kfree(priv->resp);
-fail2:
- kfree(priv->tunnel);
-fail1:
- unregister_netdev(ndev);
- free_netdev(ndev);
- return NULL;
-}
-EXPORT_SYMBOL(nss_capwapmgr_netdev_create);
-
-/*
- * nss_capwapmgr_netdev_destroy()
- * API for destroying a netdevice.
- *
- * All the CAPWAP tunnels must be destroyed first before netdevice.
- */
-nss_capwapmgr_status_t nss_capwapmgr_netdev_destroy(struct net_device *dev)
-{
- rtnl_is_locked() ? unregister_netdevice(dev) : unregister_netdev(dev);
- return NSS_CAPWAPMGR_SUCCESS;
-}
-EXPORT_SYMBOL(nss_capwapmgr_netdev_destroy);
-
-/*
- * nss_capwapmgr_register_with_nss()
- * Internal function to register with NSS FW.
- */
-static nss_capwapmgr_status_t nss_capwapmgr_register_with_nss(uint32_t interface_num, struct net_device *dev)
-{
- struct nss_ctx_instance *ctx;
-
- /* features denote the skb_types supported */
- uint32_t features = 0;
-
- ctx = nss_capwap_data_register(interface_num, nss_capwapmgr_receive_pkt, dev, features);
- if (!ctx) {
- nss_capwapmgr_warn("%p: %d: nss_capwapmgr_data_register failed\n", dev, interface_num);
- return NSS_CAPWAPMGR_FAILURE;
- }
-
- return NSS_CAPWAPMGR_SUCCESS;
-}
-
-/*
- * nss_capwapmgr_unregister_with_nss()
- * Internal function to unregister with NSS FW
- */
-static void nss_capwapmgr_unregister_with_nss(uint32_t if_num)
-{
- nss_capwapmgr_trace("%d: unregister with NSS FW", if_num);
- nss_capwap_data_unregister(if_num);
-}
-
-/*
- * nss_capwapmgr_destroy_ipv4_rule()
- * Destroy a given connection in the NSS
- */
-static nss_tx_status_t nss_capwapmgr_destroy_ipv4_rule(void *ctx, struct nss_ipv4_destroy *unid)
-{
- struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *) ctx;
- struct nss_ipv4_msg nim;
- struct nss_ipv4_rule_destroy_msg *nirdm;
-
- nss_capwapmgr_info("%p: ctx: Destroy IPv4: %pI4h:%d, %pI4h:%d, p: %d\n", nss_ctx,
- &unid->src_ip, ntohs(unid->src_port), &unid->dest_ip, ntohs(unid->dest_port), unid->protocol);
-
- nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_DESTROY_RULE_MSG,
- sizeof(struct nss_ipv4_rule_destroy_msg), NULL, NULL);
-
- nirdm = &nim.msg.rule_destroy;
-
- nirdm->tuple.protocol = (uint8_t)unid->protocol;
- nirdm->tuple.flow_ip = unid->src_ip;
- nirdm->tuple.flow_ident = (uint32_t)unid->src_port;
- nirdm->tuple.return_ip = unid->dest_ip;
- nirdm->tuple.return_ident = (uint32_t)unid->dest_port;
- return nss_ipv4_tx(nss_ctx, &nim);
-}
-
-/*
- * nss_capwapmgr_unconfigure_ipv4_rule()
- * Internal function to unconfigure IPv4 rule.
- */
-static nss_tx_status_t nss_capwapmgr_unconfigure_ipv4_rule(struct nss_ipv4_destroy *destroy)
-{
- void *ctx;
-
- ctx = nss_ipv4_get_mgr();
- if (!ctx) {
- nss_capwapmgr_warn("%s: couldn't get IPv4 ctx\n", "CAPWAP");
- return NSS_TX_FAILURE_NOT_READY;
- }
-
- return nss_capwapmgr_destroy_ipv4_rule(ctx, destroy);
-}
-
-/*
- * nss_capwapmgr_create_ipv4_rule()
- * Create a nss entry to accelerate the given connection
- */
-static nss_tx_status_t nss_capwapmgr_create_ipv4_rule(void *ctx, struct nss_ipv4_create *unic)
-{
- struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *) ctx;
- struct nss_ipv4_msg nim;
- struct nss_ipv4_rule_create_msg *nircm;
-
- nss_capwapmgr_info("%p: ctx: Create IPv4: %pI4h:%d (%pI4h:%d), %pI4h:%d (%pI4h:%d), p: %d\n", nss_ctx,
- &unic->src_ip, ntohs(unic->src_port), &unic->src_ip_xlate, ntohs(unic->src_port_xlate),
- &unic->dest_ip, ntohs(unic->dest_port), &unic->dest_ip_xlate, ntohs(unic->dest_port_xlate),
- unic->protocol);
-
- nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_CREATE_RULE_MSG,
- sizeof(struct nss_ipv4_rule_create_msg), NULL, NULL);
-
- nircm = &nim.msg.rule_create;
- nircm->valid_flags = 0;
- nircm->rule_flags = 0;
-
- /*
- * Copy over the 5 tuple details.
- */
- nircm->tuple.protocol = (uint8_t)unic->protocol;
- nircm->tuple.flow_ip = unic->src_ip;
- nircm->tuple.flow_ident = (uint32_t)unic->src_port;
- nircm->tuple.return_ip = unic->dest_ip;
- nircm->tuple.return_ident = (uint32_t)unic->dest_port;
-
- /*
- * Copy over the connection rules and set the CONN_VALID flag
- */
- nircm->conn_rule.flow_interface_num = unic->src_interface_num;
- nircm->conn_rule.flow_mtu = unic->from_mtu;
- nircm->conn_rule.flow_ip_xlate = unic->src_ip_xlate;
- nircm->conn_rule.flow_ident_xlate = (uint32_t)unic->src_port_xlate;
- memcpy(nircm->conn_rule.flow_mac, unic->src_mac, 6);
- nircm->conn_rule.return_interface_num = unic->dest_interface_num;
- nircm->conn_rule.return_mtu = unic->to_mtu;
- nircm->conn_rule.return_ip_xlate = unic->dest_ip_xlate;
- nircm->conn_rule.return_ident_xlate = (uint32_t)unic->dest_port_xlate;
- if (nircm->tuple.return_ip != nircm->conn_rule.return_ip_xlate ||
- nircm->tuple.return_ident != nircm->conn_rule.return_ident_xlate) {
- memcpy(nircm->conn_rule.return_mac, unic->dest_mac_xlate, 6);
- } else {
- memcpy(nircm->conn_rule.return_mac, unic->dest_mac, 6);
- }
-
- /*
- * Copy over the DSCP rule parameters
- */
- nircm->dscp_rule.flow_dscp = unic->flow_dscp;
- nircm->dscp_rule.return_dscp = unic->return_dscp;
- if (unic->flags & NSS_IPV4_CREATE_FLAG_DSCP_MARKING) {
- nircm->rule_flags |= NSS_IPV4_RULE_CREATE_FLAG_DSCP_MARKING;
- nircm->valid_flags |= NSS_IPV4_RULE_CREATE_DSCP_MARKING_VALID;
- }
-
- nircm->valid_flags |= NSS_IPV4_RULE_CREATE_CONN_VALID;
-
- /*
- * Copy over the pppoe rules and set the PPPOE_VALID flag.
- */
- nircm->pppoe_rule.flow_pppoe_session_id = unic->flow_pppoe_session_id;
- memcpy(nircm->pppoe_rule.flow_pppoe_remote_mac, unic->flow_pppoe_remote_mac, ETH_ALEN);
- nircm->pppoe_rule.return_pppoe_session_id = unic->return_pppoe_session_id;
- memcpy(nircm->pppoe_rule.return_pppoe_remote_mac, unic->return_pppoe_remote_mac, ETH_ALEN);
- nircm->valid_flags |= NSS_IPV4_RULE_CREATE_PPPOE_VALID;
-
- /*
- * Copy over the vlan rules and set the VLAN_VALID flag
- */
- nircm->vlan_primary_rule.ingress_vlan_tag = unic->in_vlan_tag[0];
- nircm->vlan_primary_rule.egress_vlan_tag = unic->out_vlan_tag[0];
- nircm->vlan_secondary_rule.ingress_vlan_tag = unic->in_vlan_tag[1];
- nircm->vlan_secondary_rule.egress_vlan_tag = unic->out_vlan_tag[1];
- nircm->valid_flags |= NSS_IPV4_RULE_CREATE_VLAN_VALID;
-
- /*
- * Copy over the qos rules and set the QOS_VALID flag
- */
- nircm->qos_rule.flow_qos_tag = unic->flow_qos_tag;
- nircm->qos_rule.return_qos_tag = unic->return_qos_tag;
-
- nircm->valid_flags |= NSS_IPV4_RULE_CREATE_QOS_VALID;
-
- if (unic->flags & NSS_IPV4_CREATE_FLAG_NO_SEQ_CHECK) {
- nircm->rule_flags |= NSS_IPV4_RULE_CREATE_FLAG_NO_SEQ_CHECK;
- }
-
- if (unic->flags & NSS_IPV4_CREATE_FLAG_BRIDGE_FLOW) {
- nircm->rule_flags |= NSS_IPV4_RULE_CREATE_FLAG_BRIDGE_FLOW;
- }
-
- if (unic->flags & NSS_IPV4_CREATE_FLAG_ROUTED) {
- nircm->rule_flags |= NSS_IPV4_RULE_CREATE_FLAG_ROUTED;
- }
-
- /*
- * Set the flag NSS_IPV4_RULE_CREATE_FLAG_ICMP_NO_CME_FLUSH so that
- * rule is not flushed when NSS FW receives ICMP errors/packets.
- */
- nircm->rule_flags |= NSS_IPV4_RULE_CREATE_FLAG_ICMP_NO_CME_FLUSH;
-
- return nss_ipv4_tx(nss_ctx, &nim);
-}
-
-/*
- * nss_capwapmgr_configure_ipv4()
- * Internal function for configuring IPv4 connection
- */
-static nss_tx_status_t nss_capwapmgr_configure_ipv4(struct nss_ipv4_create *pcreate)
-{
- nss_tx_status_t status;
- void *ctx;
-
- ctx = nss_ipv4_get_mgr();
- if (!ctx) {
- nss_capwapmgr_warn("%s couldn't get IPv4 ctx\n", "CAPWAP");
- return -1;
- }
-
- status = nss_capwapmgr_create_ipv4_rule(ctx, pcreate);
- if (status != NSS_TX_SUCCESS) {
- nss_capwapmgr_warn("%p: ctx: nss_ipv4_tx() failed with %d\n", ctx, status);
- return status;
- }
-
- return NSS_TX_SUCCESS;
-}
-
-/*
- * nss_capwapmgr_tx_msg_sync()
- * Waits for message to return.
- */
-static nss_capwapmgr_status_t nss_capwapmgr_tx_msg_sync(struct nss_ctx_instance *ctx, struct net_device *dev, struct nss_capwap_msg *msg)
-{
- struct nss_capwapmgr_priv *priv;
- struct nss_capwapmgr_response *r;
- uint32_t if_num;
- nss_capwapmgr_status_t status;
-
- if_num = msg->cm.interface - NSS_DYNAMIC_IF_START;
- dev_hold(dev);
- priv = netdev_priv(dev);
- r = &priv->resp[if_num];
- down(&r->sem);
- r->response = NSS_CMN_RESPONSE_ACK;
- atomic_set(&r->seq, 1); /* Indicate that we are waiting */
-
- /*
- * Call NSS driver
- */
- status = nss_capwap_tx_msg(ctx, msg);
- if (status != NSS_CAPWAPMGR_SUCCESS) {
- up(&r->sem);
- return status;
- }
-
- if (!wait_event_timeout(r->wq, atomic_read(&r->seq) == 0, 5 * HZ)) {
- atomic_set(&r->seq, 0); /* Indicate that we are no longer waiting */
- up(&r->sem);
- nss_capwapmgr_warn("%p: CAPWAP command msg response timeout\n", ctx);
- return NSS_CAPWAPMGR_FAILURE_CMD_TIMEOUT;
- }
-
- /*
- * If NSS FW responded back with an error.
- */
- if (r->response != NSS_CMN_RESPONSE_ACK) {
- up(&r->sem);
- nss_warning("%p: CAPWAP command msg response : %d, error:%d\n", ctx,
- r->response, r->error);
- return nss_capwap_remap_error(r->error);
- }
-
- up(&r->sem);
- return status;
-}
-
-/*
- * nss_capwapmgr_create_capwap_rule()
- * Internal function to create a CAPWAP rule
- */
-static nss_capwapmgr_status_t nss_capwapmgr_create_capwap_rule(struct net_device *dev, uint32_t if_num, struct nss_capwap_rule_msg *msg)
-{
- struct nss_ctx_instance *ctx = nss_capwap_get_ctx();
- struct nss_capwap_msg capwapmsg;
- struct nss_capwap_rule_msg *capwapcfg;
- nss_tx_status_t status;
-
- nss_capwapmgr_info("%p: ctx: CAPWAP Rule src_port: 0x%d dest_port:0x%d\n", ctx,
- ntohl(msg->encap.src_port), ntohl(msg->encap.dest_port));
-
- /*
- * Verify CAPWAP rule parameters.
- */
- if (ntohl(msg->decap.reassembly_timeout) > NSS_CAPWAP_MAX_REASSEMBLY_TIMEOUT) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- if (msg->decap.reassembly_timeout == 0) {
- msg->decap.reassembly_timeout = htonl(10); /* 10 milli-seconds */
- }
-
- if (ntohl(msg->decap.max_fragments) > NSS_CAPWAP_MAX_FRAGMENTS) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- if (msg->decap.max_fragments == 0) {
- msg->decap.max_fragments = htonl(NSS_CAPWAP_MAX_FRAGMENTS);
- }
-
- if (ntohl(msg->decap.max_buffer_size) > NSS_CAPWAP_MAX_BUFFER_SIZE) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- if (msg->decap.max_buffer_size == 0) {
- msg->decap.max_buffer_size = htonl(ctx->max_buf_size);
- }
-
- if (ntohl(msg->encap.path_mtu) > NSS_CAPWAP_MAX_MTU) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- if (msg->encap.path_mtu == 0) {
- msg->encap.path_mtu = htonl(NSS_GMAC_NORMAL_FRAME_MTU);
- }
-
- /*
- * Prepare the tunnel configuration parameter to send to NSS FW
- */
- memset(&capwapmsg, 0, sizeof(struct nss_capwap_msg));
- capwapcfg = &capwapmsg.msg.rule;
- memcpy(capwapcfg, msg, sizeof(struct nss_capwap_rule_msg));
-
- /*
- * Send CAPWAP tunnel create command to NSS
- */
- nss_capwap_msg_init(&capwapmsg, if_num, NSS_CAPWAP_MSG_TYPE_CFG_RULE,
- sizeof(struct nss_capwap_rule_msg),
- (nss_capwap_msg_callback_t *)nss_capwapmgr_msg_event_receive, dev);
-
- status = nss_capwapmgr_tx_msg_sync(ctx, dev, &capwapmsg);
- if (status != NSS_TX_SUCCESS) {
- nss_capwapmgr_warn("%p: ctx: create encap data tunnel error %d \n", ctx, status);
- return status;
- }
-
- return NSS_CAPWAPMGR_SUCCESS;
-}
-
-/*
- * nss_capwapmgr_update_path_mtu()
- * API for updating Path MTU
- */
-nss_capwapmgr_status_t nss_capwapmgr_update_path_mtu(struct net_device *dev, uint8_t tunnel_id, uint32_t mtu)
-{
- struct nss_capwapmgr_priv *priv;
- struct nss_capwap_msg capwapmsg;
- struct nss_capwapmgr_tunnel *t;
- nss_capwapmgr_status_t status;
-
- if (mtu > NSS_CAPWAP_MAX_MTU) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id);
- if (!t) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- dev_hold(dev);
- priv = netdev_priv(dev);
- nss_capwapmgr_info("%p: %d: tunnel update MTU is being called\n", dev, t->if_num);
-
- /*
- * Prepare the tunnel configuration parameter to send to NSS FW
- */
- memset(&capwapmsg, 0, sizeof(struct nss_capwap_msg));
-
- /*
- * Send CAPWAP data tunnel command to NSS
- */
- nss_capwap_msg_init(&capwapmsg, t->if_num, NSS_CAPWAP_MSG_TYPE_UPDATE_PATH_MTU,
- 0, (nss_capwap_msg_callback_t *)nss_capwapmgr_msg_event_receive, dev);
- capwapmsg.msg.mtu.path_mtu = mtu;
- status = nss_capwapmgr_tx_msg_sync(priv->nss_ctx, dev, &capwapmsg);
- if (status != NSS_CAPWAPMGR_SUCCESS) {
- nss_capwapmgr_warn("%p: Update Path MTU Tunnel error : %d \n", dev, status);
- dev_put(dev);
- return status;
- }
-
- dev_put(dev);
- return status;
-}
-EXPORT_SYMBOL(nss_capwapmgr_update_path_mtu);
-
-/*
- * nss_capwapmgr_change_version()
- * Change CAPWAP version
- */
-
-nss_capwapmgr_status_t nss_capwapmgr_change_version(struct net_device *dev, uint8_t tunnel_id, uint8_t ver)
-{
- struct nss_capwapmgr_priv *priv;
- struct nss_capwap_msg capwapmsg;
- struct nss_capwapmgr_tunnel *t;
- nss_capwapmgr_status_t status;
-
- t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id);
- if (!t) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- if (ver > NSS_CAPWAP_VERSION_V2) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- dev_hold(dev);
- priv = netdev_priv(dev);
-
- /*
- * Prepare the tunnel configuration parameter to send to NSS FW
- */
- memset(&capwapmsg, 0, sizeof(struct nss_capwap_msg));
-
- /*
- * Send CAPWAP data tunnel command to NSS
- */
- nss_capwap_msg_init(&capwapmsg, t->if_num, NSS_CAPWAP_MSG_TYPE_VERSION,
- 0, (nss_capwap_msg_callback_t *)nss_capwapmgr_msg_event_receive, dev);
- capwapmsg.msg.version.version = ver;
- status = nss_capwapmgr_tx_msg_sync(priv->nss_ctx, dev, &capwapmsg);
- if (status != NSS_CAPWAPMGR_SUCCESS) {
- nss_capwapmgr_warn("%p: Update Path MTU Tunnel error : %d \n", dev, status);
- dev_put(dev);
- return status;
- }
-
- dev_put(dev);
- return status;
-}
-EXPORT_SYMBOL(nss_capwapmgr_change_version);
-
-/*
- * nss_capwapmgr_tunnel_action()
- * Common function for CAPWAP tunnel operation messages without
- * any message data structures.
- */
-static nss_tx_status_t nss_capwapmgr_tunnel_action(struct nss_ctx_instance *ctx, struct net_device *dev, uint32_t if_num, nss_capwap_msg_type_t cmd)
-{
- struct nss_capwap_msg capwapmsg;
- nss_tx_status_t status;
-
- /*
- * Prepare the tunnel configuration parameter to send to NSS FW
- */
- memset(&capwapmsg, 0, sizeof(struct nss_capwap_msg));
-
- /*
- * Send CAPWAP data tunnel command to NSS
- */
- nss_capwap_msg_init(&capwapmsg, if_num, cmd, 0, (nss_capwap_msg_callback_t *)nss_capwapmgr_msg_event_receive, dev);
- status = nss_capwapmgr_tx_msg_sync(ctx, dev, &capwapmsg);
- if (status != NSS_TX_SUCCESS) {
- nss_capwapmgr_warn("%p: ctx: CMD: %d Tunnel error : %d \n", ctx, cmd, status);
- return status;
- }
-
- return status;
-}
-
-/*
- * nss_capwapmgr_enable_tunnel()
- * API for enabling a data tunnel
- */
-nss_capwapmgr_status_t nss_capwapmgr_enable_tunnel(struct net_device *dev, uint8_t tunnel_id)
-{
- struct nss_capwapmgr_priv *priv;
- struct nss_capwapmgr_tunnel *t;
- nss_tx_status_t ret;
-
- t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id);
- if (!t) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- if (t->tunnel_state & NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED) {
- return NSS_CAPWAPMGR_FAILURE_TUNNEL_ENABLED;
- }
-
- dev_hold(dev);
- priv = netdev_priv(dev);
- nss_capwapmgr_info("%p: %d: tunnel enable is being called\n", dev, t->if_num);
- ret = nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, t->if_num, NSS_CAPWAP_MSG_TYPE_ENABLE_TUNNEL);
- if (ret == NSS_TX_SUCCESS) {
- t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED;
- }
- dev_put(dev);
- return ret;
-}
-EXPORT_SYMBOL(nss_capwapmgr_enable_tunnel);
-
-/*
- * nss_capwapmgr_disable_tunnel()
- * API for disabling a data tunnel
- */
-nss_capwapmgr_status_t nss_capwapmgr_disable_tunnel(struct net_device *dev, uint8_t tunnel_id)
-{
- struct nss_capwapmgr_priv *priv;
- struct nss_capwapmgr_tunnel *t;
- nss_tx_status_t ret;
-
- t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id);
- if (!t) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- if (!(t->tunnel_state & NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED)) {
- return NSS_CAPWAPMGR_FAILURE_TUNNEL_DISABLED;
- }
-
- dev_hold(dev);
- priv = netdev_priv(dev);
- nss_capwapmgr_info("%p: %d: tunnel disable is being called\n", dev, t->if_num);
- ret = nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, t->if_num, NSS_CAPWAP_MSG_TYPE_DISABLE_TUNNEL);
- if (ret == NSS_TX_SUCCESS) {
- t->tunnel_state &= ~NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED;
- }
- dev_put(dev);
- return ret;
-}
-EXPORT_SYMBOL(nss_capwapmgr_disable_tunnel);
-
-/*
- * nss_capwapmgr_ipv4_tunnel_create()
- * API for creating IPv4 and CAPWAP rule.
- */
-nss_capwapmgr_status_t nss_capwapmgr_ipv4_tunnel_create(struct net_device *dev, uint8_t tunnel_id,
- struct nss_ipv4_create *ip_rule, struct nss_capwap_rule_msg *capwap_rule)
-{
- struct nss_capwapmgr_priv *priv;
- struct nss_capwapmgr_tunnel *t;
- nss_capwapmgr_status_t status;
- int32_t if_num;
- nss_tx_status_t nss_status;
-
- if (tunnel_id > NSS_CAPWAPMGR_MAX_TUNNELS) {
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id);
- if (t) {
- return NSS_CAPWAPMGR_FAILURE_TUNNEL_EXISTS;
- }
-
- if_num = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP);
- if (if_num < 0) {
- nss_capwapmgr_warn("%p: di returned error : %d\n", dev, if_num);
- return NSS_CAPWAPMGR_FAILURE_DI_ALLOC_FAILED;
- }
-
- if (nss_capwapmgr_register_with_nss(if_num, dev) != NSS_CAPWAPMGR_SUCCESS) {
- nss_capwapmgr_warn("%d: NSS CAPWAP register with NSS failed", if_num);
- (void)nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP);
- return NSS_CAPWAPMGR_FAILURE_REGISTER_NSS;
- }
-
- status = nss_capwapmgr_create_capwap_rule(dev, if_num, capwap_rule);
- nss_capwapmgr_info("%p: dynamic interface if_num is :%d and capwap tunnel status:%d\n", dev, if_num, status);
- if (status != NSS_CAPWAPMGR_SUCCESS) {
- nss_capwapmgr_warn("%p: %d: CAPWAP rule create failed with status: %d", dev, if_num, status);
- nss_capwapmgr_unregister_with_nss(if_num);
- (void)nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP);
- return NSS_CAPWAPMGR_FAILURE_CAPWAP_RULE;
- }
-
- ip_rule->dest_interface_num = if_num;
- nss_status = nss_capwapmgr_configure_ipv4(ip_rule);
- if (nss_status != NSS_TX_SUCCESS) {
- nss_capwapmgr_warn("%p: %d: IPv4/IPv6 rule create failed with status: %d", dev, if_num, nss_status);
- nss_capwapmgr_unregister_with_nss(if_num);
- (void)nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP);
- return NSS_CAPWAPMGR_FAILURE_IP_RULE;
- }
-
- dev_hold(dev);
- priv = netdev_priv(dev);
- t = &priv->tunnel[tunnel_id];
- nss_capwapmgr_info("%p: %d: CAPWAP TUNNEL CREATE DONE tunnel_id:%d (%p)\n", dev, if_num, tunnel_id, t);
-
- /*
- * Keep a copy of rule information.
- */
- memcpy(&t->ip_rule.v4, ip_rule, sizeof (struct nss_ipv4_create));
- memcpy(&t->capwap_rule, capwap_rule, sizeof (struct nss_capwap_rule_msg));
-
-
- /*
- * Make it globally visible inside the netdev.
- */
- t->if_num = if_num;
- priv->if_num_to_tunnel_id[if_num] = tunnel_id;
- t->tunnel_state |= NSS_CAPWAPMGR_TUNNEL_STATE_CONFIGURED;
-
- dev_put(dev);
- return status;
-}
-EXPORT_SYMBOL(nss_capwapmgr_ipv4_tunnel_create);
-
-/*
- * nss_capwapmgr_tunnel_save_stats()
- * Internal function to save tunnel stats when a tunnel is being
- * destroyed.
- */
-static void nss_capwapmgr_tunnel_save_stats(struct nss_capwap_tunnel_stats *save, struct nss_capwap_tunnel_stats *fstats)
-{
- save->rx_segments += fstats->rx_segments;
- save->tx_segments += fstats->tx_segments;
- save->dtls_pkts += fstats->dtls_pkts;
- save->oversize_drops += fstats->oversize_drops;
- save->frag_timeout_drops += fstats->frag_timeout_drops;
- save->rx_queue_full_drops += fstats->rx_queue_full_drops;
- save->rx_n2h_queue_full_drops += fstats->rx_n2h_queue_full_drops;
- save->rx_mem_failure_drops += fstats->rx_mem_failure_drops;
-
- save->tx_queue_full_drops += fstats->tx_queue_full_drops;
- save->tx_mem_failure_drops += fstats->tx_mem_failure_drops;
-
- /*
- * add pnode stats now.
- */
- save->pnode_stats.rx_packets += fstats->pnode_stats.rx_packets;
- save->pnode_stats.rx_bytes += fstats->pnode_stats.rx_bytes;
- save->pnode_stats.rx_dropped += fstats->pnode_stats.rx_dropped;
- save->pnode_stats.tx_packets += fstats->pnode_stats.tx_packets;
- save->pnode_stats.tx_bytes += fstats->pnode_stats.tx_bytes;
-}
-
-/*
- * nss_capwapmgr_tunnel_destroy()
- * API for destroying a tunnel. CAPWAP tunnel must be first disabled.
- */
-nss_capwapmgr_status_t nss_capwapmgr_tunnel_destroy(struct net_device *dev, uint8_t tunnel_id)
-{
- struct nss_capwap_tunnel_stats stats;
- struct nss_ipv4_destroy d;
- struct nss_capwapmgr_priv *priv;
- struct nss_capwapmgr_tunnel *t;
- nss_tx_status_t nss_status;
- uint32_t if_num;
- nss_capwapmgr_status_t status;
-
- t = nss_capwapmgr_verify_tunnel_param(dev, tunnel_id);
- if (!t) {
- nss_capwapmgr_warn("%p: tunnel %d: wrong argument for tunnel destroy\n", dev, tunnel_id);
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- if (!(t->tunnel_state & NSS_CAPWAPMGR_TUNNEL_STATE_CONFIGURED)) {
- return NSS_CAPWAPMGR_FAILURE_TUNNEL_NOT_CFG;
- }
-
- /*
- * We don't allow destroy operation on tunnel if it's still
- * enabled.
- */
- if (t->tunnel_state & NSS_CAPWAPMGR_TUNNEL_STATE_ENABLED) {
- return NSS_CAPWAPMGR_FAILURE_TUNNEL_ENABLED;
- }
-
- dev_hold(dev);
- priv = netdev_priv(dev);
- nss_capwapmgr_info("%p: %d: tunnel destroy is being called\n", dev, t->if_num);
- if_num = t->if_num;
-
- if (priv->if_num_to_tunnel_id[if_num] != tunnel_id) {
- nss_capwapmgr_warn("%p: %d: tunnel_id %d didn't match with tunnel_id :%d\n",
- dev, if_num, tunnel_id, priv->if_num_to_tunnel_id[if_num]);
- dev_put(dev);
- return NSS_CAPWAPMGR_FAILURE_BAD_PARAM;
- }
-
- if (nss_capwap_get_stats(if_num, &stats) == true) {
- nss_capwapmgr_tunnel_save_stats(&tunneld, &stats);
- }
-
- t->if_num = 0;
- t->tunnel_state &= ~NSS_CAPWAPMGR_TUNNEL_STATE_CONFIGURED;
- priv->if_num_to_tunnel_id[if_num] = 0;
-
- /*
- * Destroy IP rule first. TODO: Add IPv6 support also
- */
- memset(&d, 0, sizeof (struct nss_ipv4_destroy));
- d.protocol = IPPROTO_UDP; /* TODO: UDP Lite */
- d.src_ip = t->ip_rule.v4.src_ip;
- d.dest_ip = t->ip_rule.v4.dest_ip;
- d.src_port = t->ip_rule.v4.src_port;
- d.dest_port = t->ip_rule.v4.dest_port;
- nss_status = nss_capwapmgr_unconfigure_ipv4_rule(&d);
- if (nss_status != NSS_TX_SUCCESS) {
- nss_capwapmgr_warn("%p: %d: Unconfigure IP rule failed for tunnel : %d\n",
- dev, if_num, tunnel_id);
- }
-
- /*
- * Destroy CAPWAP rule now.
- */
- status = nss_capwapmgr_tunnel_action(priv->nss_ctx, dev, if_num, NSS_CAPWAP_MSG_TYPE_UNCFG_RULE);
- if (status != NSS_CAPWAPMGR_SUCCESS) {
- nss_capwapmgr_warn("%p: %d: Unconfigure CAPWAP rule failed for tunnel : %d\n",
- dev, if_num, tunnel_id);
- }
-
- nss_capwapmgr_unregister_with_nss(if_num);
-
- /*
- * Deallocate dynamic interface
- */
- nss_status = nss_dynamic_interface_dealloc_node(if_num, NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP);
- if (nss_status != NSS_TX_SUCCESS) {
- nss_capwapmgr_warn("%p: %d: Dealloc of dynamic interface failed for tunnel : %d\n",
- dev, if_num, tunnel_id);
- }
-
- memset(t, 0, sizeof (struct nss_capwapmgr_tunnel));
-
- nss_capwapmgr_info("%p: %d: Tunnel %d is completely destroyed\n", dev, if_num, tunnel_id);
- dev_put(dev);
- return nss_status;
-}
-EXPORT_SYMBOL(nss_capwapmgr_tunnel_destroy);
-
-/*
- * nss_capwapmgr_receive_pkt()
- * Receives a pkt from NSS
- */
-static void nss_capwapmgr_receive_pkt(struct net_device *dev, struct sk_buff *skb, struct napi_struct *napi)
-{
- struct nss_capwapmgr_priv *priv;
- struct nss_capwap_metaheader *pre = (struct nss_capwap_metaheader *)skb->data;
- int32_t if_num;
-
- if (skb->len < sizeof(struct nss_capwap_metaheader)) {
- nss_capwapmgr_warn("%p: skb len is short :%d", dev, skb->len);
- dev_kfree_skb_any(skb);
- return;
- }
-
- /* SKB NETIF START */
- dev_hold(dev);
- priv = netdev_priv(dev);
- if (pre->version != NSS_CAPWAP_VERSION_V2) {
- nss_capwapmgr_warn("%p: wrong version number %d expected:%d\n", dev,
- pre->version, NSS_CAPWAP_VERSION_V2);
- }
-
- if_num = pre->tunnel_id; /* NSS FW sends interface number */
- if (if_num > NSS_MAX_NET_INTERFACES) {
- nss_capwapmgr_warn("%p: if_num %d is wrong for skb\n", dev, if_num);
- pre->tunnel_id = 0xFF;
- } else {
- /*
- * Remap interface number to tunnel_id.
- */
- pre->tunnel_id = priv->if_num_to_tunnel_id[if_num];
- }
-
- skb->dev = dev;
- skb->pkt_type = PACKET_HOST;
- skb->skb_iif = dev->ifindex;
- skb_reset_mac_header(skb);
- skb_reset_transport_header(skb);
- (void) netif_rx(skb);
- /* SKB NETIF END */
- dev_put(dev);
-}
-
-#if defined(NSS_CAPWAPMGR_ONE_NETDEV)
-/*
- * nss_capwapmgr_get_netdev()
- * Returns net device used.
- */
-struct net_device *nss_capwapmgr_get_netdev(void)
-{
- return nss_capwapmgr_ndev;
-}
-EXPORT_SYMBOL(nss_capwapmgr_get_netdev);
-#endif
-
-/*
- * nss_capwapmgr_init_module()
- * Tunnel CAPWAP module init function
- */
-int __init nss_capwapmgr_init_module(void)
-{
- nss_capwapmgr_info("module (platform - IPQ806x , Build - %s:%s) loaded\n",
- __DATE__, __TIME__);
-
-#if defined(NSS_CAPWAPMGR_ONE_NETDEV)
- /*
- * In this code, we create a single netdev for all the CAPWAP
- * tunnels.
- */
- nss_capwapmgr_ndev = nss_capwapmgr_netdev_create();
- if (!nss_capwapmgr_ndev) {
- nss_capwapmgr_warn("Couldn't create capwap interface\n");
- return -1;
- }
-#endif
-
-
- memset(&tunneld, 0, sizeof (struct nss_capwap_tunnel_stats));
- return 0;
-}
-
-/*
- * nss_capwapmgr_exit_module()
- * Tunnel CAPWAP module exit function
- */
-void __exit nss_capwapmgr_exit_module(void)
-{
-#if defined(NSS_CAPWAPMGR_ONE_NETDEV)
- struct nss_capwapmgr_priv *priv;
- uint8_t i;
-
- priv = netdev_priv(nss_capwapmgr_ndev);
- for (i = 0; i < NSS_CAPWAPMGR_MAX_TUNNELS; i++) {
- (void) nss_capwapmgr_disable_tunnel(nss_capwapmgr_ndev, i);
- (void) nss_capwapmgr_tunnel_destroy(nss_capwapmgr_ndev, i);
- }
- kfree(priv->if_num_to_tunnel_id);
- kfree(priv->resp);
- kfree(priv->tunnel);
- unregister_netdev(nss_capwapmgr_ndev);
- nss_capwapmgr_ndev = NULL;
-#endif
- nss_capwapmgr_info("module unloaded\n");
-}
-
-module_init(nss_capwapmgr_init_module);
-module_exit(nss_capwapmgr_exit_module);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("NSS CAPWAP manager");
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 82c9b08..fcbe4b2 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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.
@@ -52,6 +52,7 @@
#include "nss_gre_redir.h"
#include "nss_sjack.h"
#include "nss_capwap.h"
+#include "nss_n2h.h"
/*
* Interface numbers are reserved in the
@@ -72,6 +73,10 @@
/*
* Maximum Number of interfaces
*/
+#define NSS_MAX_CORES 2
+#define NSS_MAX_DEVICE_INTERFACES (NSS_MAX_PHYSICAL_INTERFACES + NSS_MAX_VIRTUAL_INTERFACES + NSS_MAX_TUNNEL_INTERFACES + NSS_MAX_DYNAMIC_INTERFACES)
+#define NSS_MAX_NET_INTERFACES (NSS_MAX_DEVICE_INTERFACES + NSS_MAX_SPECIAL_INTERFACES)
+
#define NSS_MAX_PHYSICAL_INTERFACES 4
#define NSS_MAX_VIRTUAL_INTERFACES 16
#define NSS_MAX_TUNNEL_INTERFACES 4
diff --git a/exports/nss_capwap.h b/exports/nss_capwap.h
index 528627a..b0fcc89 100644
--- a/exports/nss_capwap.h
+++ b/exports/nss_capwap.h
@@ -83,6 +83,15 @@
/**< UDPLite tunnel */
/**
+ * CAPWAP tunnel create and type flags. These flags are used
+ * to determine packet header size during encapsulation.
+ */
+#define NSS_CAPWAPMGR_RULE_CREATE_VLAN_CONFIGURED 0x1
+ /**< VLAN Configured for CAPWAP tunnel */
+#define NSS_CAPWAPMGR_RULE_CREATE_PPPOE_CONFIGURED 0x2
+ /**< PPPoE configured for CAPWAP tunnel */
+
+/**
* CAPWAP version
*/
#define NSS_CAPWAP_VERSION_V1 0x1
@@ -161,6 +170,9 @@
struct nss_capwap_rule_msg {
struct nss_capwap_encap_rule encap; /**< Encap portion of the rule */
struct nss_capwap_decap_rule decap; /**< Decap portion of the rule */
+ uint32_t stats_timer; /**< Stats interval timer in mill-seconds */
+ int8_t rps; /**< Core to choose for receiving packets. Set to -1 for NSS FW to decide */
+ uint8_t type_flags; /**< VLAN and/or PPPOE configured */
uint8_t l3_proto; /**< 0=IPv4 or 1=IPv6 */
uint8_t which_udp; /**< 0=UDP or 1=UDPLite */
};
@@ -342,6 +354,15 @@
extern struct nss_ctx_instance *nss_capwap_get_ctx(void);
/**
+ * @brief Gets NSS max_buf_size
+ *
+ * @param NSS context
+ *
+ * @return ctx->max_buf_size.
+ */
+extern uint32_t nss_capwap_get_max_buf_size(struct nss_ctx_instance *nss_ctx);
+
+/**
* @brief Return per-tunnel statistics
*
* @param interface numbe
diff --git a/exports/nss_crypto.h b/exports/nss_crypto.h
index 5a16acf..665e21e 100644
--- a/exports/nss_crypto.h
+++ b/exports/nss_crypto.h
@@ -82,6 +82,15 @@
};
/**
+ * @brief session states
+ */
+enum nss_crypto_session_state {
+ NSS_CRYPTO_SESSION_STATE_NONE = 0, /**< session state none */
+ NSS_CRYPTO_SESSION_STATE_ACTIVE = 1, /**< session state is active */
+ NSS_CRYPTO_SESSION_STATE_FREE = 2 /**< session state is free */
+};
+
+/**
* @brief crypto origin
*/
enum nss_crypto_buf_origin {
@@ -116,7 +125,8 @@
* @brief Reset session related state.
*/
struct nss_crypto_config_session {
- uint32_t idx; /**< session idx on which will be reset */
+ uint32_t idx; /**< session idx on which will be reset */
+ uint32_t state; /**< session idx state */
};
/*
diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h
index b4991eb..2532792 100644
--- a/exports/nss_ipv4.h
+++ b/exports/nss_ipv4.h
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014 - 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.
@@ -403,6 +403,8 @@
} msg;
};
+extern int nss_ipv6_conn_cfg;
+
/**
* Callback to be called when IPv4 message is received
*/
diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h
index 116098c..091b213 100644
--- a/exports/nss_ipv6.h
+++ b/exports/nss_ipv6.h
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014 - 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.
@@ -367,6 +367,8 @@
} msg;
};
+extern int nss_ipv4_conn_cfg;
+
/**
* Callback to be called when IPv6 message is received
*/
diff --git a/exports/nss_n2h.h b/exports/nss_n2h.h
new file mode 100644
index 0000000..154a06c
--- /dev/null
+++ b/exports/nss_n2h.h
@@ -0,0 +1,149 @@
+/*
+ **************************************************************************
+ * 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_n2h.h
+ * NSS to HLOS interface definitions.
+ */
+
+/*
+ * TODO: Since this is the now the public header file for writting an
+ * IPv4 message, we need to convert the entire file to doxygen.
+ */
+
+#ifndef __NSS_N2H_H
+#define __NSS_N2H_H
+
+/*
+ * Private data structure for configure general configs
+ */
+struct nss_n2h_cfg_pvt {
+ struct semaphore sem; /* Semaphore structure */
+ struct completion complete; /* completion structure */
+ int current_value; /* valid entry */
+ int response; /* Response from FW */
+};
+
+/*
+ * Request/Response types
+ */
+enum nss_n2h_metadata_types {
+ NSS_RX_METADATA_TYPE_N2H_STATS_SYNC=0,
+ NSS_TX_METADATA_TYPE_N2H_RPS_CFG,
+ NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG,
+ NSS_METADATA_TYPE_N2H_MAX,
+};
+
+struct nss_n2h_rps {
+ uint32_t enable; /* Enable NSS RPS */
+};
+
+struct nss_n2h_empty_pool_buf {
+ uint32_t pool_size; /* Empty pool buf size */
+};
+
+/*
+ * NSS Pbuf mgr stats
+ */
+struct nss_n2h_pbuf_mgr_stats {
+ uint32_t pbuf_alloc_fails; /* Pbuf ocm alloc fail */
+ uint32_t pbuf_free_count; /* Pbuf ocm free count */
+ uint32_t pbuf_total_count; /* Pbuf ocm total count */
+};
+
+/*
+ * The NSS N2H statistics sync structure.
+ */
+struct nss_n2h_stats_sync {
+ struct nss_cmn_node_stats node_stats;
+ /* Common node stats for N2H */
+ uint32_t queue_dropped; /* Number of packets dropped because the PE queue is too full */
+ uint32_t total_ticks; /* Total clock ticks spend inside the PE */
+ uint32_t worst_case_ticks; /* Worst case iteration of the PE in ticks */
+ uint32_t iterations; /* Number of iterations around the PE */
+
+ struct nss_n2h_pbuf_mgr_stats pbuf_ocm_stats;
+ /* Pbuf OCM Stats */
+ struct nss_n2h_pbuf_mgr_stats pbuf_default_stats;
+ /* Pbuf Default Stats */
+
+ uint32_t payload_alloc_fails; /* Number of payload alloc failures */
+
+ uint32_t h2n_ctrl_pkts; /* Control packets received from HLOS */
+ uint32_t h2n_ctrl_bytes; /* Control bytes received from HLOS */
+ uint32_t n2h_ctrl_pkts; /* Control packets sent to HLOS */
+ uint32_t n2h_ctrl_bytes; /* Control bytes sent to HLOS */
+
+ uint32_t h2n_data_pkts; /* Data packets received from HLOS */
+ uint32_t h2n_data_bytes; /* Data bytes received from HLOS */
+ uint32_t n2h_data_pkts; /* Data packets sent to HLOS */
+ uint32_t n2h_data_bytes; /* Data bytes sent to HLOS */
+};
+
+/*
+ * Message structure to send/receive phys i/f commands
+ */
+struct nss_n2h_msg {
+ struct nss_cmn_msg cm; /* Message Header */
+ union {
+ struct nss_n2h_stats_sync stats_sync; /* Message: N2H stats sync */
+ struct nss_n2h_rps rps_cfg; /* Message: RPS configuration */
+ struct nss_n2h_empty_pool_buf empty_pool_buf_cfg;
+ /* Message: empty pool buf configuration */
+ } msg;
+};
+
+/**
+ * Callback to be called when IPv4 message is received
+ */
+typedef void (*nss_n2h_msg_callback_t)(void *app_data, struct nss_n2h_msg *msg);
+
+/*
+ * nss_n2h_tx_msg()
+ * API to send messaged to n2h package.
+ */
+extern nss_tx_status_t nss_n2h_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_n2h_msg *nnm);
+
+/*
+ * nss_n2h_tx()
+ * API to enable/disable Host RPS support in NSS
+ */
+extern nss_tx_status_t nss_n2h_tx(struct nss_ctx_instance *nss_ctx, uint32_t enable_rps);
+
+/*
+ * nss_n2h_empty_pool_buf_register_sysctl()
+ * API to register sysctl for empty pool buffer in n2h.
+ */
+extern void nss_n2h_empty_pool_buf_register_sysctl(void);
+
+/*
+ * nss_n2h_empty_pool_buf_unregister_sysctl()
+ * API to unregister sysctl for empty pool buffer in n2h.
+ */
+extern void nss_n2h_empty_pool_buf_unregister_sysctl(void);
+
+/*
+ * nss_n2h_msg_init()
+ * API to initialize the message for N2H package from Host to NSS
+ */
+typedef void (*nss_n2h_msg_callback_t)(void *app_data, struct nss_n2h_msg *msg);
+extern void nss_n2h_msg_init(struct nss_n2h_msg *nim, uint16_t if_num, uint32_t type, uint32_t len,
+ nss_n2h_msg_callback_t *cb, void *app_data);
+
+extern struct nss_ctx_instance *nss_ipv4_notify_register(nss_ipv4_msg_callback_t cb, void *app_data);
+#endif // __NSS_N2H_H
+
+
diff --git a/exports/nss_profiler.h b/exports/nss_profiler.h
index ab30425..3da9d54 100644
--- a/exports/nss_profiler.h
+++ b/exports/nss_profiler.h
@@ -14,6 +14,9 @@
**************************************************************************
*/
+#ifndef __NSS_PROFILER_H
+#define __NSS_PROFILER_H
+
/**
* nss_profiler.h
* NSS Profiler APIs
@@ -173,3 +176,4 @@
extern void nss_profiler_msg_init(struct nss_profiler_msg *npm, uint16_t if_num, uint32_t type, uint32_t len,
nss_profiler_callback_t *cb, void *app_data);
+#endif
diff --git a/nss_capwap.c b/nss_capwap.c
index 9965ec6..8f27ed4 100644
--- a/nss_capwap.c
+++ b/nss_capwap.c
@@ -148,6 +148,8 @@
stats->rx_segments += fstats->rx_segments;
stats->tx_segments += fstats->tx_segments;
stats->dtls_pkts += fstats->dtls_pkts;
+
+ stats->rx_dup_frag += fstats->rx_dup_frag;
stats->oversize_drops += fstats->oversize_drops;
stats->frag_timeout_drops += fstats->frag_timeout_drops;
stats->rx_queue_full_drops += fstats->rx_queue_full_drops;
@@ -157,6 +159,8 @@
stats->tx_queue_full_drops += fstats->tx_queue_full_drops;
stats->tx_mem_failure_drops += fstats->tx_mem_failure_drops;
+ stats->tx_dropped += fstats->tx_dropped;
+
/*
* add pnode stats now.
*/
@@ -548,6 +552,16 @@
EXPORT_SYMBOL(nss_capwap_get_ctx);
/*
+ * nss_capwap_get_max_buf_size()
+ * Return a CAPWAP NSS max_buf_size.
+ */
+uint32_t nss_capwap_get_max_buf_size(struct nss_ctx_instance *nss_ctx)
+{
+ return nss_core_get_max_buf_size(nss_ctx);
+}
+EXPORT_SYMBOL(nss_capwap_get_max_buf_size);
+
+/*
* nss_capwap_init()
* Initializes CAPWAP. Gets called from nss_init.c
*/
diff --git a/nss_connmgr_tun6rd.c b/nss_connmgr_tun6rd.c
deleted file mode 100644
index a6db78b..0000000
--- a/nss_connmgr_tun6rd.c
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_tun6rd.c
- *
- * This file is the NSS 6rd tunnel module
- * ------------------------REVISION HISTORY-----------------------------
- * Qualcomm Atheros 15/sep/2013 Created
- */
-
-#include <linux/types.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <net/ipv6.h>
-#include <net/ipip.h>
-#include <linux/if_arp.h>
-#include <nss_api_if.h>
-#include <nss_dynamic_interface.h>
-
-/*
- * NSS tun6rd debug macros
- */
-#if (NSS_TUN6RD_DEBUG_LEVEL < 1)
-#define nss_tun6rd_assert(fmt, args...)
-#else
-#define nss_tun6rd_assert(c) if (!(c)) { BUG_ON(!(c)); }
-#endif
-
-#if defined(CONFIG_DYNAMIC_DEBUG)
-/*
- * Compile messages for dynamic enable/disable
- */
-#define nss_tun6rd_warning(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define nss_tun6rd_info(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define nss_tun6rd_trace(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-
-/*
- * Statically compile messages at different levels
- */
-#if (NSS_TUN6RD_DEBUG_LEVEL < 2)
-#define nss_tun6rd_warning(s, ...)
-#else
-#define nss_tun6rd_warning(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
-
-#if (NSS_TUN6RD_DEBUG_LEVEL < 3)
-#define nss_tun6rd_info(s, ...)
-#else
-#define nss_tun6rd_info(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
-
-#if (NSS_TUN6RD_DEBUG_LEVEL < 4)
-#define nss_tun6rd_trace(s, ...)
-#else
-#define nss_tun6rd_trace(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
-#endif
-
-/*
- * 6rd tunnel stats
- */
-struct nss_tun6rd_stats {
- uint32_t rx_packets; /* Number of received packets */
- uint32_t rx_bytes; /* Number of received bytes */
- uint32_t tx_packets; /* Number of transmitted packets */
- uint32_t tx_bytes; /* Number of transmitted bytes */
-};
-
-/*
- * nss_tun6rd_update_dev_stats
- * Update the Dev stats received from NetAp
- */
-static void nss_tun6rd_update_dev_stats(struct net_device *dev,
- struct nss_tun6rd_sync_stats_msg *sync_stats)
-{
- struct nss_tun6rd_stats stats;
-
- stats.rx_packets = sync_stats->node_stats.rx_packets;
- stats.rx_bytes = sync_stats->node_stats.rx_bytes;
- stats.tx_packets = sync_stats->node_stats.tx_packets;
- stats.tx_bytes = sync_stats->node_stats.tx_bytes;
-
- ipip6_update_offload_stats(dev, (void *)&stats);
-}
-
-/*
- * nss_tun6rd_event_receive()
- * Event Callback to receive events from NSS
- */
-static void nss_tun6rd_event_receive(void *if_ctx, struct nss_tun6rd_msg *tnlmsg)
-{
- struct net_device *netdev = if_ctx;
-
- switch (tnlmsg->cm.type) {
- case NSS_TUN6RD_RX_STATS_SYNC:
- nss_tun6rd_update_dev_stats(netdev, (struct nss_tun6rd_sync_stats_msg *)&tnlmsg->msg.stats);
- break;
-
- default:
- nss_tun6rd_info("Unknown Event from NSS\n");
- break;
- }
-}
-
-/*
- * nss_tun6rd_exception()
- * Exception handler registered to NSS driver
- */
-static void nss_tun6rd_exception(struct net_device *dev, struct sk_buff *skb, __attribute__((unused)) struct napi_struct *napi)
-{
- const struct iphdr *iph;
-
- skb->dev = dev;
- nss_tun6rd_info("received - %d bytes name %s ver %x\n",
- skb->len,dev->name,skb->data[0]);
-
- iph = (const struct iphdr *)skb->data;
-
- /*
- * Packet after Decap/Encap Did not find the Rule.
- */
- if (iph->version != 4) {
- skb->protocol = htons(ETH_P_IPV6);
- } else {
- if (iph->protocol == IPPROTO_IPV6) {
- skb_pull(skb, sizeof(struct iphdr));
- skb->protocol = htons(ETH_P_IPV6);
- skb_reset_network_header(skb);
- skb->pkt_type = PACKET_HOST;
- skb->ip_summed = CHECKSUM_NONE;
- dev_queue_xmit(skb);
- return;
- }
- skb->protocol = htons(ETH_P_IP);
- }
-
- skb_reset_network_header(skb);
- skb->pkt_type = PACKET_HOST;
- skb->skb_iif = dev->ifindex;
- skb->ip_summed = CHECKSUM_NONE;
- netif_receive_skb(skb);
-}
-
-/*
- * nss_tun6rd_dev_up()
- * 6RD Tunnel device i/f up handler
- */
-static int nss_tun6rd_dev_up(struct net_device *netdev)
-{
- struct ip_tunnel *tunnel;
- struct ip_tunnel_6rd_parm *ip6rd;
- const struct iphdr *tiph;
- struct nss_tun6rd_msg tun6rdmsg;
- struct nss_tun6rd_attach_tunnel_msg *tun6rdcfg;
- uint32_t if_number;
- nss_tx_status_t status;
- struct nss_ctx_instance *nss_ctx;
- uint32_t features = 0; /* features denote the skb types supported by this interface */
-
- /*
- * Validate netdev for ipv6-in-ipv4 Tunnel
- */
- if (netdev->type != ARPHRD_SIT) {
- return NOTIFY_DONE;
- }
-
- tunnel = (struct ip_tunnel *)netdev_priv(netdev);
- ip6rd = &tunnel->ip6rd;
-
- /*
- * Valid 6rd Tunnel Check
- * 1. 6rd Prefix len should be non zero
- * 2. Relay prefix length should not be greater then 32
- * 3. To allow for stateless address auto-configuration on the CE LAN side,
- * 6rd delegated prefix SHOULD be /64 or shorter.
- */
- if ((ip6rd->prefixlen == 0 )
- || (ip6rd->relay_prefixlen > 32)
- || (ip6rd->prefixlen
- + (32 - ip6rd->relay_prefixlen) > 64)) {
-
- nss_tun6rd_warning("Invalid 6rd argument prefix len %d relayprefix len %d \n",
- ip6rd->prefixlen,ip6rd->relay_prefixlen);
- return NOTIFY_BAD;
- }
-
- nss_tun6rd_info("Valid 6rd Tunnel Prefix %x %x %x %x\n Prefix len %d relay_prefix %d relay_prefixlen %d \n",
- ip6rd->prefix.s6_addr32[0],ip6rd->prefix.s6_addr32[1],
- ip6rd->prefix.s6_addr32[2],ip6rd->prefix.s6_addr32[3],
- ip6rd->prefixlen, ip6rd->relay_prefix,
- ip6rd->relay_prefixlen);
-
- /*
- * Find the Tunnel device IP header info
- */
- tiph = &tunnel->parms.iph ;
- nss_tun6rd_trace("Tunnel Param srcaddr %x daddr %x ttl %d tos %x\n",
- tiph->saddr, tiph->daddr,tiph->ttl,tiph->tos);
-
- if (tiph->saddr == 0) {
- nss_tun6rd_warning("Tunnel src address not configured %x\n",
- tiph->saddr);
- return NOTIFY_BAD;
- }
-
- if_number = nss_dynamic_interface_alloc_node(NSS_DYNAMIC_INTERFACE_TYPE_TUN6RD);
- if (-1 == if_number) {
- nss_tun6rd_warning("Request interface number failed\n");
- return NOTIFY_BAD;
- }
-
- /*
- * Register 6rd tunnel with NSS
- */
- nss_ctx = nss_register_tun6rd_if(if_number,
- nss_tun6rd_exception,
- nss_tun6rd_event_receive,
- netdev,
- features);
- if (!nss_ctx) {
- status = nss_dynamic_interface_dealloc_node(if_number, NSS_DYNAMIC_INTERFACE_TYPE_TUN6RD);
- if (status != NSS_TX_SUCCESS) {
- nss_tun6rd_warning("Unable to dealloc the node[%d] in the NSS fw!\n", if_number);
- }
- nss_tun6rd_trace("nss_register_tun6rd_if failed \n");
- return NOTIFY_BAD;
- }
-
- /*
- * Prepare The Tunnel configuration parameter to send to nss
- */
- memset(&tun6rdmsg, 0, sizeof(struct nss_tun6rd_msg));
- tun6rdcfg = &tun6rdmsg.msg.tunnel;
- tun6rdcfg->prefixlen = ip6rd->prefixlen;
- tun6rdcfg->relay_prefix = ip6rd->relay_prefix;
- tun6rdcfg->relay_prefixlen = ip6rd->relay_prefixlen;
- tun6rdcfg->saddr = ntohl(tiph->saddr);
- tun6rdcfg->daddr = ntohl(tiph->daddr);
- tun6rdcfg->prefix[0] = ntohl(ip6rd->prefix.s6_addr32[0]);
- tun6rdcfg->prefix[1] = ntohl(ip6rd->prefix.s6_addr32[1]);
- tun6rdcfg->prefix[2] = ntohl(ip6rd->prefix.s6_addr32[2]);
- tun6rdcfg->prefix[3] = ntohl(ip6rd->prefix.s6_addr32[3]);
- tun6rdcfg->ttl = tiph->ttl;
- tun6rdcfg->tos = tiph->tos;
-
- nss_tun6rd_trace(" 6rd Tunnel info\n");
- nss_tun6rd_trace(" saddr %x daddr %d ttl %x tos %x\n",
- tiph->saddr, tiph->daddr, tiph->ttl, tiph->tos);
- nss_tun6rd_trace(" Prefix %x:%x:%x:%x Prefix len %d\n",
- ip6rd->prefix.s6_addr32[0], ip6rd->prefix.s6_addr32[1],
- ip6rd->prefix.s6_addr32[2], ip6rd->prefix.s6_addr32[3],
- ip6rd->prefixlen);
- nss_tun6rd_trace("Relay Prefix %x Len %d\n",
- ip6rd->relay_prefix, ip6rd->relay_prefixlen);
-
- nss_tun6rd_trace("Sending 6rd tunnel i/f up command to NSS %x\n",
- (int)nss_ctx);
-
- /*
- * Send 6rd Tunnel UP command to NSS
- */
- nss_tun6rd_msg_init(&tun6rdmsg, if_number, NSS_TUN6RD_ATTACH_PNODE,
- sizeof(struct nss_tun6rd_attach_tunnel_msg), NULL, NULL);
-
- status = nss_tun6rd_tx(nss_ctx, &tun6rdmsg);
- if (status != NSS_TX_SUCCESS) {
- nss_unregister_tun6rd_if(if_number);
- status = nss_dynamic_interface_dealloc_node(if_number, NSS_DYNAMIC_INTERFACE_TYPE_TUN6RD);
- if (status != NSS_TX_SUCCESS) {
- nss_tun6rd_warning("Unable to dealloc the node[%d] in the NSS fw!\n", if_number);
- }
- nss_tun6rd_warning("Tunnel up command error %d\n", status);
- return NOTIFY_BAD;
- }
-
- return NOTIFY_DONE;
-}
-
-/*
- * nss_tun6rd_dev_down()
- * 6RD Tunnel device i/f down handler
- */
-static int nss_tun6rd_dev_down(struct net_device *netdev)
-{
- struct ip_tunnel *tunnel;
- struct ip_tunnel_6rd_parm *ip6rd;
- int32_t if_number;
- nss_tx_status_t status;
-
- /*
- * Validate netdev for ipv6-in-ipv4 Tunnel
- */
- if (netdev->type != ARPHRD_SIT) {
- return NOTIFY_DONE;
- }
-
- /*
- * Check if tunnel 6rd is registered ?
- */
- if_number = nss_cmn_get_interface_number_by_dev(netdev);
- if (if_number < 0) {
- nss_tun6rd_warning("Net device:%p is not registered \n",netdev);
- return NOTIFY_BAD;
- }
-
-
- tunnel = (struct ip_tunnel *)netdev_priv(netdev);
- ip6rd = &tunnel->ip6rd;
-
- /*
- * Valid 6rd Tunnel Check
- */
- if ((ip6rd->prefixlen == 0 )
- || (ip6rd->relay_prefixlen > 32 )
- || (ip6rd->prefixlen
- + (32 - ip6rd->relay_prefixlen) > 64)) {
-
- nss_tun6rd_warning("Invalid 6rd argument prefix len %d relayprefix len %d \n",
- ip6rd->prefixlen,ip6rd->relay_prefixlen);
- return NOTIFY_BAD;
- }
-
- /*
- * Un-Register 6rd tunnel with NSS
- */
- nss_unregister_tun6rd_if(if_number);
- status = nss_dynamic_interface_dealloc_node(if_number, NSS_DYNAMIC_INTERFACE_TYPE_TUN6RD);
- if (status != NSS_TX_SUCCESS) {
- nss_tun6rd_warning("Dealloc node failure\n");
- return NOTIFY_BAD;
- }
-
- return NOTIFY_DONE;
-}
-
-
-/*
- * nss_tun6rd_dev_event()
- * Net device notifier for 6rd module
- */
-static int nss_tun6rd_dev_event(struct notifier_block *nb,
- unsigned long event, void *dev)
-{
- struct net_device *netdev = (struct net_device *)dev;
-
- switch (event) {
- case NETDEV_UP:
- nss_tun6rd_trace("NETDEV_UP: event %lu name %s\n", event, netdev->name);
- return nss_tun6rd_dev_up(netdev);
-
- case NETDEV_DOWN:
- nss_tun6rd_trace("NETDEV_DOWN: event %lu name %s\n", event, netdev->name);
- return nss_tun6rd_dev_down(netdev);
-
- default:
- nss_tun6rd_trace("Unhandled notifier event %lu name %s\n",event, netdev->name);
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-/*
- * Linux Net device Notifier
- */
-struct notifier_block nss_tun6rd_notifier = {
- .notifier_call = nss_tun6rd_dev_event,
-};
-
-
-/*
- * nss_tun6rd_init_module()
- * Tunnel 6rd module init function
- */
-int __init nss_tun6rd_init_module(void)
-{
- nss_tun6rd_info("module (platform - IPQ806x , Build - %s:%s) loaded\n",
- __DATE__, __TIME__);
-
- register_netdevice_notifier(&nss_tun6rd_notifier);
- nss_tun6rd_trace("Netdev Notifier registerd \n");
-
- return 0;
-}
-
-/*
- * nss_tun6rd_exit_module()
- * Tunnel 6rd module exit function
- */
-void __exit nss_tun6rd_exit_module(void)
-{
- unregister_netdevice_notifier(&nss_tun6rd_notifier);
- nss_tun6rd_info("module unloaded\n");
-}
-
-module_init(nss_tun6rd_init_module);
-module_exit(nss_tun6rd_exit_module);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("NSS tun6rd offload manager");
diff --git a/nss_connmgr_tunipip6.c b/nss_connmgr_tunipip6.c
deleted file mode 100644
index 072ef80..0000000
--- a/nss_connmgr_tunipip6.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_tunipip6.c
- *
- * This file is the NSS DS-lit and IPP6 tunnel module
- * ------------------------REVISION HISTORY-----------------------------
- * Qualcomm Atheros 15/sep/2013 Created
- */
-
-#include <linux/types.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <net/ipv6.h>
-#include <net/ipip.h>
-#include <net/ip6_tunnel.h>
-#include <linux/if_arp.h>
-#include <nss_api_if.h>
-
-/*
- * NSS tunipip6 debug macros
- */
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 1)
-#define nss_tunipip6_assert(fmt, args...)
-#else
-#define nss_tunipip6_assert(c) if (!(c)) { BUG_ON(!(c)); }
-#endif
-
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 2)
-#define nss_tunipip6_error(fmt, args...)
-#else
-#define nss_tunipip6_error(fmt, args...) printk(KERN_WARNING "nss tunipip6:"fmt, ##args)
-#endif
-
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 3)
-#define nss_tunipip6_warning(fmt, args...)
-#else
-#define nss_tunipip6_warning(fmt, args...) printk(KERN_WARNING "nss tunipip6:"fmt, ##args)
-#endif
-
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 4)
-#define nss_tunipip6_info(fmt, args...)
-#else
-#define nss_tunipip6_info(fmt, args...) printk(KERN_INFO "nss tunipip6 :"fmt, ##args)
-#endif
-
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 5)
-#define nss_tunipip6_trace(fmt, args...)
-#else
-#define nss_tunipip6_trace(fmt, args...) printk(KERN_DEBUG "nss tunipip6 :"fmt, ##args)
-#endif
-
-void nss_tunipip6_exception(struct net_device *netdev, struct sk_buff *skb, __attribute__((unused)) struct napi_struct *napi);
-void nss_tunipip6_event_receive(void *ctx, struct nss_tunipip6_msg *msg);
-
-/*
- * nss_tunipip6_tunnel
- * DS-lite and ipip 6tunnel host instance
- */
-struct nss_tunipip6_tunnel{
- struct nss_ctx_instance *nss_ctx;
- uint32_t if_num;
- struct net_device *netdev;
- uint32_t device_up;
- uint32_t features; /* The skb types supported by this interface */
-};
-
-/*
- * tunipip6 stats structure
- */
-struct nss_tunipip6_stats {
- uint32_t rx_packets; /* Number of received packets */
- uint32_t rx_bytes; /* Number of received bytes */
- uint32_t tx_packets; /* Number of transmitted packets */
- uint32_t tx_bytes; /* Number of transmitted bytes */
-};
-
-struct nss_tunipip6_tunnel g_tunipip6;
-
-/*
- * Internal function
- */
-static int
-nss_tunipip6_dev_event(struct notifier_block *nb,
- unsigned long event,
- void *dev);
-
-/*
- * Linux Net device Notifier
- */
-struct notifier_block nss_tunipip6_notifier = {
- .notifier_call = nss_tunipip6_dev_event,
-};
-
-/*
- * nss_tunipip6_dev_up()
- * IPIP6 Tunnel device i/f up handler
- */
-void nss_tunipip6_dev_up( struct net_device * netdev)
-{
- struct ip6_tnl *tunnel;
- struct nss_tunipip6_msg tnlmsg;
- struct nss_tunipip6_create_msg *tnlcfg;
- struct flowi6 *fl6;
- nss_tx_status_t status;
-
- /*
- * Validate netdev for ipv6-in-ipv4 Tunnel
- */
- if (netdev->type != ARPHRD_TUNNEL6 ) {
- return;
- }
-
- tunnel = (struct ip6_tnl *)netdev_priv(netdev);
-
- /*
- * Find he Tunnel device flow information
- */
-
- fl6 = &tunnel->fl.u.ip6;
-
- nss_tunipip6_trace(" Tunnel Param srcaddr %x:%x:%x:%x daddr %x:%x:%x:%x \n",
- fl6->saddr.s6_addr32[0], fl6->saddr.s6_addr32[1],
- fl6->saddr.s6_addr32[2], fl6->saddr.s6_addr32[3],
- fl6->daddr.s6_addr32[0], fl6->daddr.s6_addr32[1],
- fl6->daddr.s6_addr32[2], fl6->daddr.s6_addr32[3] );
- nss_tunipip6_trace(" hop limit %d \n", tunnel->parms.hop_limit);
- nss_tunipip6_trace(" tunnel param flag %x fl6.flowlabel %x \n", tunnel->parms.flags, fl6->flowlabel);
-
- /*
- * Register ipip6 tunnel with NSS
- */
- g_tunipip6.nss_ctx = nss_register_tunipip6_if(g_tunipip6.if_num,
- nss_tunipip6_exception,
- nss_tunipip6_event_receive,
- netdev,
- g_tunipip6.features);
- if (g_tunipip6.nss_ctx == NULL) {
- nss_tunipip6_trace("nss_register_tunipip6_if Failed \n");
- return;
- } else {
- nss_tunipip6_trace("nss_register_tunipip6_if Success \n");
- }
-
- /*
- *Prepare The Tunnel configuration parameter to send to nss
- */
- memset(&tnlmsg, 0, sizeof(struct nss_tunipip6_msg));
- tnlcfg = &tnlmsg.msg.tunipip6_create;
-
- tnlcfg->saddr[0] = ntohl(fl6->saddr.s6_addr32[0]);
- tnlcfg->saddr[1] = ntohl(fl6->saddr.s6_addr32[1]);
- tnlcfg->saddr[2] = ntohl(fl6->saddr.s6_addr32[2]);
- tnlcfg->saddr[3] = ntohl(fl6->saddr.s6_addr32[3]);
- tnlcfg->daddr[0] = ntohl(fl6->daddr.s6_addr32[0]);
- tnlcfg->daddr[1] = ntohl(fl6->daddr.s6_addr32[1]);
- tnlcfg->daddr[2] = ntohl(fl6->daddr.s6_addr32[2]);
- tnlcfg->daddr[3] = ntohl(fl6->daddr.s6_addr32[3]);
- tnlcfg->hop_limit = tunnel->parms.hop_limit;
- tnlcfg->flags = ntohl(tunnel->parms.flags);
- tnlcfg->flowlabel = fl6->flowlabel; /*flow Label In kernel is stored in big endian format*/
- nss_tunipip6_trace(" Tunnel Param srcaddr %x:%x:%x:%x daddr %x:%x:%x:%x \n",
- tnlcfg->saddr[0], tnlcfg->saddr[1],
- tnlcfg->saddr[2], tnlcfg->saddr[3],
- tnlcfg->daddr[0], tnlcfg->daddr[1],
- tnlcfg->daddr[2], tnlcfg->daddr[3] );
-
-
- nss_tunipip6_trace("Sending IPIP6 tunnel i/f up command to NSS %x \n",
- (int)g_tunipip6.nss_ctx);
-
- /*
- * Send IPIP6 Tunnel UP command to NSS
- */
- nss_tunipip6_msg_init(&tnlmsg, NSS_TUNIPIP6_INTERFACE, NSS_TUNIPIP6_TX_IF_CREATE,
- sizeof(struct nss_tunipip6_create_msg), NULL, NULL);
-
- status = nss_tunipip6_tx(g_tunipip6.nss_ctx, &tnlmsg);
- if (status != NSS_TX_SUCCESS) {
- nss_tunipip6_error("Tunnel up command error %d \n", status);
- return;
- }
-
- g_tunipip6.device_up = 1;
-}
-
-/*
- * nss_tunipip6_dev_down()
- * IPP6 Tunnel device i/f down handler
- */
-void nss_tunipip6_dev_down( struct net_device * netdev)
-{
- struct nss_tunipip6_msg tnlmsg;
- struct nss_tunipip6_destroy_msg *tnlcfg;
- nss_tx_status_t status;
-
- /*
- * Check if tunnel ipip6 is registered ?
- */
- if(g_tunipip6.nss_ctx == NULL){
- return;
- }
-
- /*
- * Validate netdev for ipv6-in-ipv4 Tunnel
- */
- if (netdev->type != ARPHRD_TUNNEL6) {
- return;
- }
-
- /*
- * TODO: Strick check required if its the same tunnel
- * registerd with us
- */
-
- memset(&tnlmsg, 0, sizeof(struct nss_tunipip6_msg));
- tnlcfg = &tnlmsg.msg.tunipip6_destroy;
-
- nss_tunipip6_trace("Sending Tunnel ipip6 Down command %x \n",g_tunipip6.if_num);
-
- /*
- * Send IPIP6 Tunnel DOWN command to NSS
- */
- nss_tunipip6_msg_init(&tnlmsg, NSS_TUNIPIP6_INTERFACE, NSS_TUNIPIP6_TX_IF_DESTROY,
- sizeof(struct nss_tunipip6_destroy_msg), NULL, NULL);
-
- status = nss_tunipip6_tx(g_tunipip6.nss_ctx, &tnlmsg);
- if (status != NSS_TX_SUCCESS) {
- nss_tunipip6_error("Tunnel down command error %d \n", status);
- return;
- }
-
- /*
- * Un-Register IPIP6 tunnel with NSS
- */
- nss_unregister_tunipip6_if(g_tunipip6.if_num);
- g_tunipip6.nss_ctx = NULL;
- g_tunipip6.device_up = 0;
-}
-
-/*
- * nss_tun6rd_dev_event()
- * Net device notifier for ipip6 module
- */
-static int nss_tunipip6_dev_event(struct notifier_block *nb,
- unsigned long event, void *dev)
-{
- struct net_device *netdev = (struct net_device *)dev;
-
- nss_tunipip6_trace("%s\n",__FUNCTION__);
- switch (event) {
- case NETDEV_UP:
- nss_tunipip6_trace(" NETDEV_UP :event %lu name %s \n",
- event,netdev->name);
- nss_tunipip6_dev_up(netdev);
- break;
-
- case NETDEV_DOWN:
- nss_tunipip6_trace(" NETDEV_DOWN :event %lu name %s \n",
- event,netdev->name);
- nss_tunipip6_dev_down(netdev);
- break;
-
- default:
- nss_tunipip6_trace("Unhandled notifier dev %s event %x \n",
- netdev->name,(int)event);
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-/*
- * nss_tunipip6_exception()
- * Exception handler registered to NSS driver
- */
-void nss_tunipip6_exception(struct net_device *dev, struct sk_buff *skb, __attribute__((unused)) struct napi_struct *napi)
-{
- const struct iphdr *iph;
-
- skb->dev = dev;
- nss_tunipip6_info("received - %d bytes name %s ver %x \n",
- skb->len,dev->name,skb->data[0]);
-
- iph = (const struct iphdr *)skb->data;
-
- /*
- *Packet after Decap/Encap Did not find the Rule.
- */
- if (iph->version == 4) {
- skb->protocol = htons(ETH_P_IP);
- } else {
- skb->protocol = htons(ETH_P_IPV6);
- }
-
- skb_reset_network_header(skb);
- skb->pkt_type = PACKET_HOST;
- skb->skb_iif = dev->ifindex;
- skb->ip_summed = CHECKSUM_NONE;
- netif_receive_skb(skb);
-}
-
-/*
- * nss_tunipip6_update_dev_stats
- * Update the Dev stats received from NetAp
- */
-static void nss_tunipip6_update_dev_stats(struct net_device *dev,
- struct nss_tunipip6_stats_sync_msg *sync_stats)
-{
- void *ptr;
- struct nss_tunipip6_stats stats;
-
- stats.rx_packets = sync_stats->node_stats.rx_packets;
- stats.rx_bytes = sync_stats->node_stats.rx_bytes;
- stats.tx_packets = sync_stats->node_stats.tx_packets;
- stats.tx_bytes = sync_stats->node_stats.tx_bytes;
-
- ptr = (void *)&stats;
- ip6_update_offload_stats(dev, ptr);
-
-}
-
-/**
- * @brief Event Callback to receive events from NSS
- * @param[in] pointer to net device context
- * @param[in] event type
- * @param[in] pointer to buffer
- * @param[in] length of buffer
- * @return Returns void
- */
-void nss_tunipip6_event_receive(void *if_ctx, struct nss_tunipip6_msg *tnlmsg)
-{
- struct net_device *netdev = NULL;
- netdev = (struct net_device *)if_ctx;
-
- switch (tnlmsg->cm.type) {
- case NSS_TUNIPIP6_RX_STATS_SYNC:
- nss_tunipip6_update_dev_stats(netdev, (struct nss_tunipip6_stats_sync_msg *)&tnlmsg->msg.stats_sync );
- break;
-
- default:
- nss_tunipip6_info("%s: Unknown Event from NSS",
- __FUNCTION__);
- break;
- }
-}
-
-/*
- * nss_tunipip6_init_module()
- * Tunnel ipip6 module init function
- */
-int __init nss_tunipip6_init_module(void)
-{
- nss_tunipip6_info("module (platform - IPQ806x , Build - %s:%s) loaded\n",
- __DATE__, __TIME__);
-
- register_netdevice_notifier(&nss_tunipip6_notifier);
- nss_tunipip6_trace("Netdev Notifier registerd \n");
-
- g_tunipip6.if_num = NSS_TUNIPIP6_INTERFACE;
- g_tunipip6.netdev = NULL;
- g_tunipip6.device_up = 0;
- g_tunipip6.nss_ctx = NULL;
- g_tunipip6.features = 0;
-
- return 0;
-}
-
-/*
- * nss_tunipip6_exit_module()
- * Tunnel ipip6 module exit function
- */
-void __exit nss_tunipip6_exit_module(void)
-{
-
- unregister_netdevice_notifier(&nss_tunipip6_notifier);
- nss_tunipip6_info("module unloaded\n");
-}
-
-module_init(nss_tunipip6_init_module);
-module_exit(nss_tunipip6_exit_module);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("NSS tunipip6 offload manager");
diff --git a/nss_core.c b/nss_core.c
index a0aebaa..bafdcc4 100755
--- a/nss_core.c
+++ b/nss_core.c
@@ -49,6 +49,11 @@
static struct nss_rx_cb_list nss_rx_interface_handlers[NSS_MAX_NET_INTERFACES];
+#ifdef CONFIG_DEBUG_KMEMLEAK
+struct sk_buff_head nss_skb_list;
+#endif
+
+
/*
* nss_core_set_jumbo_mru()
* Set the jumbo_mru to the specified value
@@ -301,6 +306,18 @@
nss_phys_if_rx_callback_t cb;
struct nss_subsystem_dataplane_register *subsys_dp_reg = &nss_top->subsys_dp_register[interface_num];
+
+#ifdef CONFIG_DEBUG_KMEMLEAK
+ /*
+ * Tracking for kmemleak: Remove the skb from the nss_skb_list
+ */
+ spin_lock_bh(&nss_skb_list.lock);
+ __skb_unlink(nbuf, &nss_skb_list);
+ spin_unlock_bh(&nss_skb_list.lock);
+#endif
+
+ NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+
switch (buffer_type) {
case N2H_BUFFER_SHAPER_BOUNCED_INTERFACE:
{
@@ -685,7 +702,7 @@
* nss_core_handle_linear_skb()
* Handler for processing linear skbs.
*/
-static inline bool nss_core_handle_linear_skb(struct sk_buff **nbuf_ptr, struct sk_buff **head_ptr,
+static inline bool nss_core_handle_linear_skb(struct nss_ctx_instance *nss_ctx, struct sk_buff **nbuf_ptr, struct sk_buff **head_ptr,
struct sk_buff **tail_ptr, struct n2h_descriptor *desc)
{
uint16_t bit_flags = desc->bit_flags;
@@ -720,6 +737,7 @@
* NSS should playaround with data area and should not
* touch HEADROOM area
*/
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_SIMPLE]);
return true;
}
@@ -815,7 +833,7 @@
*nbuf_ptr = head;
*head_ptr = NULL;
*tail_ptr = NULL;
-
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_SKB_FRAGLIST]);
return true;
}
@@ -878,9 +896,7 @@
opaque = desc->opaque;
bit_flags = desc->bit_flags;
if (unlikely((buffer_type == N2H_BUFFER_CRYPTO_RESP))) {
- NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[NSS_STATS_DRV_RX_CRYPTO_RESP]);
-
-
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_CRYPTO_RESP]);
/*
* This is a crypto buffer hence send it to crypto driver
*
@@ -901,6 +917,7 @@
* Invalid opaque pointer
*/
nss_dump_desc(nss_ctx, desc);
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_BAD_DESCRIPTOR]);
goto next;
}
@@ -949,6 +966,17 @@
if (unlikely(head)) {
nss_warning("%p: we should not have an incomplete paged skb while"
" constructing a linear skb %p", nbuf, head);
+
+#ifdef CONFIG_DEBUG_KMEMLEAK
+ /*
+ * Tracking for kmemleak: Remove the skb from the nss_skb_list
+ */
+ spin_lock_bh(&nss_skb_list.lock);
+ __skb_unlink(head, &nss_skb_list);
+ spin_unlock_bh(&nss_skb_list.lock);
+#endif
+
+ NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
dev_kfree_skb_any(head);
head = NULL;
goto next;
@@ -957,7 +985,7 @@
if (!nss_core_handle_nr_frag_skb(&nbuf, &jumbo_start, desc, buffer_type)) {
goto next;
}
-
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_NR_FRAGS]);
goto consume;
}
@@ -968,6 +996,17 @@
if (unlikely(jumbo_start)) {
nss_warning("%p: we should not have an incomplete linear skb while"
" constructing a paged skb %p", nbuf, jumbo_start);
+
+#ifdef CONFIG_DEBUG_KMEMLEAK
+ /*
+ * Tracking for kmemleak: Remove the skb from the nss_skb_list
+ */
+ spin_lock_bh(&nss_skb_list.lock);
+ __skb_unlink(jumbo_start, &nss_skb_list);
+ spin_unlock_bh(&nss_skb_list.lock);
+#endif
+
+ NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
dev_kfree_skb_any(jumbo_start);
jumbo_start = NULL;
goto next;
@@ -977,7 +1016,7 @@
* This is a simple linear skb. Use the the linear skb
* handler to process it.
*/
- if (!nss_core_handle_linear_skb(&nbuf, &head, &tail, desc)) {
+ if (!nss_core_handle_linear_skb(nss_ctx, &nbuf, &head, &tail, desc)) {
goto next;
}
@@ -1241,6 +1280,16 @@
break;
}
+#ifdef CONFIG_DEBUG_KMEMLEAK
+ /*
+ * Tracking for kmemleak because skbs dont have references.
+ */
+ spin_lock_bh(&nss_skb_list.lock);
+ __skb_queue_head(&nss_skb_list, nbuf);
+ spin_unlock_bh(&nss_skb_list.lock);
+#endif
+
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
desc->opaque = (uint32_t)nbuf;
desc->buffer = buffer;
desc->buffer_type = H2N_BUFFER_EMPTY;
@@ -1537,6 +1586,7 @@
(uint32_t)nbuf, (uint16_t)(nbuf->data - nbuf->head), nbuf->len,
(uint16_t)(nbuf->end - nbuf->head), (uint32_t)nbuf->priority, mss, bit_flags);
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
if (unlikely(!NSS_IS_IF_TYPE(VIRTUAL, if_num))) {
if (likely(nbuf->destructor == NULL)) {
if (likely(skb_recycle_check(nbuf, nss_ctx->max_buf_size))) {
@@ -1546,10 +1596,13 @@
}
}
}
-
+#endif
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_SIMPLE]);
return 1;
}
+//Note to Thomas: Linux has support for atomic_inc() on a 64 bit value. Hint, use iot
+
/*
* nss_core_send_buffer_nr_frags()
* Sends frags array (NETIF_F_SG) to NSS FW
@@ -1619,7 +1672,7 @@
desc->bit_flags |= H2N_BIT_FLAG_LAST_SEGMENT;
desc->bit_flags &= ~(H2N_BIT_FLAG_DISCARD);
desc->opaque = (uint32_t)nbuf;
-
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_NR_FRAGS]);
return i+1;
}
@@ -1700,7 +1753,7 @@
desc->bit_flags |= H2N_BIT_FLAG_LAST_SEGMENT;
desc->bit_flags &= ~(H2N_BIT_FLAG_DISCARD);
desc->opaque = (uint32_t)nbuf;
-
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_FRAGLIST]);
return i+1;
}
@@ -1889,6 +1942,16 @@
h2n_desc_ring->hlos_index = hlos_index;
if_map->h2n_hlos_index[qid] = hlos_index;
+#ifdef CONFIG_DEBUG_KMEMLEAK
+ /*
+ * Tracking for kmemleak because skbs dont have references.
+ */
+ spin_lock_bh(&nss_skb_list.lock);
+ __skb_queue_head(&nss_skb_list, nbuf);
+ spin_unlock_bh(&nss_skb_list.lock);
+#endif
+
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
spin_unlock_bh(&h2n_desc_ring->lock);
return NSS_CORE_STATUS_SUCCESS;
}
diff --git a/nss_core.h b/nss_core.h
index fe2ab82..d088084 100755
--- a/nss_core.h
+++ b/nss_core.h
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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.
@@ -23,6 +23,7 @@
#define __NSS_CORE_H
#include <linux/kernel.h>
+#include <linux/version.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/spinlock.h>
@@ -87,6 +88,7 @@
#if (NSS_PKT_STATS_ENABLED == 1)
#define NSS_PKT_STATS_INCREMENT(nss_ctx, x) nss_pkt_stats_increment((nss_ctx), (x))
+#define NSS_PKT_STATS_DECREMENT(nss_ctx, x) nss_pkt_stats_decrement((nss_ctx), (x))
#else
#define NSS_PKT_STATS_INCREMENT(nss_ctx, x)
#endif
@@ -182,6 +184,20 @@
#define NSS_FREQ_733_MIN 0x10000 /* Instructions Per ms Min */
#define NSS_FREQ_733_MAX 0x50000 /* Instructions Per ms Max */
+#if (NSS_DT_SUPPORT == 1)
+#define NSSTCM_FREQ 400000000 /* NSS TCM Frequency in Hz */
+
+/* NSS Clock names */
+#define NSS_TCM_SRC_CLK "nss_tcm_src"
+#define NSS_TCM_CLK "nss_tcm_clk"
+
+/* NSS core reset/clamp names */
+#define NSS_CORE_CLK_RST_CLAMP "clkrst_clamp"
+#define NSS_CORE_CLAMP "clamp"
+#define NSS_CORE_AHB_RESET "ahb"
+#define NSS_CORE_AXI_RESET "axi"
+#endif
+
/*
* IPV4 node statistics
*
@@ -280,18 +296,26 @@
*/
enum nss_stats_drv {
NSS_STATS_DRV_NBUF_ALLOC_FAILS = 0, /* NBUF allocation errors */
- NSS_STATS_DRV_TX_QUEUE_FULL_0, /* Tx queue full for Core 0*/
- NSS_STATS_DRV_TX_QUEUE_FULL_1, /* Tx queue full for Core 1*/
- NSS_STATS_DRV_TX_EMPTY, /* H2N Empty buffers */
- NSS_STATS_DRV_TX_PACKET, /* H2N Data packets */
- NSS_STATS_DRV_TX_CMD_REQ, /* H2N Control packets */
- NSS_STATS_DRV_TX_CRYPTO_REQ, /* H2N Crypto requests */
- NSS_STATS_DRV_RX_EMPTY, /* N2H Empty buffers */
- NSS_STATS_DRV_RX_PACKET, /* N2H Data packets */
- NSS_STATS_DRV_RX_CMD_RESP, /* N2H Command responses */
- NSS_STATS_DRV_RX_STATUS, /* N2H Status packets */
- NSS_STATS_DRV_RX_CRYPTO_RESP, /* N2H Crypto responses */
- NSS_STATS_DRV_RX_VIRTUAL, /* N2H Virtual packets */
+ NSS_STATS_DRV_TX_QUEUE_FULL_0, /* Tx queue full for Core 0*/
+ NSS_STATS_DRV_TX_QUEUE_FULL_1, /* Tx queue full for Core 1*/
+ NSS_STATS_DRV_TX_EMPTY, /* H2N Empty buffers */
+ NSS_STATS_DRV_TX_PACKET, /* H2N Data packets */
+ NSS_STATS_DRV_TX_CMD_REQ, /* H2N Control packets */
+ NSS_STATS_DRV_TX_CRYPTO_REQ, /* H2N Crypto requests */
+ NSS_STATS_DRV_RX_EMPTY, /* N2H Empty buffers */
+ NSS_STATS_DRV_RX_PACKET, /* N2H Data packets */
+ NSS_STATS_DRV_RX_CMD_RESP, /* N2H Command responses */
+ NSS_STATS_DRV_RX_STATUS, /* N2H Status packets */
+ NSS_STATS_DRV_RX_CRYPTO_RESP, /* N2H Crypto responses */
+ NSS_STATS_DRV_RX_VIRTUAL, /* N2H Virtual packets */
+ NSS_STATS_DRV_TX_SIMPLE, /* H2N Simple SKB Packets */
+ NSS_STATS_DRV_TX_NR_FRAGS, /* H2N NR Frags SKB Packets */
+ NSS_STATS_DRV_TX_FRAGLIST, /* H2N Fraglist SKB Packets */
+ NSS_STATS_DRV_RX_SIMPLE, /* N2H Simple SKB Packets */
+ NSS_STATS_DRV_RX_NR_FRAGS, /* N2H NR Frags SKB Packets */
+ NSS_STATS_DRV_RX_SKB_FRAGLIST, /* N2H Fraglist SKB Packets */
+ NSS_STATS_DRV_RX_BAD_DESCRIPTOR, /* N2H Bad descriptor reads */
+ NSS_STATS_DRV_NSS_SKB_COUNT,
NSS_STATS_DRV_MAX,
};
@@ -386,6 +410,17 @@
NSS_STATS_N2H_PAYLOAD_ALLOC_FAILS,
/* Number of pbuf allocations that have failed because there were no free payloads */
+
+ NSS_STATS_N2H_H2N_CONTROL_PACKETS, /* Control packets received from HLOS */
+ NSS_STATS_N2H_H2N_CONTROL_BYTES, /* Control bytes received from HLOS */
+ NSS_STATS_N2H_N2H_CONTROL_PACKETS, /* Control packets sent to HLOS */
+ NSS_STATS_N2H_N2H_CONTROL_BYTES, /* Control bytes sent to HLOS */
+
+ NSS_STATS_N2H_H2N_DATA_PACKETS, /* Data packets received from HLOS */
+ NSS_STATS_N2H_H2N_DATA_BYTES, /* Data bytes received from HLOS */
+ NSS_STATS_N2H_N2H_DATA_PACKETS, /* Data packets sent to HLOS */
+ NSS_STATS_N2H_N2H_DATA_BYTES, /* Data bytes sent to HLOS */
+
NSS_STATS_N2H_MAX,
};
@@ -604,7 +639,7 @@
struct nss_shaper_bounce_registrant bounce_bridge_registrants[NSS_MAX_NET_INTERFACES];
/* Registrants for bridge shaper bounce operations */
nss_lag_event_callback_t lag_event_callback;
-
+ /* Registrants for lag operations */
uint32_t dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_MAX];
/*
@@ -648,6 +683,11 @@
/* IPv6 protocol exception events per interface */
uint64_t stats_if_exception_pppoe[NSS_MAX_PHYSICAL_INTERFACES][NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_PPPOE_EXCEPTION_EVENT_MAX];
/* PPPoE exception events for per session on per interface */
+#if (NSS_DT_SUPPORT == 1)
+ void *nss_fpb_base; /* Virtual address of FPB base */
+ bool nss_hal_common_init_done;
+#endif
+
/*
* TODO: Review and update following fields
*/
@@ -664,6 +704,17 @@
*stat = *stat + 1;
spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
}
+
+/*
+ * nss_pkt_stats_increment()
+ */
+static inline void nss_pkt_stats_decrement(struct nss_ctx_instance *nss_ctx, uint64_t *stat)
+{
+ spin_lock_bh(&nss_ctx->nss_top->stats_lock);
+ *stat = *stat - 1;
+ spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
+}
+
#endif
/*
@@ -723,6 +774,46 @@
uint32_t initialized; /* Flag to check for adequate initial samples */
};
+
+#if (NSS_DT_SUPPORT == 1)
+/*
+ * nss_feature_enabled
+ */
+enum nss_feature_enabled {
+ NSS_FEATURE_NOT_ENABLED = 0, /* Feature is not enabled on this core */
+ NSS_FEATURE_ENABLED, /* Feature is enabled on this core */
+};
+
+/*
+ * nss_platform_data
+ * Platform data per core
+ */
+struct nss_platform_data {
+ uint32_t id; /* NSS core ID */
+ uint32_t num_irq; /* No. of interrupts supported per core */
+ uint32_t irq[2]; /* IRQ numbers per interrupt */
+ uint32_t nmap; /* Virtual address of NSS CSM space */
+ uint32_t vmap; /* Virtual address of NSS virtual register map */
+ uint32_t nphys; /* Physical address of NSS CSM space */
+ uint32_t vphys; /* Physical address of NSS virtual register map */
+ uint32_t rst_addr; /* Reset address of NSS core */
+ uint32_t load_addr; /* Load address of NSS firmware */
+ enum nss_feature_enabled turbo_frequency; /* Does this core support turbo frequencies */
+ enum nss_feature_enabled ipv4_enabled; /* Does this core handle IPv4? */
+ enum nss_feature_enabled ipv4_reasm_enabled; /* Does this core handle IPv4? */
+ enum nss_feature_enabled ipv6_enabled; /* Does this core handle IPv6? */
+ enum nss_feature_enabled l2switch_enabled; /* Does this core handle L2 switch? */
+ enum nss_feature_enabled crypto_enabled; /* Does this core handle crypto? */
+ enum nss_feature_enabled ipsec_enabled; /* Does this core handle IPsec? */
+ enum nss_feature_enabled wlan_enabled; /* Does this core handle WLAN 11ac? */
+ enum nss_feature_enabled tun6rd_enabled; /* Does this core handle 6rd 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 ? */
+ enum nss_feature_enabled shaping_enabled; /* Does this core handle shaping ? */
+ enum nss_feature_enabled gmac_enabled[4]; /* Does this core handle GMACs? */
+};
+#endif
+
/*
* nss_core_log_msg_failures()
* Driver function for logging failed messages.
@@ -766,6 +857,12 @@
extern uint32_t nss_core_register_handler(uint32_t interface, nss_core_rx_callback_t cb, void *app_data);
extern uint32_t nss_core_unregister_handler(uint32_t interface);
+static inline uint32_t nss_core_get_max_buf_size(struct nss_ctx_instance *nss_ctx)
+{
+ return nss_ctx->max_buf_size;
+}
+
+
/*
* APIs provided by nss_tx_rx.c
*/
diff --git a/nss_data_plane.c b/nss_data_plane.c
index 093385a..52e39d4 100644
--- a/nss_data_plane.c
+++ b/nss_data_plane.c
@@ -26,7 +26,7 @@
* nss_data_plane_open()
* Called by gmac to notify open to nss-fw
*/
-static nss_gmac_status_t nss_data_plane_open(void *arg, uint32_t tx_desc_ring, uint32_t rx_desc_ring, uint32_t mode)
+static int nss_data_plane_open(void *arg, uint32_t tx_desc_ring, uint32_t rx_desc_ring, uint32_t mode)
{
struct nss_data_plane_param *dp = (struct nss_data_plane_param *)arg;
@@ -44,7 +44,7 @@
* nss_data_plane_close()
* Called by gmac to notify close to nss-fw
*/
-static nss_gmac_status_t nss_data_plane_close(void *arg)
+static int nss_data_plane_close(void *arg)
{
/*
* We don't actually do synopsys gmac close in fw, just return success
@@ -56,7 +56,7 @@
* nss_data_plane_link_state()
* Called by gmac to notify link state change to nss-fw
*/
-static nss_gmac_status_t nss_data_plane_link_state(void *arg, uint32_t link_state)
+static int nss_data_plane_link_state(void *arg, uint32_t link_state)
{
struct nss_data_plane_param *dp = (struct nss_data_plane_param *)arg;
@@ -67,7 +67,7 @@
* nss_data_plane_mac_addr()
* Called by gmac to set mac address
*/
-static nss_gmac_status_t nss_data_plane_mac_addr(void *arg, uint8_t *addr)
+static int nss_data_plane_mac_addr(void *arg, uint8_t *addr)
{
struct nss_data_plane_param *dp = (struct nss_data_plane_param *)arg;
@@ -78,7 +78,7 @@
* nss_data_plane_change_mtu()
* Called by gmac to change mtu of a gmac
*/
-static nss_gmac_status_t nss_data_plane_change_mtu(void *arg, uint32_t mtu)
+static int nss_data_plane_change_mtu(void *arg, uint32_t mtu)
{
struct nss_data_plane_param *dp = (struct nss_data_plane_param *)arg;
@@ -89,7 +89,7 @@
* nss_data_plane_buf()
* Called by gmac to pass a sk_buff for xmit
*/
-static nss_gmac_status_t nss_data_plane_buf(void *arg, struct sk_buff *os_buf)
+static int nss_data_plane_buf(void *arg, struct sk_buff *os_buf)
{
struct nss_data_plane_param *dp = (struct nss_data_plane_param *)arg;
diff --git a/nss_hal/include/nss_hal.h b/nss_hal/include/nss_hal.h
index 50b4495..3d84d0e 100644
--- a/nss_hal/include/nss_hal.h
+++ b/nss_hal/include/nss_hal.h
@@ -22,8 +22,11 @@
#ifndef __NSS_HAL_H
#define __NSS_HAL_H
+#include <linux/platform_device.h>
+
#include <nss_hal_pvt.h>
+#if (NSS_DT_SUPPORT != 1)
/*
* nss_hal_common_reset()
*/
@@ -31,14 +34,22 @@
{
__nss_hal_common_reset(clk_src);
}
+#endif
/*
* nss_hal_core_reset()
*/
+#if (NSS_DT_SUPPORT != 1)
static inline void nss_hal_core_reset(uint32_t core_id, uint32_t map, uint32_t addr, uint32_t clk_src)
{
__nss_hal_core_reset(core_id, map, addr, clk_src);
}
+#else
+static inline void nss_hal_core_reset(uint32_t map_base, uint32_t reset_addr)
+{
+ __nss_hal_core_reset(map_base, reset_addr);
+}
+#endif
/*
* nss_hal_read_interrupt_cause()
diff --git a/nss_hal/ipq806x/nss_clocks.h b/nss_hal/ipq806x/nss_clocks.h
index ada706d..1e7af1a 100644
--- a/nss_hal/ipq806x/nss_clocks.h
+++ b/nss_hal/ipq806x/nss_clocks.h
@@ -20,6 +20,7 @@
#ifndef __NSS_CLOCKS_H
#define __NSS_CLOCKS_H
+#if (NSS_DT_SUPPORT != 1)
#include <asm/io.h>
#include <mach/msm_iomap.h>
@@ -126,4 +127,5 @@
PLL_LOCKED
};
+#endif
#endif /* __NSS_CLOCKS_H */
diff --git a/nss_hal/ipq806x/nss_hal_pvt.c b/nss_hal/ipq806x/nss_hal_pvt.c
index e78c22a..e721ce3 100644
--- a/nss_hal/ipq806x/nss_hal_pvt.c
+++ b/nss_hal/ipq806x/nss_hal_pvt.c
@@ -22,7 +22,12 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio.h>
+#include <linux/version.h>
+
+#if (NSS_DT_SUPPORT != 1)
#include <mach/gpiomux.h>
+#endif
+
#include "nss_hal_pvt.h"
#include "nss_clocks.h"
#include "nss_core.h"
@@ -30,7 +35,9 @@
/*
* Global declarations
*/
+extern struct nss_top_instance nss_top_main;
+#if (NSS_FW_DBG_SUPPORT == 1)
/*
* NSS debug pins configuration
*/
@@ -148,6 +155,7 @@
},
},
};
+#endif /* NSS_FW_DBG_SUPPORT */
/*
* clk_reg_write_32()
@@ -173,10 +181,13 @@
*/
void __nss_hal_debug_enable(void)
{
+#if (NSS_FW_DBG_SUPPORT == 1)
msm_gpiomux_install(nss_spi_gpiomux,
ARRAY_SIZE(nss_spi_gpiomux));
+#endif
}
+#if (NSS_DT_SUPPORT != 1)
/*
* nss_hal_pvt_pll_change
* Change the Pll between 11(400mhz) or 18(1066 or 1466)
@@ -631,12 +642,18 @@
return;
}
+#endif /* NSS_DT_SUPPORT */
/*
* __nss_hal_core_reset
*/
+#if (NSS_DT_SUPPORT == 1)
+void __nss_hal_core_reset(uint32_t map, uint32_t addr)
+#else
void __nss_hal_core_reset(uint32_t core_id, uint32_t map, uint32_t addr, uint32_t clk_src)
+#endif
{
+#if (NSS_DT_SUPPORT != 1)
#if defined(NSS_ENABLE_CLOCK)
/*
* Enable mpt clock
@@ -715,6 +732,7 @@
clk_reg_write_32(UBI32_COREn_RESET_CLAMP(core_id), 0x0);
mdelay(1);
+#endif /* NSS_DT_SUPPORT */
/*
* Apply ubi32 core reset
diff --git a/nss_hal/ipq806x/nss_hal_pvt.h b/nss_hal/ipq806x/nss_hal_pvt.h
index 16f86b4..53c90c4 100755
--- a/nss_hal/ipq806x/nss_hal_pvt.h
+++ b/nss_hal/ipq806x/nss_hal_pvt.h
@@ -24,6 +24,7 @@
#include "nss_regs.h"
#include <linux/types.h>
+#include <linux/platform_device.h>
#define NSS_HAL_SUPPORTED_INTERRUPTS (NSS_REGS_N2H_INTR_STATUS_DATA_COMMAND_QUEUE | \
NSS_REGS_N2H_INTR_STATUS_EMPTY_BUFFER_QUEUE| \
@@ -71,12 +72,15 @@
nss_write_32(map, NSS_REGS_C2C_INTR_SET_OFFSET, cause);
}
+#if (NSS_DT_SUPPORT == 1)
+extern void __nss_hal_core_reset(uint32_t map, uint32_t reset);
+#else
extern void __nss_hal_core_reset(uint32_t core_id, uint32_t map, uint32_t addr, uint32_t clk_src);
extern void __nss_hal_common_reset(uint32_t *clk_src);
-extern void __nss_hal_debug_enable(void);
extern uint32_t nss_hal_pvt_divide_pll18(uint32_t core_id, uint32_t divider);
extern void nss_hal_pvt_pll_change(uint32_t pll);
extern uint32_t nss_hal_pvt_enable_pll18(uint32_t speed);
extern void nss_hal_pvt_register_dump(void);
-
+#endif
+extern void __nss_hal_debug_enable(void);
#endif /* __NSS_HAL_PVT_H */
diff --git a/nss_hal/ipq806x/nss_regs.h b/nss_hal/ipq806x/nss_regs.h
index 0dc85d3..055072b 100755
--- a/nss_hal/ipq806x/nss_regs.h
+++ b/nss_hal/ipq806x/nss_regs.h
@@ -86,7 +86,7 @@
*/
static inline uint32_t nss_read_32(uint32_t addr, uint32_t offs)
{
- return readl((addr + offs));
+ return readl((void *)(addr + offs));
}
/*
@@ -95,7 +95,7 @@
*/
static inline void nss_write_32(uint32_t addr, uint32_t offs, uint32_t val)
{
- writel(val, (addr + offs));
+ writel(val, (void *)(addr + offs));
}
#endif /* __NSS_REGS_H */
diff --git a/nss_hlos_if.h b/nss_hlos_if.h
index 9ab0c58..cdd6120 100755
--- a/nss_hlos_if.h
+++ b/nss_hlos_if.h
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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.
@@ -28,15 +28,9 @@
#define NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6 8196 /**< MAX Connection shared between IPv4 and IPv6 */
#define NSS_CONN_CFG_TIMEOUT 6000 /**< 6 sec timeout for connection cfg message */
-/*
- * Variables used for sysctl updates.
- */
-extern int nss_ipv4_conn_cfg;
-extern int nss_ipv6_conn_cfg;
-
enum {
- SUCCESS = 0,
- FAILURE = 1,
+ NSS_SUCCESS = 0,
+ NSS_FAILURE = 1,
};
/*
@@ -49,7 +43,6 @@
int response; /* Response from FW */
};
-
/*
* Request/Response types
*/
@@ -143,56 +136,6 @@
*/
/*
- * Request/Response types
- */
-enum nss_n2h_metadata_types {
- NSS_RX_METADATA_TYPE_N2H_STATS_SYNC=0,
- NSS_TX_METADATA_TYPE_N2H_RPS_CFG,
- NSS_METADATA_TYPE_N2H_MAX,
-};
-
-struct nss_n2h_rps {
- uint32_t enable; /* Enable NSS RPS */
-};
-
-/*
- * NSS Pbuf mgr stats
- */
-struct nss_n2h_pbuf_mgr_stats {
- uint32_t pbuf_alloc_fails; /* Pbuf ocm alloc fail */
- uint32_t pbuf_free_count; /* Pbuf ocm free count */
- uint32_t pbuf_total_count; /* Pbuf ocm total count */
-};
-
-/*
- * The NSS N2H statistics sync structure.
- */
-struct nss_n2h_stats_sync {
- struct nss_cmn_node_stats node_stats;
- /* Common node stats for N2H */
- uint32_t queue_dropped; /* Number of packets dropped because the PE queue is too full */
- uint32_t total_ticks; /* Total clock ticks spend inside the PE */
- uint32_t worst_case_ticks; /* Worst case iteration of the PE in ticks */
- uint32_t iterations; /* Number of iterations around the PE */
-
- struct nss_n2h_pbuf_mgr_stats pbuf_ocm_stats; /* Pbuf OCM Stats */
- struct nss_n2h_pbuf_mgr_stats pbuf_default_stats; /* Pbuf Default Stats */
-
- uint32_t payload_alloc_fails;
-};
-
-/*
- * Message structure to send/receive phys i/f commands
- */
-struct nss_n2h_msg {
- struct nss_cmn_msg cm; /* Message Header */
- union {
- struct nss_n2h_stats_sync stats_sync; /* Message: N2H stats sync */
- struct nss_n2h_rps rps_cfg; /* Message: RPS configuration */
- } msg;
-};
-
-/*
* IPv4 reasm node stats
*/
struct nss_ipv4_reasm_stats_sync {
diff --git a/nss_init.c b/nss_init.c
index 6777274..f9ca687 100755
--- a/nss_init.c
+++ b/nss_init.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013 - 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.
@@ -20,7 +20,9 @@
*
*/
#include "nss_core.h"
+#if (NSS_PM_SUPPORT == 1)
#include "nss_pm.h"
+#endif
#include "nss_tx_rx_common.h"
#include "nss_data_plane.h"
@@ -31,7 +33,16 @@
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/device.h>
+
+#if (NSS_DT_SUPPORT == 1)
+#include <linux/of.h>
+#include <linux/of_net.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/reset.h>
+#else
#include <mach/msm_nss.h>
+#endif
#include <linux/sysctl.h>
#include <linux/regulator/consumer.h>
@@ -57,10 +68,16 @@
int nss_jumbo_mru __read_mostly = 0;
int nss_paged_mode __read_mostly = 0;
+#ifdef CONFIG_DEBUG_KMEMLEAK
+extern struct sk_buff_head nss_skb_list;
+#endif
+
/*
* PM client handle
*/
+#if (NSS_PM_SUPPORT == 1)
static void *pm_client;
+#endif
/*
* Handler to send NSS messages
@@ -119,33 +136,225 @@
return IRQ_HANDLED;
}
+#if (NSS_DT_SUPPORT == 1)
+/*
+ * nss_drv_of_get_pdata()
+ * Retrieve platform data from device node.
+ */
+static struct nss_platform_data *nss_drv_of_get_pdata(struct device_node *np,
+ struct platform_device *pdev)
+{
+ struct nss_platform_data *npd = NULL;
+ struct nss_ctx_instance *nss_ctx = NULL;
+ struct nss_top_instance *nss_top = &nss_top_main;
+ uint32_t val;
+ struct resource res_nphys, res_vphys;
+ int32_t i;
+
+ npd = devm_kzalloc(&pdev->dev, sizeof(struct nss_platform_data), GFP_KERNEL);
+ if (!npd) {
+ return NULL;
+ }
+
+ if (of_property_read_u32(np, "qcom,id", &npd->id)
+ || of_property_read_u32(np, "qcom,rst_addr", &npd->rst_addr)
+ || of_property_read_u32(np, "qcom,load_addr", &npd->load_addr)
+ || of_property_read_u32(np, "qcom,turbo_frequency", &npd->turbo_frequency)
+ || of_property_read_u32(np, "qcom,gmac0_enabled", &npd->gmac_enabled[0])
+ || of_property_read_u32(np, "qcom,gmac1_enabled", &npd->gmac_enabled[1])
+ || of_property_read_u32(np, "qcom,gmac2_enabled", &npd->gmac_enabled[2])
+ || of_property_read_u32(np, "qcom,gmac3_enabled", &npd->gmac_enabled[3])
+ || of_property_read_u32(np, "qcom,num_irq", &npd->num_irq)) {
+ pr_err("%s: error reading critical device node properties\n", np->name);
+ goto out;
+ }
+
+ nss_ctx = &nss_top->nss[npd->id];
+ nss_ctx->id = npd->id;
+
+ if (of_address_to_resource(np, 0, &res_nphys) != 0) {
+ nss_info("%p: nss%d: of_address_to_resource() fail for nphys \n", nss_ctx, nss_ctx->id);
+ goto out;
+ }
+
+ if (of_address_to_resource(np, 1, &res_vphys) != 0) {
+ nss_info("%p: nss%d: of_address_to_resource() fail for vphys \n", nss_ctx, nss_ctx->id);
+ goto out;
+ }
+
+ /*
+ * Save physical addresses
+ */
+ npd->nphys = res_nphys.start;
+ npd->vphys = res_vphys.start;
+
+ npd->nmap = (uint32_t)ioremap_nocache(npd->nphys, resource_size(&res_nphys));
+ if (!npd->nmap) {
+ nss_info("%p: nss%d: ioremap() fail for nphys \n", nss_ctx, nss_ctx->id);
+ goto out;
+ }
+
+ npd->vmap = (uint32_t)ioremap_nocache(npd->vphys, resource_size(&res_vphys));
+ if (!npd->vmap) {
+ nss_info("%p: nss%d: ioremap() fail for vphys \n", nss_ctx, nss_ctx->id);
+ goto out;
+ }
+
+ /*
+ * Clear TCM memory used by this core
+ */
+ for (i = 0; i < resource_size(&res_vphys) ; i += 4) {
+ nss_write_32((uint32_t)npd->vmap, i, 0);
+ }
+
+ /*
+ * Get IRQ numbers
+ */
+ for (val = 0 ; val < npd->num_irq ; val++) {
+ npd->irq[val] = irq_of_parse_and_map(np, val);
+ if (!npd->irq[val]) {
+ nss_info("%p: nss%d: irq_of_parse_and_map() fail for irq %d\n",
+ nss_ctx, nss_ctx->id, val);
+ goto out;
+ }
+ }
+
+ if (of_property_read_u32(np, "qcom,ipv4_enabled", &npd->ipv4_enabled)
+ || of_property_read_u32(np, "qcom,ipv6_enabled", &npd->ipv6_enabled)
+ || of_property_read_u32(np, "qcom,l2switch_enabled", &npd->l2switch_enabled)
+ || of_property_read_u32(np, "qcom,crypto_enabled", &npd->crypto_enabled)
+ || of_property_read_u32(np, "qcom,ipsec_enabled", &npd->ipsec_enabled)
+ || of_property_read_u32(np, "qcom,wlan_enabled", &npd->wlan_enabled)
+ || of_property_read_u32(np, "qcom,tun6rd_enabled", &npd->tun6rd_enabled)
+ || of_property_read_u32(np, "qcom,tunipip6_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);
+ }
+
+ return npd;
+
+out:
+ if (npd->nmap) {
+ iounmap((void *)npd->nmap);
+ }
+
+ if (npd->vmap) {
+ iounmap((void *)npd->vmap);
+ }
+
+ devm_kfree(&pdev->dev, npd);
+
+ return NULL;
+}
+
+#endif
/*
* nss_probe()
* HLOS device probe callback
*/
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
static int __devinit nss_probe(struct platform_device *nss_dev)
+#else
+static int nss_probe(struct platform_device *nss_dev)
+#endif
{
struct nss_top_instance *nss_top = &nss_top_main;
- struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
- struct nss_platform_data *npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
+ struct nss_ctx_instance *nss_ctx = NULL;
+ struct nss_platform_data *npd = NULL;
struct netdev_priv_instance *ndev_priv;
+#if (NSS_DT_SUPPORT == 1)
+ struct reset_control *rstctl = NULL;
+#endif
int i, err = 0;
const struct firmware *nss_fw = NULL;
int rc = -ENODEV;
void __iomem *load_mem;
- nss_ctx->nss_top = nss_top;
+#if (NSS_DT_SUPPORT == 1)
+ struct device_node *np = NULL;
+
+ if (nss_top_main.nss_hal_common_init_done == false) {
+ /*
+ * Perform clock init common to all NSS cores
+ */
+ struct clk *nss_tcm_src = NULL;
+ struct clk *nss_tcm_clk = NULL;
+
+ /*
+ * Attach debug interface to TLMM
+ */
+ nss_write_32((uint32_t)nss_top_main.nss_fpb_base, NSS_REGS_FPB_CSR_CFG_OFFSET, 0x360);
+
+ /*
+ * NSS TCM CLOCK
+ */
+ nss_tcm_src = clk_get(&nss_dev->dev, NSS_TCM_SRC_CLK);
+ if (IS_ERR(nss_tcm_src)) {
+ pr_err("nss-driver: cannot get clock: " NSS_TCM_SRC_CLK);
+ return -EFAULT;
+ }
+
+ clk_set_rate(nss_tcm_src, NSSTCM_FREQ);
+ clk_prepare(nss_tcm_src);
+ clk_enable(nss_tcm_src);
+
+ nss_tcm_clk = clk_get(&nss_dev->dev, NSS_TCM_CLK);
+ if (IS_ERR(nss_tcm_clk)) {
+ pr_err("nss-driver: cannot get clock: " NSS_TCM_CLK);
+ return -EFAULT;
+ }
+
+ clk_prepare(nss_tcm_clk);
+ clk_enable(nss_tcm_clk);
+
+ nss_top_main.nss_hal_common_init_done = true;
+ nss_info("nss_hal_common_reset Done.\n");
+ }
+
+ if (nss_dev->dev.of_node) {
+ /*
+ * Device Tree based init
+ */
+
+ np = of_node_get(nss_dev->dev.of_node);
+ npd = nss_drv_of_get_pdata(np, nss_dev);
+
+ of_node_put(np);
+
+ if (!npd) {
+ return -EFAULT;
+ }
+
+ nss_ctx = &nss_top->nss[npd->id];
+ nss_ctx->id = npd->id;
+ nss_dev->id = nss_ctx->id;
+
+ } else {
+ /*
+ * Platform Device based init
+ */
+
+ npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
+ nss_ctx = &nss_top->nss[nss_dev->id];
+ nss_ctx->id = nss_dev->id;
+ }
+
+#else
+ npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
+ nss_ctx = &nss_top->nss[nss_dev->id];
nss_ctx->id = nss_dev->id;
+#endif
+ nss_ctx->nss_top = nss_top;
nss_info("%p: NSS_DEV_ID %s \n", nss_ctx, dev_name(&nss_dev->dev));
/*
* F/W load from NSS Driver
*/
- if (nss_dev->id == 0) {
+ if (nss_ctx->id == 0) {
rc = request_firmware(&nss_fw, NETAP0_IMAGE, &(nss_dev->dev));
- } else if (nss_dev->id == 1) {
+ } else if (nss_ctx->id == 1) {
rc = request_firmware(&nss_fw, NETAP1_IMAGE, &(nss_dev->dev));
} else {
nss_warning("%p: Invalid nss dev: %d \n", nss_ctx, nss_dev->id);
@@ -179,7 +388,7 @@
/*
* Both NSS cores controlled by same regulator, Hook only Once
*/
- if (!nss_dev->id) {
+ if (!nss_ctx->id) {
nss_core0_clk = clk_get(&nss_dev->dev, "nss_core_clk");
if (IS_ERR(nss_core0_clk)) {
@@ -192,6 +401,7 @@
clk_prepare(nss_core0_clk);
clk_enable(nss_core0_clk);
+#if (NSS_PM_SUPPORT == 1)
/*
* Check if turbo is supported
*/
@@ -206,13 +416,16 @@
printk("nss_driver - Turbo No Support %d\n", npd->turbo_frequency);
nss_runtime_samples.freq_scale_sup_max = NSS_MAX_CPU_SCALES - 1;
}
+#else
+ printk("nss_driver - Turbo Not Supported\n");
+#endif
}
/*
* Get load address of NSS firmware
*/
- nss_info("%p: Setting NSS%d Firmware load address to %x\n", nss_ctx, nss_dev->id, npd->load_addr);
- nss_top->nss[nss_dev->id].load = npd->load_addr;
+ nss_info("%p: Setting NSS%d Firmware load address to %x\n", nss_ctx, nss_ctx->id, npd->load_addr);
+ nss_top->nss[nss_ctx->id].load = npd->load_addr;
/*
* Get virtual and physical memory addresses for nss logical/hardware address maps
@@ -242,7 +455,7 @@
nss_ctx->vphys = npd->vphys;
nss_assert(nss_ctx->vphys);
nss_info("%d:ctx=%p, vphys=%x, vmap=%x, nphys=%x, nmap=%x",
- nss_dev->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
+ nss_ctx->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
/*
* Register netdevice handlers
@@ -408,8 +621,9 @@
}
}
+#if (NSS_PM_SUPPORT == 1)
nss_freq_register_handler();
-
+#endif
nss_lso_rx_register_handler();
nss_top->frequency_handler_id = nss_dev->id;
@@ -432,9 +646,64 @@
/*
* Enable clocks and bring NSS core out of reset
*/
- nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
+#if (NSS_DT_SUPPORT == 1)
+ /*
+ * Remove UBI32 reset clamp
+ */
+ rstctl = devm_reset_control_get(&nss_dev->dev, NSS_CORE_CLK_RST_CLAMP);
+ if (IS_ERR(rstctl)) {
+ nss_info("%p: Deassert UBI32 reset clamp failed", nss_ctx, nss_ctx->id);
+ err = -EFAULT;
+ goto err_init_5;
+ }
+ reset_control_deassert(rstctl);
+ mdelay(1);
+ reset_control_put(rstctl);
/*
+ * Remove UBI32 core clamp
+ */
+ rstctl = devm_reset_control_get(&nss_dev->dev, NSS_CORE_CLAMP);
+ if (IS_ERR(rstctl)) {
+ nss_info("%p: Deassert UBI32 core clamp failed", nss_ctx, nss_ctx->id);
+ err = -EFAULT;
+ goto err_init_5;
+ }
+ reset_control_deassert(rstctl);
+ mdelay(1);
+ reset_control_put(rstctl);
+
+ /*
+ * Remove UBI32 AHB reset
+ */
+ rstctl = devm_reset_control_get(&nss_dev->dev, NSS_CORE_AHB_RESET);
+ if (IS_ERR(rstctl)) {
+ nss_info("%p: Deassert AHB reset failed", nss_ctx, nss_ctx->id);
+ err = -EFAULT;
+ goto err_init_5;
+ }
+ reset_control_deassert(rstctl);
+ mdelay(1);
+ reset_control_put(rstctl);
+
+ /*
+ * Remove UBI32 AXI reset
+ */
+ rstctl = devm_reset_control_get(&nss_dev->dev, NSS_CORE_AXI_RESET);
+ if (IS_ERR(rstctl)) {
+ nss_info("%p: Deassert AXI reset failed", nss_ctx, nss_ctx->id);
+ err = -EFAULT;
+ goto err_init_5;
+ }
+ reset_control_deassert(rstctl);
+ mdelay(1);
+ reset_control_put(rstctl);
+
+ nss_hal_core_reset(nss_ctx->nmap, nss_ctx->load);
+#else
+ nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
+#endif
+ /*
* Enable interrupts for NSS core
*/
nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
@@ -462,7 +731,27 @@
unregister_netdev(nss_ctx->int_ctx[0].ndev);
err_init_1:
free_netdev(nss_ctx->int_ctx[0].ndev);
+
+#if (NSS_DT_SUPPORT == 1)
+ if (nss_dev->dev.of_node) {
+ if (npd->nmap) {
+ iounmap((void *)npd->nmap);
+ }
+
+ if (npd->vmap) {
+ iounmap((void *)npd->vmap);
+ }
+ }
+#endif
+
err_init_0:
+
+#if (NSS_DT_SUPPORT == 1)
+ if (nss_dev->dev.of_node) {
+ devm_kfree(&nss_dev->dev, npd);
+ }
+
+#endif
return err;
}
@@ -470,7 +759,11 @@
* nss_remove()
* HLOS device remove callback
*/
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
static int __devexit nss_remove(struct platform_device *nss_dev)
+#else
+static int nss_remove(struct platform_device *nss_dev)
+#endif
{
struct nss_top_instance *nss_top = &nss_top_main;
struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
@@ -512,24 +805,54 @@
nss_data_plane_unregister_from_nss_gmac(i);
}
}
+#if (NSS_DT_SUPPORT == 1)
+ if (nss_dev->dev.of_node) {
+ if (nss_ctx->nmap) {
+ iounmap((void *)nss_ctx->nmap);
+ nss_ctx->nmap = 0;
+ }
+
+ if (nss_ctx->vmap) {
+ iounmap((void *)nss_ctx->vmap);
+ nss_ctx->vmap = 0;
+ }
+ }
+#endif
nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
return 0;
}
+#if (NSS_DT_SUPPORT == 1)
+static struct of_device_id nss_dt_ids[] = {
+ { .compatible = "qcom,nss0" },
+ { .compatible = "qcom,nss1" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, nss_dt_ids);
+#endif
+
/*
* nss_driver
* Platform driver structure for NSS
*/
struct platform_driver nss_driver = {
.probe = nss_probe,
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
.remove = __devexit_p(nss_remove),
+#else
+ .remove = nss_remove,
+#endif
.driver = {
.name = "qca-nss",
.owner = THIS_MODULE,
+#if (NSS_DT_SUPPORT == 1)
+ .of_match_table = of_match_ptr(nss_dt_ids),
+#endif
},
};
+#if (NSS_PM_SUPPORT == 1)
/*
* nss_reset_frequency_stats_samples()
* Reset all frequency sampling state when auto scaling is turned off.
@@ -732,7 +1055,9 @@
return ret;
}
+#endif /* NSS_PM_SUPPORT */
+#if (NSS_FW_DBG_SUPPORT == 1)
/*
* nss_debug_handler()
* Enable NSS debug output
@@ -751,6 +1076,7 @@
return ret;
}
+#endif
/*
* nss_rps_handler()
@@ -846,6 +1172,7 @@
return ret;
}
+#if (NSS_PM_SUPPORT == 1)
/*
* sysctl-tuning infrastructure.
*/
@@ -880,6 +1207,7 @@
},
{ }
};
+#endif
static ctl_table nss_general_table[] = {
{
@@ -889,6 +1217,7 @@
.mode = 0644,
.proc_handler = proc_dointvec,
},
+#if (NSS_FW_DBG_SUPPORT == 1)
{
.procname = "debug",
.data = &nss_ctl_debug,
@@ -896,6 +1225,7 @@
.mode = 0644,
.proc_handler = &nss_debug_handler,
},
+#endif
{
.procname = "coredump",
.data = &nss_cmd_buf.coredump,
@@ -935,11 +1265,13 @@
};
static ctl_table nss_clock_dir[] = {
+#if (NSS_PM_SUPPORT == 1)
{
.procname = "clock",
.mode = 0555,
.child = nss_freq_table,
},
+#endif
{
.procname = "general",
.mode = 0555,
@@ -974,15 +1306,58 @@
*/
static int __init nss_init(void)
{
+#if (NSS_DT_SUPPORT == 1)
+ struct device_node *cmn = NULL;
+ struct resource res_nss_fpb_base;
+#endif
+
nss_info("Init NSS driver");
+#if (NSS_PM_SUPPORT == 1)
nss_freq_change_context = nss_freq_get_mgr();
+#else
+ nss_freq_change_context = NULL;
+#endif
+#if (NSS_DT_SUPPORT == 1)
+ /*
+ * Get reference to NSS common device node
+ */
+ cmn = of_find_node_by_name(NULL, "nss-common");
+ if (!cmn) {
+ nss_info("cannot find nss-common node\n");
+ return -EFAULT;
+ }
+
+ if (of_address_to_resource(cmn, 0, &res_nss_fpb_base) != 0) {
+ nss_info("of_address_to_resource() return error for nss_fpb_base\n");
+ of_node_put(cmn);
+ return -EFAULT;
+ }
+
+ nss_top_main.nss_fpb_base = ioremap_nocache(res_nss_fpb_base.start,
+ resource_size(&res_nss_fpb_base));
+ if (!nss_top_main.nss_fpb_base) {
+ nss_info("ioremap fail for nss_fpb_base\n");
+ of_node_put(cmn);
+ return -EFAULT;
+ }
+
+ nss_top_main.nss_hal_common_init_done = false;
+
+ /*
+ * Release reference to NSS common device node
+ */
+ of_node_put(cmn);
+ cmn = NULL;
+#else
/*
* Perform clock init common to all NSS cores
*/
nss_hal_common_reset(&(nss_top_main.clk_src));
+#endif /* NSS_DT_SUPPORT */
+
/*
* Enable spin locks
*/
@@ -1005,6 +1380,16 @@
nss_ipv4_register_sysctl();
nss_ipv6_register_sysctl();
+#ifdef CONFIG_DEBUG_KMEMLEAK
+ /*
+ * If the system is under kmemleak debugging, track our
+ * skbs by putting them in a list.
+ */
+
+ skb_queue_head_init(&nss_skb_list);
+#endif
+
+#if (NSS_PM_SUPPORT == 1)
/*
* Setup Runtime Sample values
*/
@@ -1047,6 +1432,7 @@
if (!pm_client) {
nss_warning("Error registering with PM driver");
}
+#endif
/*
* Register platform_driver
@@ -1066,11 +1452,23 @@
unregister_sysctl_table(nss_dev_header);
/*
+ * Unregister n2h specific sysctl
+ */
+ nss_n2h_empty_pool_buf_unregister_sysctl();
+
+ /*
* Unregister ipv4/6 specific sysctl
*/
nss_ipv4_unregister_sysctl();
nss_ipv6_unregister_sysctl();
+#if (NSS_DT_SUPPORT == 1)
+ if(nss_top_main.nss_fpb_base) {
+ iounmap(nss_top_main.nss_fpb_base);
+ nss_top_main.nss_fpb_base = 0;
+ }
+#endif
+
platform_driver_unregister(&nss_driver);
}
diff --git a/nss_ipsecmgr.c b/nss_ipsecmgr.c
deleted file mode 100644
index 988807d..0000000
--- a/nss_ipsecmgr.c
+++ /dev/null
@@ -1,1262 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_ipsecmgr.c
- * NSS to HLOS IPSec Manager
- */
-#include <linux/types.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/rtnetlink.h>
-#include <asm/atomic.h>
-#include <nss_api_if.h>
-#include <nss_ipsec.h>
-#include "nss_ipsecmgr.h"
-
-#if defined(CONFIG_DYNAMIC_DEBUG)
-/*
- * Compile messages for dynamic enable/disable
- */
-#define nss_ipsecmgr_error(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define nss_ipsecmgr_warn(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define nss_ipsecmgr_info(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define nss_ipsecmgr_trace(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-
-#else
-/*
- * Statically compile messages at different levels
- */
-#define nss_ipsecmgr_error(s, ...) { \
- if (NSS_IPSECMGR_DEBUG_LEVEL < NSS_IPSECMGR_DEBUG_LVL_ERROR) { \
- pr_alert("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
- } \
-}
-#define nss_ipsecmgr_warn(s, ...) { \
- if (NSS_IPSECMGR_DEBUG_LEVEL < NSS_IPSECMGR_DEBUG_LVL_WARN) { \
- pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
- } \
-}
-#define nss_ipsecmgr_info(s, ...) { \
- if (NSS_IPSECMGR_DEBUG_LEVEL < NSS_IPSECMGR_DEBUG_LVL_INFO) { \
- pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
- } \
-}
-#define nss_ipsecmgr_trace(s, ...) { \
- if (NSS_IPSECMGR_DEBUG_LEVEL < NSS_IPSECMGR_DEBUG_LVL_TRACE) { \
- pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
- } \
-}
-
-#endif /* !CONFIG_DYNAMIC_DEBUG */
-
-/* NSS IPsec entry state */
-enum nss_ipsecmgr_entry_state {
- NSS_IPSECMGR_ENTRY_STATE_INIT = 0, /* init state of the entry */
- NSS_IPSECMGR_ENTRY_STATE_VALID = 1, /* entry is valid */
- NSS_IPSECMGR_ENTRY_STATE_INVALID = 2, /* entry is invalid */
- NSS_IPSECMGR_ENTRY_STATE_MAX
-};
-
-/* IPsec table entry */
-struct nss_ipsecmgr_tbl_entry {
- struct nss_ipsec_rule_sel sel; /* rule selector */
- uint32_t sa_idx; /* index into SA table for this rule */
- enum nss_ipsecmgr_entry_state state; /* state */
-};
-
-/* NSS IPsec table type */
-struct nss_ipsecmgr_tbl {
- uint32_t total_tx; /* total packets tx'ed from ENCAP/DECAP */
- uint32_t total_rx; /* total packets rx'ed at ENCAP/DECAP */
- uint32_t total_dropped; /* total dropped packets at ENCAP/DECAP */
- struct nss_ipsecmgr_tbl_entry entry[NSS_IPSEC_MAX_RULES]; /* table entry */
- uint32_t count; /* number of entries */
- spinlock_t lock;
-};
-
-/* NSS IPsec SA */
-struct nss_ipsec_sa {
- atomic_t user; /* reference count */
- uint32_t esp_spi; /* ESP SPI */
-
- enum nss_ipsecmgr_rule_type type; /* IPsec rule type (ENCAP/DECAP) */
-
- struct nss_ipsec_rule_data data; /* IPsec rule data */
- struct nss_ipsec_sa_stats stats; /* SA statistics */
-};
-
-/* NSS IPsec manager private structure */
-struct nss_ipsecmgr_priv {
- struct nss_ipsecmgr_tbl encap; /* encap table */
- struct nss_ipsecmgr_tbl decap; /* decap table */
- struct nss_ipsec_sa sa_tbl[NSS_IPSEC_MAX_SA]; /* global SA table */
-
- void *cb_ctx; /* callback context */
- nss_ipsecmgr_data_cb_t data_cb; /* data callback function */
- nss_ipsecmgr_event_cb_t event_cb; /* event callback function */
- struct nss_ctx_instance *nss_ctx; /* NSS context */
- uint32_t nss_ifnum; /* NSS if num for data */
-};
-
-typedef bool (*nss_ipsecmgr_op_t)(struct net_device *dev, struct nss_ipsecmgr_tbl *tbl, struct nss_ipsec_msg *nim);
-
-/* NSS IPsec manager operation (message types) complete routines */
-struct nss_ipsecmgr_ops {
- nss_ipsecmgr_op_t verify_fn; /* verify function for the op */
- nss_ipsecmgr_op_t commit_fn; /* commit function for the op */
-};
-
-/* driver global info */
-struct nss_ipsecmgr_drv {
- atomic_t sa_count; /* number of SA's available for */
-};
-
-/*
- **********************
- * globals
- **********************
- */
-
-static struct nss_ipsecmgr_drv gbl_drv_ctx; /* global driver context */
-
-/*
- **********************
- * Helper Functions
- **********************
- */
-
-/*
- * nss_ipsecmgr_sa_init()
- * Initialize SA
- */
-static void nss_ipsecmgr_sa_init(struct nss_ipsec_sa *sa)
-{
- memset(sa, 0, sizeof(struct nss_ipsec_sa));
- atomic_set(&sa->user, 0);
-}
-
-/*
- * nss_ipsecmgr_sa_get()
- * Get reference to SA at given index
- */
-static struct nss_ipsec_sa *nss_ipsecmgr_sa_get(struct nss_ipsec_sa sa_tbl[], uint32_t sa_idx)
-{
- struct nss_ipsec_sa *sa = &sa_tbl[sa_idx];
-
- atomic_inc(&sa->user);
-
- return sa;
-}
-
-/*
- * nss_ipsecmgr_sa_put()
- * Release reference to SA at given index
- */
-static void nss_ipsecmgr_sa_put(struct nss_ipsec_sa sa_tbl[], uint32_t sa_idx)
-{
- struct nss_ipsec_sa *sa = &sa_tbl[sa_idx];
-
- if (atomic_read(&sa->user) == 0) {
- nss_ipsecmgr_error("SA already freed for (%d)\n", sa_idx);
- return;
- }
-
- if (atomic_dec_and_test(&sa->user)) {
- nss_ipsecmgr_sa_init(sa);
- }
-}
-
-/*
- * nss_ipsecmgr_get_type()
- * Get IPsec manager rule type (encap/decap)
- */
-static enum nss_ipsecmgr_rule_type nss_ipsecmgr_get_type(uint16_t if_num)
-{
- switch(if_num) {
- case NSS_IPSEC_ENCAP_IF_NUMBER:
- return NSS_IPSECMGR_RULE_TYPE_ENCAP;
-
- case NSS_IPSEC_DECAP_IF_NUMBER:
- return NSS_IPSECMGR_RULE_TYPE_DECAP;
-
- default:
- return NSS_IPSECMGR_RULE_TYPE_NONE;
- }
-}
-
-/*
- * nss_ipsecmgr_get_tbl()
- * return the table associated with the interface number
- */
-static inline struct nss_ipsecmgr_tbl *nss_ipsecmgr_get_tbl(struct nss_ipsecmgr_priv *priv, uint16_t if_num)
-{
- switch (if_num) {
- case NSS_IPSEC_ENCAP_IF_NUMBER:
- return &priv->encap;
-
- case NSS_IPSEC_DECAP_IF_NUMBER:
- return &priv->decap;
-
- default:
- return NULL;
- }
-}
-
-/*
- * nss_ipsecmgr_copy_encap_add()
- * prepare the IPsec message for encap add operation
- */
-static void nss_ipsecmgr_copy_encap_add(struct net_device *dev, struct nss_ipsec_rule *msg, union nss_ipsecmgr_rule *rule)
-{
- struct nss_ipsecmgr_encap_add *encap = &rule->encap_add;
- struct nss_ipsec_rule_sel *sel = &msg->sel;
- struct nss_ipsec_rule_oip *oip = &msg->oip;
- struct nss_ipsec_rule_data *data = &msg->data;
-
- /*
- * Populate the selectors for encap direction
- */
- sel->ipv4_src = encap->inner_ipv4_src;
- sel->ipv4_dst = encap->inner_ipv4_dst;
-
- sel->src_port = encap->inner_src_port;
- sel->dst_port = encap->inner_dst_port;
-
- sel->ipv4_proto = encap->inner_ipv4_proto;
-
- /*
- * Populate the outer IP data for encap direction
- */
- oip->ipv4_dst = encap->outer_ipv4_dst;
- oip->ipv4_src = encap->outer_ipv4_src;
-
- oip->esp_spi = encap->esp_spi;
-
- oip->ipv4_ttl = encap->outer_ipv4_ttl;
-
- /*
- * Populate the data part
- */
- data->cipher_algo = encap->cipher_algo;
- data->esp_seq_skip = (encap->esp_seq_skip == 1);
- data->esp_tail_skip = (encap->esp_tail_skip == 1);
-
- data->esp_icv_len = encap->esp_icv_len;
- data->auth_algo = encap->auth_algo;
-
- data->crypto_index = encap->crypto_index;
-
- data->nat_t_req = encap->nat_t_req;
- data->use_pattern = encap->use_pattern;
-}
-
-/*
- * nss_ipsecmgr_copy_decap_add()
- * prepare the IPsec message for decap add operation
- */
-static void nss_ipsecmgr_copy_decap_add(struct net_device *dev, struct nss_ipsec_rule *msg, union nss_ipsecmgr_rule *rule)
-{
- struct nss_ipsecmgr_decap_add *decap = &rule->decap_add;
- struct nss_ipsec_rule_sel *sel = &msg->sel;
- struct nss_ipsec_rule_data *data = &msg->data;
- /*
- * Populate the selectors for encap direction
- */
- sel->ipv4_src = decap->outer_ipv4_src;
- sel->ipv4_dst = decap->outer_ipv4_dst;
-
- sel->esp_spi = decap->esp_spi;
-
- sel->ipv4_proto = IPPROTO_ESP;
-
- /*
- * Populate the data part
- */
- data->cipher_algo = decap->cipher_algo;
-
- data->esp_icv_len = decap->esp_icv_len;
- data->esp_seq_skip = (decap->esp_seq_skip == 1);
- data->esp_tail_skip = (decap->esp_tail_skip == 1);
- data->auth_algo = decap->auth_algo;
-
- data->crypto_index = decap->crypto_index;
-
- data->nat_t_req = decap->nat_t_req;
- if (data->nat_t_req) {
- sel->dst_port = NSS_IPSECMGR_NATT_PORT_DATA;
- }
-
- data->window_size = decap->window_size;
-}
-
-/*
- * nss_ipsecmgr_copy_encap_del()
- * prepare the IPsec message for encap del operation
- */
-static void nss_ipsecmgr_copy_encap_del(struct net_device *dev, struct nss_ipsec_rule *msg, union nss_ipsecmgr_rule *rule)
-{
- struct nss_ipsecmgr_encap_del *encap = &rule->encap_del;
- struct nss_ipsec_rule_sel *sel = &msg->sel;
-
- /*
- * Populate the selectors for encap direction
- */
- sel->ipv4_src = encap->inner_ipv4_src;
- sel->ipv4_dst = encap->inner_ipv4_dst;
-
- sel->src_port = encap->inner_src_port;
- sel->dst_port = encap->inner_dst_port;
-
- sel->ipv4_proto = encap->inner_ipv4_proto;
-}
-
-/*
- * nss_ipsecmgr_copy_decap_del()
- * prepare the IPsec message for decap del operation
- */
-static void nss_ipsecmgr_copy_decap_del(struct net_device *dev, struct nss_ipsec_rule *msg, union nss_ipsecmgr_rule *rule)
-{
- struct nss_ipsecmgr_decap_del *decap = &rule->decap_del;
- struct nss_ipsec_rule_sel *sel = &msg->sel;
- /*
- * Populate the selectors for encap direction
- */
- sel->ipv4_src = decap->outer_ipv4_src;
- sel->ipv4_dst = decap->outer_ipv4_dst;
-
- sel->esp_spi = decap->esp_spi;
-
- sel->ipv4_proto = IPPROTO_ESP;
-}
-
-/*
- **********************
- * message handlers
- **********************
- */
-/*
- * nss_ipsecmgr_verify_add()
- * verify the Add operation before committing
- */
-static bool nss_ipsecmgr_verify_add(struct net_device *dev, struct nss_ipsecmgr_tbl *tbl, struct nss_ipsec_msg *nim)
-{
- struct nss_ipsec_rule *rule = &nim->msg.push;
- struct nss_ipsecmgr_tbl_entry *entry;
- uint32_t tbl_idx;
-
- tbl_idx = rule->rule_idx;
- if (tbl_idx >= NSS_IPSEC_MAX_RULES) {
- nss_ipsecmgr_error("table index out of range\n");
- return false;
- }
-
- entry = &tbl->entry[tbl_idx];
-
- /*
- * XXX:Duplicate hit or hash collision; We need to handle
- * hash collision
- */
- if (entry->state == NSS_IPSECMGR_ENTRY_STATE_VALID) {
- return false;
- }
-
- /*
- * Table full, XXX:must increment stats
- */
- if ((tbl->count + 1) >= NSS_IPSEC_MAX_RULES) {
- return false;
- }
-
- return true;
-}
-
-/*
- * nss_ipsecmgr_commit_add()
- * commit the Add operation
- */
-static bool nss_ipsecmgr_commit_add(struct net_device *dev, struct nss_ipsecmgr_tbl *tbl, struct nss_ipsec_msg *nim)
-{
- struct nss_ipsec_rule *rule = &nim->msg.push;
- struct nss_ipsecmgr_tbl_entry *entry;
- struct nss_ipsecmgr_priv *priv;
- struct nss_ipsec_sa *sa;
- uint32_t tbl_idx;
- uint32_t sa_idx;
-
- priv = netdev_priv(dev);
-
- /* Reduce the number of availabe SA(s) as we have successfully added one */
- atomic_dec(&gbl_drv_ctx.sa_count);
-
- tbl_idx = rule->rule_idx;
- entry = &tbl->entry[tbl_idx];
-
- tbl->count++;
-
- memcpy(&entry->sel, &rule->sel, sizeof(struct nss_ipsec_rule_sel));
- entry->state = NSS_IPSECMGR_ENTRY_STATE_VALID;
-
- /* increment SA use count */
- sa_idx = rule->sa_idx;
- sa = nss_ipsecmgr_sa_get(priv->sa_tbl, sa_idx);
-
- /* copy rule data to SA */
- memcpy(&sa->data, &rule->data, sizeof(struct nss_ipsec_rule_data));
-
- /* save rule type (encap/decap) */
- sa->type = nss_ipsecmgr_get_type(nim->cm.interface);
-
- /* save ESP SPI in SA */
- switch (nim->cm.interface) {
- case NSS_IPSEC_ENCAP_IF_NUMBER:
- sa->esp_spi = rule->oip.esp_spi;
- break;
-
- case NSS_IPSEC_DECAP_IF_NUMBER:
- sa->esp_spi = rule->sel.esp_spi;
- break;
-
- default:
- nss_ipsecmgr_error("invalid interface num = %d\n", nim->cm.interface);
- return false;
- }
-
- /* save SA table index for this rule entry */
- entry->sa_idx = sa_idx;
-
- return true;
-}
-
-/*
- * nss_ipsecmgr_verify_del()
- * verify the del operation before committing
- */
-static bool nss_ipsecmgr_verify_del(struct net_device *dev, struct nss_ipsecmgr_tbl *tbl, struct nss_ipsec_msg *nim)
-{
- struct nss_ipsec_rule *rule = &nim->msg.push;
- struct nss_ipsecmgr_tbl_entry *entry;
- uint32_t tbl_idx;
-
- tbl_idx = rule->rule_idx;
- if (tbl_idx >= NSS_IPSEC_MAX_RULES) {
- nss_ipsecmgr_error("table index out of range\n");
- return false;
- }
-
- entry = &tbl->entry[tbl_idx];
-
- /*
- * Entry already deleted, XXX:must increment stats
- */
- if (entry->state == NSS_IPSECMGR_ENTRY_STATE_INVALID) {
- return false;
- }
-
- /*
- * Entry never existed, XXX:must increment stats
- */
- if (entry->state == NSS_IPSECMGR_ENTRY_STATE_INIT) {
- return false;
- }
-
- /*
- * Table empty, XXX:must increment stats
- */
- if (tbl->count == 0) {
- return false;
- }
-
- return true;
-}
-
-/*
- * nss_ipsecmgr_commit_del()
- * commit the Del operation
- */
-static bool nss_ipsecmgr_commit_del(struct net_device *dev, struct nss_ipsecmgr_tbl *tbl, struct nss_ipsec_msg *nim)
-{
- struct nss_ipsec_rule *rule = &nim->msg.push;
- struct nss_ipsecmgr_tbl_entry *entry;
- struct nss_ipsecmgr_priv *priv;
- uint32_t tbl_idx;
- uint32_t sa_idx;
-
- priv = netdev_priv(dev);
-
- /* Increase the number of available SA(s) as we have successfully freed one */
- atomic_inc(&gbl_drv_ctx.sa_count);
-
- tbl_idx = rule->rule_idx;
- entry = &tbl->entry[tbl_idx];
-
- tbl->count--;
-
- memset(&entry->sel, 0, sizeof(struct nss_ipsec_rule_sel));
- entry->state = NSS_IPSECMGR_ENTRY_STATE_INVALID;
-
- /* decrement SA use count */
- sa_idx = rule->sa_idx;
- nss_ipsecmgr_sa_put(priv->sa_tbl, sa_idx);
-
- return true;
-}
-
-/*
- * nss_ipsecmgr_verify_stats()
- * verify stats update operation
- */
-static bool nss_ipsecmgr_verify_stats(struct net_device *dev, struct nss_ipsecmgr_tbl *tbl, struct nss_ipsec_msg *nim)
-{
- struct nss_ipsec_sa_stats *msg_sa_stats = &nim->msg.stats;
-
- /*
- * Table empty, nothing to update
- */
- if (tbl->count == 0) {
- return false;
- }
-
- if (msg_sa_stats->sa_idx > NSS_CRYPTO_MAX_IDXS) {
- return false;
- }
-
- return true;
-}
-
-/*
- * nss_ipsecmgr_commit_stats()
- * commit stats for the SA
- */
-static bool nss_ipsecmgr_commit_stats(struct net_device *dev, struct nss_ipsecmgr_tbl *tbl, struct nss_ipsec_msg *nim)
-{
- struct nss_ipsec_sa_stats *msg_stats = &nim->msg.stats;
- struct nss_ipsec_sa_stats *sa_stats;
- struct nss_ipsec_sa *sa;
- struct nss_ipsecmgr_priv *priv;
- struct nss_ipsecmgr_event event = {.type = NSS_IPSECMGR_EVENT_SA_STATS};
- struct nss_ipsecmgr_sa_stats *event_stats = &event.data.stats;
- nss_ipsecmgr_event_cb_t event_cb;
- void *cb_ctx;
- uint32_t sa_idx;
-
- priv = netdev_priv(dev);
-
- /* get reference to SA stats */
- sa_idx = msg_stats->sa_idx;
- sa = nss_ipsecmgr_sa_get(priv->sa_tbl, sa_idx);
-
- sa_stats = &sa->stats;
-
- /* copy SA statistics */
- sa_stats->seqnum = msg_stats->seqnum;
- memcpy(&sa_stats->pkts, &msg_stats->pkts, sizeof(struct nss_ipsec_pkt_stats));
-
- /* execute event callback to send SA stats event */
- event_cb = priv->event_cb;
- cb_ctx = priv->cb_ctx;
- if (event_cb && cb_ctx) {
- event_stats->esp_spi = sa->esp_spi;
- event_stats->seqnum = sa_stats->seqnum;
- event_stats->crypto_index = sa->data.crypto_index;
- event_stats->type = sa->type;
-
- event_stats->pkts_processed = sa_stats->pkts.processed;
- event_stats->pkts_dropped = sa_stats->pkts.dropped;
- event_stats->pkts_failed = sa_stats->pkts.failed;
-
- event_cb(cb_ctx, &event);
- }
-
- /* decrement SA use count */
- nss_ipsecmgr_sa_put(priv->sa_tbl, sa_idx);
-
- return true;
-}
-
-/*
- * nss_ipsecmgr_verify_flush()
- * verify the flush operation
- */
-static bool nss_ipsecmgr_verify_flush(struct net_device *dev, struct nss_ipsecmgr_tbl *tbl, struct nss_ipsec_msg *nim)
-{
- return true;
-}
-
-/*
- * nss_ipsecmgr_commit_flush()
- * commit the flush operation
- */
-static bool nss_ipsecmgr_commit_flush(struct net_device *dev, struct nss_ipsecmgr_tbl *tbl, struct nss_ipsec_msg *nim)
-{
- struct nss_ipsecmgr_priv *priv;
- struct nss_ipsec_sa *sa;
- int32_t count;
-
- priv = netdev_priv(dev);
-
- tbl->count = 0;
-
- for (count = 0, sa = &priv->sa_tbl[0]; count < NSS_IPSEC_MAX_SA; count++, sa++) {
- nss_ipsecmgr_sa_init(sa);
- }
-
- return true;
-}
-
-/*
- * callback operation
- */
-const static struct nss_ipsecmgr_ops cb_ops[NSS_IPSEC_MSG_TYPE_MAX] = {
- [NSS_IPSEC_MSG_TYPE_ADD_RULE] = {nss_ipsecmgr_verify_add, nss_ipsecmgr_commit_add},
- [NSS_IPSEC_MSG_TYPE_DEL_RULE] = {nss_ipsecmgr_verify_del, nss_ipsecmgr_commit_del},
- [NSS_IPSEC_MSG_TYPE_SYNC_STATS] = {nss_ipsecmgr_verify_stats, nss_ipsecmgr_commit_stats},
- [NSS_IPSEC_MSG_TYPE_FLUSH_TUN] = {nss_ipsecmgr_verify_flush, nss_ipsecmgr_commit_flush}
-};
-
-/*
- * nss_ipsecmgr_op_receive()
- * asynchronous event reception
- */
-static void nss_ipsecmgr_op_receive(void *app_data, struct nss_ipsec_msg *nim)
-{
- struct net_device *tun_dev = (struct net_device *)app_data;
- struct nss_ipsecmgr_priv *priv;
- struct nss_ipsecmgr_tbl *tbl;
- nss_ipsecmgr_op_t verify_fn;
- nss_ipsecmgr_op_t commit_fn;
- struct net_device *dev;
-
- BUG_ON(tun_dev == NULL);
- BUG_ON(nim == NULL);
-
- /* this holds the ref_cnt for the device */
- dev = dev_get_by_index(&init_net, nim->tunnel_id);
- if (dev == NULL) {
- nss_ipsecmgr_error("event received on deallocated I/F (%d)\n", nim->tunnel_id);
- return;
- }
-
- if (dev != tun_dev) {
- nss_ipsecmgr_error("event received on incorrect I/F (%d)\n", nim->tunnel_id);
- goto done;
- }
-
- priv = netdev_priv(dev);
-
- tbl = nss_ipsecmgr_get_tbl(priv, nim->cm.interface);
- if (tbl == NULL) {
- nss_ipsecmgr_error("invalid interface number(%d)\n", nim->cm.interface);
- goto done;
- }
-
- verify_fn = cb_ops[nim->cm.type].verify_fn;
- commit_fn = cb_ops[nim->cm.type].commit_fn;
-
- if (!verify_fn || !commit_fn) {
- nss_ipsecmgr_error("unhandled type (%d)\n", nim->cm.type);
- goto done;
- }
-
- /*
- * Now we can operate on the entry of the table
- */
- spin_lock_bh(&tbl->lock);
-
- if (verify_fn(dev, tbl, nim) == true) {
- commit_fn(dev, tbl, nim);
- }
-
- spin_unlock_bh(&tbl->lock);
-done:
- /* release the device as we are done */
- dev_put(dev);
-}
-
-/*
- * nss_ipsecmgr_op_send()
- * Push a IPsec rule to NSS
- */
-static bool nss_ipsecmgr_op_send(struct net_device *dev, struct nss_ipsec_msg *nim, uint32_t if_num, enum nss_ipsec_msg_type type)
-{
- struct nss_ipsecmgr_priv *priv;
- nss_tx_status_t status;
-
- priv = netdev_priv(dev);
- if (priv->nss_ctx == NULL) {
- nss_ipsecmgr_error("Tunnel registration or de-registration is underway\n");
- return false;
- }
-
- nim->tunnel_id = dev->ifindex;
-
- nss_ipsec_msg_init(nim, if_num, type, NSS_IPSEC_MSG_LEN, (nss_ipsec_msg_callback_t *)nss_ipsecmgr_op_receive, dev);
-
- status = nss_ipsec_tx_msg(priv->nss_ctx, nim);
- if (status != NSS_TX_SUCCESS) {
- nss_ipsecmgr_error("unable to push rule(%d) for %s\n", type, dev->name);
- return false;
- }
-
- return true;
-}
-
-/*
- * nss_ipsecmgr_buf_receive()
- * receive NSS exception packets
- */
-static void nss_ipsecmgr_buf_receive(struct net_device *dev, struct sk_buff *skb, __attribute((unused)) struct napi_struct *napi)
-{
- struct nss_ipsecmgr_priv *priv;
- nss_ipsecmgr_data_cb_t cb_fn;
- void *cb_ctx;
- struct iphdr *ip;
-
- BUG_ON(dev == NULL);
- BUG_ON(skb == NULL);
-
- /* hold the device till we process it */
- dev_hold(dev);
-
- /*
- * XXX:need to ensure that the dev being accessed is not deleted
- */
- priv = netdev_priv(dev);
-
- skb->dev = dev;
-
- cb_fn = priv->data_cb;
- cb_ctx = priv->cb_ctx;
-
- /*
- * if tunnel creator gave a callback then send the packet without
- * any modifications to him
- */
- if (cb_fn && cb_ctx) {
- cb_fn(cb_ctx, skb);
- goto done;
- }
-
- ip = (struct iphdr *)skb->data;
- if ((ip->version != IPVERSION) || (ip->ihl != 5)) {
- nss_ipsecmgr_error("dropping packets(IP version:%x, Header len:%x)\n", ip->version, ip->ihl);
- dev_kfree_skb_any(skb);
- goto done;
- }
-
- skb_reset_network_header(skb);
- skb_reset_mac_header(skb);
-
- skb->pkt_type = PACKET_HOST;
- skb->protocol = cpu_to_be16(ETH_P_IP);
- skb->skb_iif = dev->ifindex;
-
- netif_receive_skb(skb);
-done:
- /* release the device as we are done */
- dev_put(dev);
-}
-
-/*
- **********************
- * Netdev ops
- **********************
- */
-
-/*
- * nss_ipsecmgr_tunnel_init()
- * initiallizes the tunnel
- */
-static int nss_ipsecmgr_tunnel_init(struct net_device *dev)
-{
- struct nss_ipsecmgr_priv *priv;
-
- priv = netdev_priv(dev);
-
- priv->nss_ctx = nss_ipsec_get_context();
-
- return 0;
-}
-
-/*
- * nss_ipsecmgr_tunnel_exit()
- * deinitiallizes the tunnel
- */
-static void nss_ipsecmgr_tunnel_exit(struct net_device *dev)
-{
- struct nss_ipsecmgr_priv *priv;
-
- priv = netdev_priv(dev);
-
- priv->nss_ctx = NULL;
-}
-
-/*
- * nss_ipsecmgr_tunnel_open()
- * open the tunnel for usage
- */
-static int nss_ipsecmgr_tunnel_open(struct net_device *dev)
-{
- struct nss_ipsecmgr_priv *priv;
-
- priv = netdev_priv(dev);
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-/*
- * nss_ipsecmgr_tunnel_stop()
- * stop the IPsec tunnel
- */
-static int nss_ipsecmgr_tunnel_stop(struct net_device *dev)
-{
- struct nss_ipsecmgr_priv *priv;
-
- priv = netdev_priv(dev);
-
- netif_stop_queue(dev);
-
- return 0;
-}
-
-/*
- * nss_ipsecmgr_tunnel_xmit()
- * tunnel transmit function
- */
-static netdev_tx_t nss_ipsecmgr_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- uint32_t if_num;
- struct iphdr *inner_ip;
- struct nss_ipsecmgr_priv *priv;
- struct nss_ipsecmgr_tbl *encap;
-
- if_num = NSS_IPSEC_ENCAP_IF_NUMBER;
- priv = netdev_priv(dev);
- encap = &priv->encap;
-
- if (skb_is_nonlinear(skb)) {
- nss_ipsecmgr_error("%p: NSS IPSEC does not support fragments %p\n", priv->nss_ctx, skb);
- goto fail;
- }
-
- /*
- * Check if skb is shared
- */
- if (unlikely(skb_shared(skb))) {
- nss_ipsecmgr_error("%p: Shared skb is not supported: %p\n", priv->nss_ctx, skb);
- goto fail;
- }
-
- /*
- * Check the packet head room & tail room
- */
- if (unlikely(skb_headroom(skb) < dev->needed_headroom)) {
- nss_ipsecmgr_error("%p: Insufficient head room :%d in skb: %p\n", priv->nss_ctx, skb_headroom(skb), skb);
- goto fail;
- }
-
- if (unlikely(skb_tailroom(skb) < dev->needed_tailroom)) {
- nss_ipsecmgr_error("%p: Insufficient tail room:%d in skb: %p\n", priv->nss_ctx, skb_tailroom(skb), skb);
- goto fail;
- }
-
- /*
- * Check if packet is given starting from network header
- */
- if (skb->data != skb_network_header(skb)) {
- nss_ipsecmgr_error("%p: 'Skb data is not starting from IP header", priv->nss_ctx);
- goto fail;
- }
-
- inner_ip = (struct iphdr *)ip_hdr(skb);
-
- /*
- * Validate if packet has ip options
- */
- if ((inner_ip->version != IPVERSION) || (inner_ip->ihl != 5)) {
- nss_ipsecmgr_error("%p: Unsupported IP header ipver: 0x%x iphdr_len: 0x%x\n", priv->nss_ctx,
- inner_ip->version, inner_ip->ihl);
- goto fail;
- }
-
- /*
- * Check the TTL value
- */
- if ((inner_ip->ttl == 0)) {
- nss_ipsecmgr_error("%p: IP TTL is zero, unabled to transmit\n", priv->nss_ctx);
- goto fail;
- }
-
- /*
- * Send the packet down
- */
- if (nss_ipsec_tx_buf(skb, if_num) != 0) {
- /*
- * TODO: NEED TO STOP THE QUEUE
- */
- goto fail;
- }
-
- /*
- * Increment the tx count
- */
- encap->total_tx++;
-
- return NETDEV_TX_OK;
-
-fail:
- return NETDEV_TX_BUSY;
-}
-
-/*
- * nss_ipsecmgr_tunnel_stats()
- * get tunnel statistics
- */
-static struct net_device_stats *nss_ipsecmgr_tunnel_stats(struct net_device *dev)
-{
- struct net_device_stats *stats = &dev->stats;
- struct nss_ipsecmgr_priv *priv;
- struct nss_ipsec_sa *sa;
- uint32_t i;
-
- memset(stats, 0, sizeof(struct net_device_stats));
-
- priv = netdev_priv(dev);
-
- for (i = 0, sa = &priv->sa_tbl[0]; i < NSS_IPSEC_MAX_SA; i++, sa++) {
- if (atomic_read(&sa->user) == 0) {
- continue;
- }
-
- switch (sa->type) {
- case NSS_IPSECMGR_RULE_TYPE_ENCAP:
- stats->tx_packets += sa->stats.pkts.processed;
- stats->tx_dropped += sa->stats.pkts.dropped;
- break;
-
- case NSS_IPSECMGR_RULE_TYPE_DECAP:
- stats->rx_packets += sa->stats.pkts.processed;
- stats->rx_dropped += sa->stats.pkts.dropped;
- break;
-
- default:
- nss_ipsecmgr_error("unknown ipsec rule type\n");
- break;
- }
- }
-
- return stats;
-}
-
-/* NSS IPsec tunnel operation */
-static const struct net_device_ops nss_ipsecmgr_tunnel_ops = {
- .ndo_init = nss_ipsecmgr_tunnel_init,
- .ndo_uninit = nss_ipsecmgr_tunnel_exit,
- .ndo_start_xmit = nss_ipsecmgr_tunnel_xmit,
- .ndo_open = nss_ipsecmgr_tunnel_open,
- .ndo_stop = nss_ipsecmgr_tunnel_stop,
- .ndo_get_stats = nss_ipsecmgr_tunnel_stats,
-};
-
-/*
- * nss_ipsecmgr_tunnel_free()
- * free an existing IPsec tunnel interface
- */
-static void nss_ipsecmgr_tunnel_free(struct net_device *dev)
-{
- struct nss_ipsecmgr_priv *priv = netdev_priv(dev);
- struct nss_ipsecmgr_tbl *encap_tbl;
- struct nss_ipsecmgr_tbl *decap_tbl;
-
- encap_tbl = &priv->encap;
- decap_tbl = &priv->decap;
-
- nss_ipsecmgr_info("IPsec tunnel device(%s) freed\n", dev->name);
- nss_ipsecmgr_info("Entries left: encap(%d), decap(%d)\n", encap_tbl->count, decap_tbl->count);
-
- free_netdev(dev);
-}
-
-/*
- * nss_ipsecmr_setup_tunnel()
- * setup the IPsec tunnel
- */
-static void nss_ipsecmgr_tunnel_setup(struct net_device *dev)
-{
- dev->addr_len = ETH_ALEN;
- dev->mtu = NSS_IPSECMGR_TUN_MTU(ETH_DATA_LEN);
-
- dev->hard_header_len = NSS_IPSECMGR_TUN_MAX_HDR_LEN;
- dev->needed_headroom = NSS_IPSECMGR_TUN_HEADROOM;
- dev->needed_tailroom = NSS_IPSECMGR_TUN_TAILROOM;
-
- dev->type = NSS_IPSEC_ARPHRD_IPSEC;
-
- dev->ethtool_ops = NULL;
- dev->header_ops = NULL;
- dev->netdev_ops = &nss_ipsecmgr_tunnel_ops;
-
- dev->destructor = nss_ipsecmgr_tunnel_free;
-
- /*
- * XXX:should get the MAC address from the ethernet device
- */
- memcpy(dev->dev_addr, "\xaa\xbb\xcc\xdd\xee\xff", dev->addr_len);
- memset(dev->broadcast, 0xff, dev->addr_len);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-}
-
-/*
- **********************
- * Exported Functions
- **********************
- */
-
-/*
- * nss_ipsecmgr_tunnel_add()
- * add a IPsec pseudo tunnel device
- */
-struct net_device *nss_ipsecmgr_tunnel_add(void *cb_ctx, nss_ipsecmgr_data_cb_t data_cb, nss_ipsecmgr_event_cb_t event_cb)
-{
- struct net_device *dev;
- struct nss_ipsecmgr_priv *priv;
- struct nss_ipsec_sa *sa;
- int status;
- int count;
- int32_t if_num;
-
- /* Features denote the skb types supported */
- uint32_t features = 0;
-
- dev = alloc_netdev(sizeof(struct nss_ipsecmgr_priv), NSS_IPSECMGR_TUN_NAME, nss_ipsecmgr_tunnel_setup);
- if (!dev) {
- nss_ipsecmgr_error("unable to allocate a tunnel device\n");
- return NULL;
- }
-
- priv = netdev_priv(dev);
-
- priv->cb_ctx = cb_ctx;
- priv->data_cb = data_cb;
- priv->event_cb = event_cb;
-
- /* initialize SA stats table for this tunnel */
- for (count = 0, sa = &priv->sa_tbl[0]; count < NSS_IPSEC_MAX_SA; count++, sa++) {
- nss_ipsecmgr_sa_init(sa);
- }
-
- spin_lock_init(&priv->encap.lock);
- spin_lock_init(&priv->decap.lock);
-
- status = rtnl_is_locked() ? register_netdevice(dev) : register_netdev(dev);
- if (status < 0) {
- goto fail;
- }
-
- if_num = nss_ipsec_get_interface(priv->nss_ctx);
- if (if_num < 0) {
- nss_ipsecmgr_error("Invalid nss interface :%d\n", if_num);
- return NULL;
- }
-
- nss_ipsec_data_register(if_num, nss_ipsecmgr_buf_receive, dev, features);
-
- /*
- * Store data interface number in private data
- */
- priv->nss_ifnum = if_num;
-
- nss_ipsec_notify_register(NSS_IPSEC_ENCAP_IF_NUMBER, nss_ipsecmgr_op_receive, dev);
- nss_ipsec_notify_register(NSS_IPSEC_DECAP_IF_NUMBER, nss_ipsecmgr_op_receive, dev);
-
- return dev;
-
-fail:
- free_netdev(dev);
-
- return NULL;
-}
-EXPORT_SYMBOL(nss_ipsecmgr_tunnel_add);
-
-/*
- * nss_ipsecmgr_del_tunnel()
- * delete an existing IPsec tunnel
- */
-bool nss_ipsecmgr_tunnel_del(struct net_device *dev)
-{
- struct nss_ipsecmgr_priv *priv;
- struct nss_ipsecmgr_tbl *encap;
- struct nss_ipsecmgr_tbl *decap;
- struct nss_ipsec_msg nim;
- bool status;
-
- priv = netdev_priv(dev);
-
- encap = &priv->encap;
- decap = &priv->decap;
-
- /*
- * Unregister the callbacks from the HLOS as we are no longer
- * interested in exception data & async messages
- */
- nss_ipsec_data_unregister(priv->nss_ctx, priv->nss_ifnum);
-
- nss_ipsec_notify_unregister(priv->nss_ctx, NSS_IPSEC_ENCAP_IF_NUMBER);
- nss_ipsec_notify_unregister(priv->nss_ctx, NSS_IPSEC_DECAP_IF_NUMBER);
-
- priv->data_cb = NULL;
- priv->event_cb = NULL;
-
- /*
- * Prepare to flush all SA(s) inside a tunnel
- */
- memset(&nim, 0, sizeof(struct nss_ipsec_msg));
-
- status = nss_ipsecmgr_op_send(dev, &nim, NSS_IPSEC_ENCAP_IF_NUMBER, NSS_IPSEC_MSG_TYPE_FLUSH_TUN);
- if (status != true) {
- nss_ipsecmgr_error("unable complete tunnel deletion, for ingress rules\n");
- goto fail;
- }
-
- /* release all SA(s) associated with the encap */
- atomic_sub(encap->count, &gbl_drv_ctx.sa_count);
-
- status = nss_ipsecmgr_op_send(dev, &nim, NSS_IPSEC_DECAP_IF_NUMBER, NSS_IPSEC_MSG_TYPE_FLUSH_TUN);
- if (status != true) {
- nss_ipsecmgr_error("unable complete tunnel deletion, for egress rules\n");
- goto fail;
- }
-
- /* release all SA(s) associated with the decap */
- atomic_sub(decap->count, &gbl_drv_ctx.sa_count);
-
- /*
- * The unregister should start here but the expectation is that the free would
- * happen when the reference count goes down to '0'
- */
- rtnl_is_locked() ? unregister_netdevice(dev) : unregister_netdev(dev);
-
- return true;
-fail:
- /* caller must retry */
- return false;
-}
-EXPORT_SYMBOL(nss_ipsecmgr_tunnel_del);
-
-/*
- * nss_ipsecmgr_sa_add()
- * add a new SA to the tunnel
- */
-bool nss_ipsecmgr_sa_add(struct net_device *dev, union nss_ipsecmgr_rule *rule, enum nss_ipsecmgr_rule_type type)
-{
- struct nss_ipsecmgr_priv *priv;
- struct nss_ipsec_msg nim;
- uint32_t if_num;
-
- priv = netdev_priv(dev);
-
- /* check if there are free SA(s) */
- if (atomic_read(&gbl_drv_ctx.sa_count) == 0) {
- return false;
- }
-
- memset(&nim, 0, sizeof(struct nss_ipsec_msg));
-
- /* XXX: some basic validation of the passed rule needs to happen */
-
- switch (type) {
- case NSS_IPSECMGR_RULE_TYPE_ENCAP:
- if_num = NSS_IPSEC_ENCAP_IF_NUMBER;
- nss_ipsecmgr_copy_encap_add(dev, &nim.msg.push, rule);
- break;
-
- case NSS_IPSECMGR_RULE_TYPE_DECAP:
- if_num = NSS_IPSEC_DECAP_IF_NUMBER;
- nss_ipsecmgr_copy_decap_add(dev, &nim.msg.push, rule);
- break;
-
- default:
- nss_ipsecmgr_error("Unknown rule type(%d) for Add operation\n", type);
- return false;
- }
-
- return nss_ipsecmgr_op_send(dev, &nim, if_num, NSS_IPSEC_MSG_TYPE_ADD_RULE);
-
-}
-EXPORT_SYMBOL(nss_ipsecmgr_sa_add);
-
-/*
- * nss_ipsecmgr_sa_del()
- *
- */
-bool nss_ipsecmgr_sa_del(struct net_device *dev, union nss_ipsecmgr_rule *rule, enum nss_ipsecmgr_rule_type type)
-{
- struct nss_ipsecmgr_priv *priv;
- struct nss_ipsec_msg nim;
- uint32_t if_num;
-
- priv = netdev_priv(dev);
-
- /* check if all SA(s) are already freed */
- if (atomic_read(&gbl_drv_ctx.sa_count) == NSS_IPSEC_MAX_RULES) {
- return false;
- }
-
- memset(&nim, 0, sizeof(struct nss_ipsec_msg));
-
- /* XXX: some basic validation of the passed rule needs to happen */
-
- switch (type) {
- case NSS_IPSECMGR_RULE_TYPE_ENCAP:
- if_num = NSS_IPSEC_ENCAP_IF_NUMBER;
- nss_ipsecmgr_copy_encap_del(dev, &nim.msg.push, rule);
- break;
-
- case NSS_IPSECMGR_RULE_TYPE_DECAP:
- if_num = NSS_IPSEC_DECAP_IF_NUMBER;
- nss_ipsecmgr_copy_decap_del(dev, &nim.msg.push, rule);
- break;
-
- default:
- nss_ipsecmgr_error("Unknown rule type(%d) for Del operation\n", type);
- return false;
- }
- return nss_ipsecmgr_op_send(dev, &nim, if_num, NSS_IPSEC_MSG_TYPE_DEL_RULE);
-}
-EXPORT_SYMBOL(nss_ipsecmgr_sa_del);
-
-static int __init nss_ipsecmgr_init(void)
-{
- nss_ipsecmgr_info("NSS IPsec manager loaded: Build date %s\n", __DATE__);
-
- memset(&gbl_drv_ctx, 0, sizeof(struct nss_ipsecmgr_drv));
-
- atomic_set(&gbl_drv_ctx.sa_count, NSS_IPSEC_MAX_RULES);
-
- return 0;
-}
-
-
-static void __exit nss_ipsecmgr_exit(void)
-{
- nss_ipsecmgr_info("NSS IPsec manager unloader\n");
-}
-
-module_init(nss_ipsecmgr_init);
-module_exit(nss_ipsecmgr_exit);
diff --git a/nss_ipv4.c b/nss_ipv4.c
index 1052de8..c7c3135 100644
--- a/nss_ipv4.c
+++ b/nss_ipv4.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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.
@@ -32,7 +32,9 @@
static void nss_ipv4_driver_conn_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync *nirs)
{
struct nss_top_instance *nss_top = nss_ctx->nss_top;
+#if (NSS_PPP_SUPPORT == 1)
struct net_device *pppoe_dev = NULL;
+#endif
/*
* Update statistics maintained by NSS driver
@@ -47,6 +49,7 @@
/*
* Update the PPPoE interface stats, if there is any PPPoE session on the interfaces.
*/
+#if (NSS_PPP_SUPPORT == 1)
if (nirs->flow_pppoe_session_id) {
pppoe_dev = ppp_session_to_netdev(nirs->flow_pppoe_session_id, (uint8_t *)nirs->flow_pppoe_remote_mac);
if (pppoe_dev) {
@@ -64,6 +67,7 @@
dev_put(pppoe_dev);
}
}
+#endif
}
/*
@@ -302,7 +306,7 @@
* Error, hence we are not updating the nss_ipv4_conn_cfg
* Restore the current_value to its previous state
*/
- i4cfgp.response = FAILURE;
+ i4cfgp.response = NSS_FAILURE;
complete(&i4cfgp.complete);
return;
}
@@ -312,7 +316,7 @@
* saved at the sysctl handler.
*/
nss_info("IPv4 connection configuration success: %d\n", nim->cm.error);
- i4cfgp.response = SUCCESS;
+ i4cfgp.response = NSS_SUCCESS;
complete(&i4cfgp.complete);
}
@@ -327,7 +331,7 @@
struct nss_ipv4_msg nim;
struct nss_ipv4_rule_conn_cfg_msg *nirccm;
nss_tx_status_t nss_tx_status;
- int ret = FAILURE;
+ int ret = NSS_FAILURE;
uint32_t sum_of_conn;
/*
@@ -372,7 +376,7 @@
*/
nss_ipv4_conn_cfg = i4cfgp.current_value;
up(&i4cfgp.sem);
- return FAILURE;
+ return NSS_FAILURE;
}
nss_info("%p: IPv4 supported connections: %d\n", nss_ctx, nss_ipv4_conn_cfg);
@@ -394,7 +398,7 @@
*/
nss_ipv4_conn_cfg = i4cfgp.current_value;
up(&i4cfgp.sem);
- return FAILURE;
+ return NSS_FAILURE;
}
/*
@@ -409,7 +413,7 @@
*/
nss_ipv4_conn_cfg = i4cfgp.current_value;
up(&i4cfgp.sem);
- return FAILURE;
+ return NSS_FAILURE;
}
/*
@@ -417,18 +421,18 @@
* If ACK: Callback function will update nss_ipv4_conn_cfg with
* i4cfgp.num_conn_valid, which holds the user input
*/
- if (FAILURE == i4cfgp.response) {
+ if (NSS_FAILURE == i4cfgp.response) {
/*
* Restore the current_value to its previous state
*/
nss_ipv4_conn_cfg = i4cfgp.current_value;
up(&i4cfgp.sem);
- return FAILURE;
+ return NSS_FAILURE;
}
up(&i4cfgp.sem);
- return SUCCESS;
+ return NSS_SUCCESS;
}
static ctl_table nss_ipv4_table[] = {
diff --git a/nss_ipv6.c b/nss_ipv6.c
index 0b1400b..4e56cc5 100644
--- a/nss_ipv6.c
+++ b/nss_ipv6.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014 - 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.
@@ -31,7 +31,9 @@
static void nss_ipv6_driver_conn_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync *nics)
{
struct nss_top_instance *nss_top = nss_ctx->nss_top;
+#if (NSS_PPP_SUPPORT == 1)
struct net_device *pppoe_dev = NULL;
+#endif
/*
* Update statistics maintained by NSS driver
@@ -46,6 +48,7 @@
/*
* Update the PPPoE interface stats, if there is any PPPoE session on the interfaces.
*/
+#if (NSS_PPP_SUPPORT == 1)
if (nics->flow_pppoe_session_id) {
pppoe_dev = ppp_session_to_netdev(nics->flow_pppoe_session_id, (uint8_t *)nics->flow_pppoe_remote_mac);
if (pppoe_dev) {
@@ -63,6 +66,7 @@
dev_put(pppoe_dev);
}
}
+#endif
}
/*
@@ -301,7 +305,7 @@
* Error, hence we are not updating the nss_ipv4_conn_cfg
* Restore the current_value to its previous state
*/
- i6cfgp.response = FAILURE;
+ i6cfgp.response = NSS_FAILURE;
complete(&i6cfgp.complete);
return;
}
@@ -311,7 +315,7 @@
* saved at the sysctl handler.
*/
nss_info("IPv6 connection configuration success: %d\n", nim->cm.error);
- i6cfgp.response = SUCCESS;
+ i6cfgp.response = NSS_SUCCESS;
complete(&i6cfgp.complete);
}
@@ -327,7 +331,7 @@
struct nss_ipv6_msg nim;
struct nss_ipv6_rule_conn_cfg_msg *nirccm;
nss_tx_status_t nss_tx_status;
- int ret = FAILURE;
+ int ret = NSS_FAILURE;
uint32_t sum_of_conn;
/*
@@ -370,7 +374,7 @@
*/
nss_ipv6_conn_cfg = i6cfgp.current_value;
up(&i6cfgp.sem);
- return FAILURE;
+ return NSS_FAILURE;
}
@@ -393,7 +397,7 @@
*/
nss_ipv6_conn_cfg = i6cfgp.current_value;
up(&i6cfgp.sem);
- return FAILURE;
+ return NSS_FAILURE;
}
/*
@@ -408,7 +412,7 @@
*/
nss_ipv6_conn_cfg = i6cfgp.current_value;
up(&i6cfgp.sem);
- return FAILURE;
+ return NSS_FAILURE;
}
/*
@@ -416,17 +420,17 @@
* If ACK: Callback function will update nss_ipv4_conn_cfg with
* i6cfgp.num_conn_valid, which holds the user input
*/
- if (FAILURE == i6cfgp.response) {
+ if (NSS_FAILURE == i6cfgp.response) {
/*
* Restore the current_value to its previous state
*/
nss_ipv6_conn_cfg = i6cfgp.current_value;
up(&i6cfgp.sem);
- return FAILURE;
+ return NSS_FAILURE;
}
up(&i6cfgp.sem);
- return SUCCESS;
+ return NSS_SUCCESS;
}
static ctl_table nss_ipv6_table[] = {
diff --git a/nss_log.c b/nss_log.c
index e37b08d..b271763 100644
--- a/nss_log.c
+++ b/nss_log.c
@@ -30,7 +30,6 @@
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/platform_device.h>
-#include <mach/msm_nss.h>
#include <linux/device.h>
#include <nss_hal.h>
#include "nss_core.h"
diff --git a/nss_n2h.c b/nss_n2h.c
index bb725ee..f1b46d8 100755
--- a/nss_n2h.c
+++ b/nss_n2h.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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.
@@ -21,61 +21,26 @@
#include "nss_tx_rx_common.h"
-#define NSS_N2H_TIMEOUT 5*HZ
-
-wait_queue_head_t nss_n2h_wq;
+#define NSS_CORE_0 0
+#define NSS_CORE_1 1
/*
- * nss_n2h_tx()
- * Send Message to NSS to enable RPS.
- *
- * This API could be used for any additional RPS related
- * configuration in future.
+ * This number is chosen becuase currently default IPV4 + IPV6
+ * connection size is 1024 + 1024 = 2048.
+ * FYI: However this doesnt have any impact on n2h/ipv6 connections
*/
-nss_tx_status_t nss_n2h_tx(struct nss_ctx_instance *nss_ctx, uint32_t enable_rps)
-{
- struct sk_buff *nbuf;
- nss_tx_status_t status;
- struct nss_n2h_msg *nnhm;
- struct nss_n2h_rps *rps_cfg;
+#define NSS_N2H_MIN_EMPTY_POOL_BUF_SZ 2048
+#define NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ 8192
- NSS_VERIFY_CTX_MAGIC(nss_ctx);
- if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
- return NSS_TX_FAILURE_NOT_READY;
- }
+int nss_n2h_empty_pool_buf_cfg[NSS_MAX_CORES] __read_mostly = {NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ, NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ};
- nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
- if (unlikely(!nbuf)) {
- spin_lock_bh(&nss_ctx->nss_top->stats_lock);
- nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
- spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
- return NSS_TX_FAILURE;
- }
+struct nss_n2h_registered_data {
+ nss_n2h_msg_callback_t n2h_callback;
+ void *app_data;
+};
- nnhm = (struct nss_n2h_msg *)skb_put(nbuf, sizeof(struct nss_n2h_msg));
-
- nnhm->cm.type = NSS_TX_METADATA_TYPE_N2H_RPS_CFG;
- nnhm->cm.version = NSS_HLOS_MESSAGE_VERSION;
- nnhm->cm.interface = NSS_N2H_INTERFACE;
- nnhm->cm.len = nbuf->len;
-
- rps_cfg = &nnhm->msg.rps_cfg;
-
- rps_cfg->enable = enable_rps;
-
- nss_info("n22_n2h_rps_configure %d \n", enable_rps);
-
- 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_info("%p: unable to enqueue 'nss frequency change' - marked as stopped\n", nss_ctx);
- 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);
-
- return NSS_TX_SUCCESS;
-}
+static struct nss_n2h_cfg_pvt nss_n2h_nepbcfgp[NSS_MAX_CORES];
+static struct nss_n2h_registered_data nss_n2h_rd[NSS_MAX_CORES];
/*
* nss_n2h_stats_sync()
@@ -120,6 +85,22 @@
*/
nss_ctx->stats_n2h[NSS_STATS_N2H_PAYLOAD_ALLOC_FAILS] += nnss->payload_alloc_fails;
+ /*
+ * Host <=> NSS control traffic stats
+ */
+ nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_CONTROL_PACKETS] += nnss->h2n_ctrl_pkts;
+ nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_CONTROL_BYTES] += nnss->h2n_ctrl_bytes;
+ nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_CONTROL_PACKETS] += nnss->n2h_ctrl_pkts;
+ nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_CONTROL_BYTES] += nnss->n2h_ctrl_bytes;
+
+ /*
+ * Host <=> NSS control data traffic stats
+ */
+ nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_DATA_PACKETS] += nnss->h2n_data_pkts;
+ nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_DATA_BYTES] += nnss->h2n_data_bytes;
+ nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_PACKETS] += nnss->n2h_data_pkts;
+ nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_BYTES] += nnss->n2h_data_bytes;
+
spin_unlock_bh(&nss_top->stats_lock);
}
@@ -130,6 +111,7 @@
static void nss_n2h_interface_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
{
struct nss_n2h_msg *nnm = (struct nss_n2h_msg *)ncm;
+ nss_n2h_msg_callback_t cb;
BUG_ON(ncm->interface != NSS_N2H_INTERFACE);
@@ -145,12 +127,14 @@
case NSS_TX_METADATA_TYPE_N2H_RPS_CFG:
nss_ctx->n2h_rps_en = nnm->msg.rps_cfg.enable;
nss_info("NSS N2H rps_en %d \n",nnm->msg.rps_cfg.enable);
- wake_up(&nss_n2h_wq);
+ break;
+
+ case NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG:
+ nss_info("%p: empty pool buf cfg response from FW", nss_ctx);
break;
case NSS_RX_METADATA_TYPE_N2H_STATS_SYNC:
nss_n2h_stats_sync(nss_ctx, &nnm->msg.stats_sync);
- wake_up(&nss_n2h_wq);
break;
default:
@@ -162,6 +146,435 @@
nss_ctx, ncm->response, ncm->type, ncm->interface);
}
}
+
+ /*
+ * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
+ * to the same callback/app_data.
+ */
+ if (nnm->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
+ /*
+ * Place holder for the user to create right call
+ * back and app data when response is NSS_CMM_RESPONSE_NOTIFY
+ */
+ ncm->cb = (uint32_t)nss_n2h_rd[nss_ctx->id].n2h_callback;
+ ncm->app_data = (uint32_t)nss_n2h_rd[nss_ctx->id].app_data;
+ }
+
+ /*
+ * Do we have a callback?
+ */
+ if (!ncm->cb) {
+ return;
+ }
+
+ /*
+ * Callback
+ */
+ cb = (nss_n2h_msg_callback_t)ncm->cb;
+ cb((void *)ncm->app_data, nnm);
+}
+
+/*
+ * nss_n2h_empty_pool_buf_cfg_core1_callback()
+ * call back function for the n2h connection configuration handler
+ */
+static void nss_n2h_empty_pool_buf_cfg_callback(void *app_data,
+ struct nss_n2h_msg *nnm)
+{
+ int core_num = (int)app_data;
+ if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
+ struct nss_n2h_empty_pool_buf *nnepbcm;
+ nnepbcm = &nnm->msg.empty_pool_buf_cfg;
+
+ /*
+ * Error, hence we are not updating the nss_n2h_empty_pool_buf
+ * Restore the current_value to its previous state
+ */
+ nss_warning("Core %d empty pool buf set failure: %d\n", core_num, nnm->cm.error);
+ nss_n2h_nepbcfgp[core_num].response = NSS_FAILURE;
+ complete(&nss_n2h_nepbcfgp[core_num].complete);
+ return;
+ }
+
+ /*
+ * Sucess at NSS FW, hence updating nss_n2h_empty_pool_buf, with the valid value
+ * saved at the sysctl handler.
+ */
+ nss_info("Core %d empty pool buf set success: %d\n", core_num, nnm->cm.error);
+ nss_n2h_nepbcfgp[core_num].response = NSS_SUCCESS;
+ complete(&nss_n2h_nepbcfgp[core_num].complete);
+}
+
+/*
+ * nss_n2h_empty_pool_buf_core1_handler()
+ * Sets the number of connections for IPv4
+ */
+static int nss_n2h_set_empty_pool_buf(ctl_table *ctl, int write, void __user *buffer,
+ size_t *lenp, loff_t *ppos,
+ int core_num, int *new_val)
+{
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
+ struct nss_n2h_msg nnm;
+ struct nss_n2h_empty_pool_buf *nnepbcm;
+ nss_tx_status_t nss_tx_status;
+ int ret = NSS_FAILURE;
+
+ /*
+ * Acquiring semaphore
+ */
+ down(&nss_n2h_nepbcfgp[core_num].sem);
+
+ /*
+ * Take snap shot of current value
+ */
+ nss_n2h_nepbcfgp[core_num].current_value = *new_val;
+
+ /*
+ * Write the variable with user input
+ */
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ if (ret || (!write)) {
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return ret;
+ }
+
+ /*
+ * Input for n2h should be atleast 2048 to support defalt connections
+ * of 1024 (IPV4) + 1024 (IPV6) connections.
+ */
+ if ((*new_val < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
+ nss_warning("%p: core %d setting %d is less than minimum number of buffer",
+ nss_ctx, core_num, *new_val);
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ *new_val = nss_n2h_nepbcfgp[core_num].current_value;
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return NSS_FAILURE;
+ }
+
+ nss_info("%p: core %d number of empty pool buffer is : %d\n",
+ nss_ctx, core_num, *new_val);
+
+ nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
+ NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG,
+ sizeof(struct nss_n2h_empty_pool_buf),
+ (nss_n2h_msg_callback_t *)nss_n2h_empty_pool_buf_cfg_callback,
+ (void *)core_num);
+
+ nnepbcm = &nnm.msg.empty_pool_buf_cfg;
+ nnepbcm->pool_size = htonl(*new_val);
+ nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
+
+ if (nss_tx_status != NSS_TX_SUCCESS) {
+ nss_warning("%p: core %d nss_tx error setting empty pool buffer: %d\n",
+ nss_ctx, core_num, *new_val);
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ *new_val = nss_n2h_nepbcfgp[core_num].current_value;
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return NSS_FAILURE;
+ }
+
+ /*
+ * Blocking call, wait till we get ACK for this msg.
+ */
+ ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
+ if (ret == 0) {
+ nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx, core_num);
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ *new_val = nss_n2h_nepbcfgp[core_num].current_value;
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return NSS_FAILURE;
+ }
+
+ /*
+ * ACK/NACK received from NSS FW
+ * If ACK: Callback function will update nss_n2h_empty_pool_buf with
+ * nss_n2h_nepbcfgp.num_conn_valid, which holds the user input
+ */
+ if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ *new_val = nss_n2h_nepbcfgp[core_num].current_value;
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return NSS_FAILURE;
+ }
+
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return NSS_SUCCESS;
+}
+
+/*
+ * nss_n2h_empty_pool_buf_core1_handler()
+ * Sets the number of empty buffer for core 1
+ */
+static int nss_n2h_empty_pool_buf_cfg_core1_handler(ctl_table *ctl,
+ int write, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
+ NSS_CORE_1, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1]);
+}
+
+/*
+ * nss_n2h_empty_pool_buf_core0_handler()
+ * Sets the number of empty buffer for core 0
+ */
+static int nss_n2h_empty_pool_buf_cfg_core0_handler(ctl_table *ctl,
+ int write, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
+ NSS_CORE_0, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0]);
+}
+
+static ctl_table nss_n2h_table[] = {
+ {
+ .procname = "n2h_empty_pool_buf_core0",
+ .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0],
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_n2h_empty_pool_buf_cfg_core0_handler,
+ },
+ {
+ .procname = "n2h_empty_pool_buf_core1",
+ .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1],
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_n2h_empty_pool_buf_cfg_core1_handler,
+ },
+
+ { }
+};
+
+static ctl_table nss_n2h_dir[] = {
+ {
+ .procname = "n2hcfg",
+ .mode = 0555,
+ .child = nss_n2h_table,
+ },
+ { }
+};
+
+
+static ctl_table nss_n2h_root_dir[] = {
+ {
+ .procname = "nss",
+ .mode = 0555,
+ .child = nss_n2h_dir,
+ },
+ { }
+};
+
+static ctl_table nss_n2h_root[] = {
+ {
+ .procname = "dev",
+ .mode = 0555,
+ .child = nss_n2h_root_dir,
+ },
+ { }
+};
+
+static struct ctl_table_header *nss_n2h_header;
+
+/*
+ * nss_n2h_msg_init()
+ * Initialize IPv4 message.
+ */
+void nss_n2h_msg_init(struct nss_n2h_msg *nim, uint16_t if_num, uint32_t type,
+ uint32_t len, nss_n2h_msg_callback_t *cb, void *app_data)
+{
+ nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
+}
+
+
+/*
+ * nss_n2h_register_sysctl()
+ * Register sysctl specific to n2h
+ */
+void nss_n2h_empty_pool_buf_register_sysctl(void)
+{
+ /*
+ * Register sysctl table.
+ */
+ nss_n2h_header = register_sysctl_table(nss_n2h_root);
+
+ /*
+ * Core0
+ */
+ sema_init(&nss_n2h_nepbcfgp[NSS_CORE_0].sem, 1);
+ init_completion(&nss_n2h_nepbcfgp[NSS_CORE_0].complete);
+ nss_n2h_nepbcfgp[NSS_CORE_0].current_value = nss_n2h_empty_pool_buf_cfg[NSS_CORE_0];
+
+ /*
+ * Core1
+ */
+ sema_init(&nss_n2h_nepbcfgp[NSS_CORE_1].sem, 1);
+ init_completion(&nss_n2h_nepbcfgp[NSS_CORE_1].complete);
+ nss_n2h_nepbcfgp[NSS_CORE_1].current_value = nss_n2h_empty_pool_buf_cfg[NSS_CORE_1];
+}
+
+/*
+ * nss_n2h_unregister_sysctl()
+ * Unregister sysctl specific to n2h
+ */
+void nss_n2h_empty_pool_buf_unregister_sysctl(void)
+{
+ /*
+ * Unregister sysctl table.
+ */
+ if (nss_n2h_header) {
+ unregister_sysctl_table(nss_n2h_header);
+ }
+}
+
+/*
+ * nss_n2h_tx_msg()
+ * Send messages to NSS n2h pacakge
+ */
+nss_tx_status_t nss_n2h_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_n2h_msg *nnm)
+{
+ struct nss_n2h_msg *nnm2;
+ struct nss_cmn_msg *ncm = &nnm->cm;
+ struct sk_buff *nbuf;
+ nss_tx_status_t status;
+
+ NSS_VERIFY_CTX_MAGIC(nss_ctx);
+ if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+ return NSS_TX_FAILURE_NOT_READY;
+ }
+
+ /*
+ * Sanity check the message
+ */
+ if (ncm->interface != NSS_N2H_INTERFACE) {
+ nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
+ return NSS_TX_FAILURE;
+ }
+
+ if (ncm->type >= NSS_METADATA_TYPE_N2H_MAX) {
+ nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+ return NSS_TX_FAILURE;
+ }
+
+ if (ncm->len > sizeof(struct nss_n2h_msg)) {
+ nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
+ return NSS_TX_FAILURE;
+ }
+
+
+ nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+ if (unlikely(!nbuf)) {
+ spin_lock_bh(&nss_ctx->nss_top->stats_lock);
+ nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
+ spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
+ return NSS_TX_FAILURE;
+ }
+
+ /*
+ * Copy the message to our skb.
+ */
+ nnm2 = (struct nss_n2h_msg *)skb_put(nbuf, sizeof(struct nss_n2h_msg));
+ memcpy(nnm2, nnm, sizeof(struct nss_n2h_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_info("%p: unable to enqueue 'nss frequency change' - marked as stopped\n", nss_ctx);
+ 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_n2h_tx()
+ * Send Message to NSS to enable RPS.
+ *
+ * This API could be used for any additional RPS related
+ * configuration in future.
+ *
+ * TODO: rename to _rps and rewrite assignment from handler to a callback.
+ */
+nss_tx_status_t nss_n2h_tx(struct nss_ctx_instance *nss_ctx, uint32_t enable_rps)
+{
+ struct sk_buff *nbuf;
+ nss_tx_status_t status;
+ struct nss_n2h_msg *nnhm;
+ struct nss_n2h_rps *rps_cfg;
+
+ NSS_VERIFY_CTX_MAGIC(nss_ctx);
+ if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+ return NSS_TX_FAILURE_NOT_READY;
+ }
+
+ nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+ if (unlikely(!nbuf)) {
+ spin_lock_bh(&nss_ctx->nss_top->stats_lock);
+ nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
+ spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
+ return NSS_TX_FAILURE;
+ }
+
+ nnhm = (struct nss_n2h_msg *)skb_put(nbuf, sizeof(struct nss_n2h_msg));
+
+ nss_n2h_msg_init(nnhm, NSS_N2H_INTERFACE, NSS_TX_METADATA_TYPE_N2H_RPS_CFG,
+ sizeof(struct nss_n2h_rps),
+ NULL, NULL);
+
+ rps_cfg = &nnhm->msg.rps_cfg;
+
+ rps_cfg->enable = enable_rps;
+
+ nss_info("n22_n2h_rps_configure %d \n", enable_rps);
+
+ 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_info("%p: unable to enqueue 'nss frequency change' - marked as stopped\n", nss_ctx);
+ 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);
+
+ return NSS_TX_SUCCESS;
+}
+
+/*
+ * nss_n2h_notify_register()
+ * Register to received N2H events.
+ *
+ * NOTE: Do we want to pass an nss_ctx here so that we can register for n2h on any core?
+ */
+struct nss_ctx_instance *nss_n2h_notify_register(int core, nss_n2h_msg_callback_t cb, void *app_data)
+{
+ if (core >= NSS_MAX_CORES) {
+ nss_warning("Input core number %d is wrong \n", core);
+ return NULL;
+ }
+ /*
+ * TODO: We need to have a new array in support of the new API
+ * TODO: If we use a per-context array, we would move the array into nss_ctx based.
+ */
+ nss_n2h_rd[core].n2h_callback = cb;
+ nss_n2h_rd[core].app_data = app_data;
+ return &nss_top_main.nss[core];
}
/*
@@ -171,8 +584,13 @@
{
nss_core_register_handler(NSS_N2H_INTERFACE, nss_n2h_interface_handler, NULL);
+ nss_n2h_notify_register(NSS_CORE_0, NULL, NULL);
+ nss_n2h_notify_register(NSS_CORE_1, NULL, NULL);
+
/*
- * Initialize wait queue
+ * Registering sysctl for n2h empty pool buffer.
*/
- init_waitqueue_head(&nss_n2h_wq);
+ nss_n2h_empty_pool_buf_register_sysctl();
}
+
+EXPORT_SYMBOL(nss_n2h_notify_register);
diff --git a/nss_pm.c b/nss_pm.c
index 65305eb..e8c944f 100644
--- a/nss_pm.c
+++ b/nss_pm.c
@@ -23,7 +23,9 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include "nss_clocks.h"
+#include <nss_api_if.h>
+#if (NSS_PM_SUPPORT == 1)
#include "nss_pm.h"
/*
@@ -188,6 +190,7 @@
DEFINE_SIMPLE_ATTRIBUTE(perf_level_fops, nss_pm_dbg_perf_level_get, nss_pm_dbg_perf_level_set, "%llu\n");
DEFINE_SIMPLE_ATTRIBUTE(autoscale_fops, nss_pm_dbg_autoscale_get, nss_pm_dbg_autoscale_set, "%llu\n");
+#endif /** (NSS_PM_SUPPORT == 1) */
/*
* nss_pm_client_register
@@ -200,6 +203,7 @@
*/
void *nss_pm_client_register(nss_pm_client_t client_id)
{
+#if (NSS_PM_SUPPORT == 1)
int ret;
struct dentry *pm_dentry;
nss_pm_client_data_t *pm_client;
@@ -265,6 +269,7 @@
out:
return (void *)pm_client;
error:
+#endif
return NULL;
}
EXPORT_SYMBOL(nss_pm_client_register);
@@ -275,6 +280,7 @@
*/
int nss_pm_client_unregister(nss_pm_client_t client_id)
{
+#if (NSS_PM_SUPPORT == 1)
nss_pm_client_data_t *pm_client;
if (unlikely(client_id >= NSS_PM_MAX_CLIENTS)) {
@@ -302,6 +308,7 @@
return NSS_PM_API_SUCCESS;
error:
+#endif
return NSS_PM_API_FAILED;
}
@@ -311,6 +318,7 @@
*/
nss_pm_interface_status_t nss_pm_set_perf_level(void *handle, nss_pm_perf_level_t lvl)
{
+#if (NSS_PM_SUPPORT == 1)
int ret = 0;
nss_pm_client_data_t *pm_client;
@@ -377,11 +385,12 @@
nss_pm_info("perf level request, current: %d new: %d \n", pm_client->current_perf_lvl, lvl);
pm_client->current_perf_lvl = lvl;
-
+#endif
return NSS_PM_API_SUCCESS;
}
EXPORT_SYMBOL(nss_pm_set_perf_level);
+#if (NSS_PM_SUPPORT == 1)
/*
* nss_pm_set_turbo()
* Sets the turbo support flag globally for all clients
@@ -409,3 +418,4 @@
nss_pm_warning("Failed to create qca-nss-drv directory in debugfs");
}
}
+#endif
diff --git a/nss_pm.h b/nss_pm.h
index f94cb6a..2a2cb8d 100644
--- a/nss_pm.h
+++ b/nss_pm.h
@@ -22,10 +22,13 @@
#ifndef __NSS_PM_H
#define __NSS_PM_H
+#include<linux/version.h>
+
#include <mach/msm_nss_gmac.h>
#include <mach/msm_nss_crypto.h>
#include <mach/msm_bus_board.h>
#include <mach/msm_bus.h>
+
#include <nss_api_if.h>
/*
diff --git a/nss_pppoe.c b/nss_pppoe.c
index 0cfe3a2..3d5f2a9 100644
--- a/nss_pppoe.c
+++ b/nss_pppoe.c
@@ -222,6 +222,7 @@
*/
static void nss_pppoe_rule_create_success(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_rule_create_success_msg *pcs)
{
+#if (NSS_PPP_SUPPORT == 1)
struct net_device *ppp_dev = ppp_session_to_netdev(pcs->pppoe_session_id, pcs->pppoe_remote_mac);
if (!ppp_dev) {
@@ -240,6 +241,7 @@
}
dev_put(ppp_dev);
+#endif
}
/*
diff --git a/nss_qdisc/Makefile b/nss_qdisc/Makefile
deleted file mode 100755
index 8facfeb..0000000
--- a/nss_qdisc/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-##########################################################################
-# Copyright (c) 2014, 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.
-##########################################################################
-
-ccflags-y := -I$(obj)/../exports -I$(srctree)/net/bridge -DNSS_QDISC_DEBUG_LEVEL=0
-
-obj-m += qca-nss-qdisc.o
-qca-nss-qdisc-objs := nss_qdisc.o \
- nss_fifo.o \
- nss_codel.o \
- nss_tbl.o \
- nss_prio.o \
- nss_bf.o \
- nss_wrr.o \
- nss_htb.o \
- nss_blackhole.o \
- nss_wred.o
diff --git a/nss_qdisc/nss_bf.c b/nss_qdisc/nss_bf.c
deleted file mode 100644
index e7146b7..0000000
--- a/nss_qdisc/nss_bf.c
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_qdisc.h"
-
-struct nss_bf_class_data {
- struct nss_qdisc nq; /* Base class used by nss_qdisc */
- struct Qdisc_class_common cl_common; /* Common class structure */
- u32 rate; /* Allowed bandwidth for this class */
- u32 burst; /* Allowed burst for this class */
- u32 mtu; /* MTU size of the interface */
- u32 quantum; /* Quantum allocation for DRR */
- struct Qdisc *qdisc; /* Pointer to child qdisc */
-};
-
-struct nss_bf_sched_data {
- struct nss_qdisc nq; /* Base class used by nss_qdisc */
- u16 defcls; /* default class id */
- struct nss_bf_class_data root; /* root class */
- struct Qdisc_class_hash clhash; /* class hash */
-};
-
-static inline struct nss_bf_class_data *nss_bf_find_class(u32 classid,
- struct Qdisc *sch)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- struct Qdisc_class_common *clc;
- clc = qdisc_class_find(&q->clhash, classid);
- if (clc == NULL) {
- nss_qdisc_warning("%s: Cannot find class with classid %u in qdisc %p hash table %p\n", __func__, classid, sch, &q->clhash);
- return NULL;
- }
- return container_of(clc, struct nss_bf_class_data, cl_common);
-}
-
-static const struct nla_policy nss_bf_policy[TCA_NSSBF_MAX + 1] = {
- [TCA_NSSBF_CLASS_PARMS] = { .len = sizeof(struct tc_nssbf_class_qopt) },
-};
-
-static int nss_bf_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
- struct nlattr **tca, unsigned long *arg)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- struct nss_bf_class_data *cl = (struct nss_bf_class_data *)*arg;
- struct nlattr *opt = tca[TCA_OPTIONS];
- struct nlattr *na[TCA_NSSBF_MAX + 1];
- struct tc_nssbf_class_qopt *qopt;
- int err;
- struct nss_if_msg nim_config;
- struct net_device *dev = qdisc_dev(sch);
-
- nss_qdisc_info("%s: Changing bf class %u\n", __func__, classid);
- if (opt == NULL)
- return -EINVAL;
-
- err = nla_parse_nested(na, TCA_NSSBF_MAX, opt, nss_bf_policy);
- if (err < 0)
- return err;
-
- if (na[TCA_NSSBF_CLASS_PARMS] == NULL)
- return -EINVAL;
-
- /*
- * If class with a given classid is not found, we allocate a new one
- */
- if (!cl) {
- struct nss_if_msg nim_attach;
- nss_qdisc_info("%s: Bf class %u not found. Allocating a new class.\n", __func__, classid);
- cl = kzalloc(sizeof(struct nss_bf_class_data), GFP_KERNEL);
-
- if (!cl) {
- nss_qdisc_error("%s: Class allocation failed for classid %u\n", __func__, classid);
- return -EINVAL;
- }
-
- nss_qdisc_info("%s: Bf class %u allocated %p\n", __func__, classid, cl);
- cl->cl_common.classid = classid;
-
- /*
- * We make the child qdisc a noop qdisc, and
- * set reference count to 1. This is important,
- * reference count should not be 0.
- */
- cl->qdisc = &noop_qdisc;
- atomic_set(&cl->nq.refcnt, 1);
- *arg = (unsigned long)cl;
-
- nss_qdisc_info("%s: Adding classid %u to qdisc %p hash queue %p\n", __func__, classid, sch, &q->clhash);
-
- /*
- * This is where a class gets initialized. Classes do not have a init function
- * that is registered to Linux. Therefore we initialize the NSSBF_GROUP shaper
- * here.
- */
- if (nss_qdisc_init(sch, &cl->nq, NSS_SHAPER_NODE_TYPE_BF_GROUP, classid) < 0) {
- nss_qdisc_error("%s: Nss init for class %u failed\n", __func__, classid);
- kfree(cl);
- return -EINVAL;
- }
-
- /*
- * Set qos_tag of parent to which the class needs to e attached to.
- */
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
-
- /*
- * Set the child to be this class.
- */
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.snc.bf_attach.child_qos_tag = cl->nq.qos_tag;
-
- /*
- * Send node_attach command down to the NSS
- */
- if (nss_qdisc_node_attach(&q->nq, &cl->nq, &nim_attach,
- NSS_SHAPER_CONFIG_TYPE_BF_ATTACH) < 0) {
- nss_qdisc_error("%s: Nss attach for class %u failed\n", __func__, classid);
- nss_qdisc_destroy(&cl->nq);
- kfree(cl);
- return -EINVAL;
- }
-
- /*
- * Add class to hash tree once it is attached in the NSS
- */
- sch_tree_lock(sch);
- qdisc_class_hash_insert(&q->clhash, &cl->cl_common);
- sch_tree_unlock(sch);
-
- /*
- * Hash grow should not come within the tree lock
- */
- qdisc_class_hash_grow(sch, &q->clhash);
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(&cl->nq);
-
- nss_qdisc_info("%s: Class %u successfully allocated\n", __func__, classid);
- }
-
- qopt = nla_data(na[TCA_NSSBF_CLASS_PARMS]);
-
- sch_tree_lock(sch);
- cl->rate = qopt->rate;
- cl->burst = qopt->burst;
-
- /*
- * If MTU and quantum values are not provided, set them to
- * the interface's MTU value.
- */
- if (!qopt->mtu) {
- cl->mtu = psched_mtu(dev);
- nss_qdisc_info("MTU not provided for bf class on interface %s. "
- "Setting MTU to %u bytes\n", dev->name, cl->mtu);
- } else {
- cl->mtu = qopt->mtu;
- }
-
- if (!qopt->quantum) {
- cl->quantum = psched_mtu(dev);
- nss_qdisc_info("Quantum value not provided for bf class on interface %s. "
- "Setting quantum to %u\n", dev->name, cl->quantum);
- } else {
- cl->quantum = qopt->quantum;
- }
-
- sch_tree_unlock(sch);
-
- /*
- * Fill information that needs to be sent down to the NSS for configuring the
- * bf class.
- */
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.bf_group_param.quantum = cl->quantum;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.bf_group_param.lap.rate = cl->rate;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.bf_group_param.lap.burst = cl->burst;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.bf_group_param.lap.max_size = cl->mtu;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.bf_group_param.lap.short_circuit = false;
-
- nss_qdisc_info("Rate = %u Burst = %u MTU = %u Quantum = %u\n", cl->rate, cl->burst, cl->mtu, cl->quantum);
-
- /*
- * Send configure command to the NSS
- */
- if (nss_qdisc_configure(&cl->nq, &nim_config,
- NSS_SHAPER_CONFIG_TYPE_BF_GROUP_CHANGE_PARAM) < 0) {
- nss_qdisc_error("%s: Failed to configure class %u\n", __func__, classid);
- return -EINVAL;
- }
-
- nss_qdisc_info("%s: Class %u changed successfully\n", __func__, classid);
- return 0;
-}
-
-static void nss_bf_destroy_class(struct Qdisc *sch, struct nss_bf_class_data *cl)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- struct nss_if_msg nim;
-
- nss_qdisc_info("Destroying bf class %p from qdisc %p\n", cl, sch);
-
- /*
- * Note, this function gets called even for NSSBF and not just for NSSBF_GROUP.
- * If this is BF qdisc then we should not call nss_qdisc_destroy or stop polling
- * for stats. These two actions will happen inside nss_bf_destroy(), which is called
- * only for the root qdisc.
- */
- if (cl == &q->root) {
- nss_qdisc_info("%s: We do not destroy bf class %p here since this is "
- "the qdisc %p\n", __func__, cl, sch);
- return;
- }
-
- /*
- * We always have to detach our child qdisc in NSS, before destroying it.
- */
- if (cl->qdisc != &noop_qdisc) {
- struct nss_qdisc *nq_child = qdisc_priv(cl->qdisc);
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- if (nss_qdisc_node_detach(&cl->nq, nq_child, &nim,
- NSS_SHAPER_CONFIG_TYPE_BF_GROUP_DETACH) < 0) {
- nss_qdisc_error("%s: Failed to detach child %x from class %x\n",
- __func__, cl->qdisc->handle, q->nq.qos_tag);
- return;
- }
- }
-
- /*
- * And now we destroy the child.
- */
- qdisc_destroy(cl->qdisc);
-
- /*
- * Stop the stats polling timer and free class
- */
- nss_qdisc_stop_basic_stats_polling(&cl->nq);
-
- /*
- * Destroy the shaper in NSS
- */
- nss_qdisc_destroy(&cl->nq);
-
- /*
- * Free class
- */
- kfree(cl);
-}
-
-static int nss_bf_delete_class(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- struct nss_bf_class_data *cl = (struct nss_bf_class_data *)arg;
- struct nss_if_msg nim;
- int refcnt;
- struct nss_qdisc *nq_child = (struct nss_qdisc *)qdisc_priv(cl->qdisc);
-
- /*
- * Since all classes are leaf nodes in our case, we dont have to make
- * that check.
- */
- if (cl == &q->root)
- return -EBUSY;
-
- /*
- * The message to NSS should be sent to the parent of this class
- */
- nss_qdisc_info("%s: Detaching bf class: %p\n", __func__, cl);
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.bf_detach.child_qos_tag = cl->nq.qos_tag;
- if (nss_qdisc_node_detach(&q->nq, nq_child, &nim,
- NSS_SHAPER_CONFIG_TYPE_BF_DETACH) < 0) {
- return -EINVAL;
- }
-
- sch_tree_lock(sch);
- qdisc_reset(cl->qdisc);
- qdisc_class_hash_remove(&q->clhash, &cl->cl_common);
- refcnt = atomic_sub_return(1, &cl->nq.refcnt);
- sch_tree_unlock(sch);
- if (!refcnt) {
- nss_qdisc_error("%s: Reference count should not be zero for class %p\n", __func__, cl);
- }
-
- return 0;
-}
-
-static int nss_bf_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
- struct Qdisc **old)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- struct nss_bf_class_data *cl = (struct nss_bf_class_data *)arg;
- struct nss_if_msg nim_detach;
- struct nss_if_msg nim_attach;
- struct nss_qdisc *nq_new = qdisc_priv(new);
-
- nss_qdisc_info("Grafting class %p\n", sch);
-
- if (cl == &q->root) {
- nss_qdisc_error("%p: Can't graft root class\n", cl);
- return -EINVAL;
- }
-
- if (new == NULL)
- new = &noop_qdisc;
-
- sch_tree_lock(sch);
- *old = cl->qdisc;
- sch_tree_unlock(sch);
-
- /*
- * Since we initially attached a noop qdisc as child (in Linux),
- * we do not perform a detach in the NSS if its a noop qdisc.
- */
- nss_qdisc_info("%s:Grafting old: %p with new: %p\n", __func__, *old, new);
- if (*old != &noop_qdisc) {
- struct nss_qdisc *nq_old = (struct nss_qdisc *)qdisc_priv(*old);
- nss_qdisc_info("%s: Detaching old: %p\n", __func__, *old);
- nim_detach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- if (nss_qdisc_node_detach(&cl->nq, nq_old, &nim_detach,
- NSS_SHAPER_CONFIG_TYPE_BF_GROUP_DETACH) < 0) {
- return -EINVAL;
- }
- }
-
- /*
- * If the new qdisc is a noop qdisc, we do not send down an attach command
- * to the NSS.
- */
- if (new != &noop_qdisc) {
- nss_qdisc_info("%s: Attaching new: %p\n", __func__, new);
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.snc.bf_group_attach.child_qos_tag = nq_new->qos_tag;
- if (nss_qdisc_node_attach(&cl->nq, nq_new, &nim_attach,
- NSS_SHAPER_CONFIG_TYPE_BF_GROUP_ATTACH) < 0) {
- return -EINVAL;
- }
- }
-
- /*
- * Attach qdisc once it is done in the NSS
- */
- sch_tree_lock(sch);
- cl->qdisc = new;
- sch_tree_unlock(sch);
-
- nss_qdisc_info("Nssbf grafted");
-
- return 0;
-}
-
-static struct Qdisc *nss_bf_leaf_class(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_bf_class_data *cl = (struct nss_bf_class_data *)arg;
- nss_qdisc_info("bf class leaf %p\n", cl);
-
- /*
- * Since all nss_bf groups are leaf nodes, we can always
- * return the attached qdisc.
- */
- return cl->qdisc;
-}
-
-static void nss_bf_qlen_notify(struct Qdisc *sch, unsigned long arg)
-{
- nss_qdisc_info("bf qlen notify %p\n", sch);
- /*
- * Gets called when qlen of child changes (Useful for deactivating)
- * Not useful for us here.
- */
-}
-
-static unsigned long nss_bf_get_class(struct Qdisc *sch, u32 classid)
-{
- struct nss_bf_class_data *cl = nss_bf_find_class(classid, sch);
-
- nss_qdisc_info("Get bf class %p - class match = %p\n", sch, cl);
-
- if (cl != NULL)
- atomic_add(1, &cl->nq.refcnt);
-
- return (unsigned long)cl;
-}
-
-static void nss_bf_put_class(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_bf_class_data *cl = (struct nss_bf_class_data *)arg;
- nss_qdisc_info("bf put class for %p\n", cl);
-
- /*
- * We are safe to destroy the qdisc if the reference count
- * goes down to 0.
- */
- if (atomic_sub_return(1, &cl->nq.refcnt) == 0) {
- nss_bf_destroy_class(sch, cl);
- }
-}
-
-static int nss_bf_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb,
- struct tcmsg *tcm)
-{
- struct nss_bf_class_data *cl = (struct nss_bf_class_data *)arg;
- struct nlattr *opts;
- struct tc_nssbf_class_qopt qopt;
-
- nss_qdisc_info("Dumping class %p of Qdisc %p\n", cl, sch);
-
- qopt.burst = cl->burst;
- qopt.rate = cl->rate;
- qopt.mtu = cl->mtu;
- qopt.quantum = cl->quantum;
-
- /*
- * All bf group nodes are root nodes. i.e. they dont
- * have any mode bf groups attached beneath them.
- */
- tcm->tcm_parent = TC_H_ROOT;
- tcm->tcm_handle = cl->cl_common.classid;
- tcm->tcm_info = cl->qdisc->handle;
-
- opts = nla_nest_start(skb, TCA_OPTIONS);
- if (opts == NULL)
- goto nla_put_failure;
- NLA_PUT(skb, TCA_NSSBF_CLASS_PARMS, sizeof(qopt), &qopt);
- return nla_nest_end(skb, opts);
-
-nla_put_failure:
- nla_nest_cancel(skb, opts);
- return -EMSGSIZE;
-}
-
-static int nss_bf_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)arg;
-
- if (gnet_stats_copy_basic(d, &nq->bstats) < 0 ||
- gnet_stats_copy_queue(d, &nq->qstats) < 0) {
- return -1;
- }
-
- return 0;
-}
-
-static void nss_bf_walk(struct Qdisc *sch, struct qdisc_walker *arg)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- struct hlist_node *n;
- struct nss_bf_class_data *cl;
- unsigned int i;
-
- nss_qdisc_info("In bf walk %p\n", sch);
- if (arg->stop)
- return;
-
- for (i = 0; i < q->clhash.hashsize; i++) {
- hlist_for_each_entry(cl, n, &q->clhash.hash[i],
- cl_common.hnode) {
- if (arg->count < arg->skip) {
- arg->count++;
- continue;
- }
- if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
- arg->stop = 1;
- return;
- }
- arg->count++;
- }
- }
-}
-
-static int nss_bf_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- struct tc_nssbf_qopt *qopt;
- int err;
-
- nss_qdisc_info("Init bf qdisc %p\n", sch);
- if (opt == NULL || nla_len(opt) < sizeof(*qopt))
- return -EINVAL;
- qopt = nla_data(opt);
-
- q->defcls = qopt->defcls;
- err = qdisc_class_hash_init(&q->clhash);
- if (err < 0)
- return err;
-
- q->root.cl_common.classid = sch->handle;
- q->root.qdisc = &noop_qdisc;
-
- qdisc_class_hash_insert(&q->clhash, &q->root.cl_common);
- qdisc_class_hash_grow(sch, &q->clhash);
-
- /*
- * Initialize the NSSBF shaper in NSS
- */
- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_BF, 0) < 0)
- return -EINVAL;
-
- nss_qdisc_info("Nssbf initialized - handle %x parent %x\n", sch->handle, sch->parent);
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(&q->nq);
-
- return 0;
-}
-
-static int nss_bf_change_qdisc(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- struct tc_nssbf_qopt *qopt;
-
- /*
- * NSSBF does not care about the defcls, so we dont send down any
- * configuration parameter.
- */
- nss_qdisc_info("Changing bf qdisc %p\n", sch);
- if (opt == NULL || nla_len(opt) < sizeof(*qopt))
- return -EINVAL;
- qopt = nla_data(opt);
-
- sch_tree_lock(sch);
- q->defcls = qopt->defcls;
- sch_tree_unlock(sch);
-
- return 0;
-}
-
-static void nss_bf_reset_class(struct nss_bf_class_data *cl)
-{
- nss_qdisc_reset(cl->qdisc);
- nss_qdisc_info("Nssbf class resetted %p\n", cl->qdisc);
-}
-
-static void nss_bf_reset_qdisc(struct Qdisc *sch)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- struct nss_bf_class_data *cl;
- struct hlist_node *n;
- unsigned int i;
-
- for (i = 0; i < q->clhash.hashsize; i++) {
- hlist_for_each_entry(cl, n, &q->clhash.hash[i], cl_common.hnode)
- nss_bf_reset_class(cl);
- }
-
- nss_qdisc_reset(sch);
- nss_qdisc_info("Nssbf qdisc resetted %p\n", sch);
-}
-
-static void nss_bf_destroy_qdisc(struct Qdisc *sch)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- struct hlist_node *n, *next;
- struct nss_bf_class_data *cl;
- struct nss_if_msg nim;
- unsigned int i;
-
- /*
- * Destroy all the classes before the root qdisc is destroyed.
- */
- for (i = 0; i < q->clhash.hashsize; i++) {
- hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i], cl_common.hnode) {
-
- /*
- * If this is the root class, we dont have to destroy it. This will be taken
- * care of by the nss_bf_destroy() function.
- */
- if (cl == &q->root) {
- nss_qdisc_info("%s: We do not detach or destroy bf class %p here since this is "
- "the qdisc %p\n", __func__, cl, sch);
- continue;
- }
-
- /*
- * Reduce refcnt by 1 before destroying. This is to
- * ensure that polling of stat stops properly.
- */
- atomic_sub(1, &cl->nq.refcnt);
-
- /*
- * Detach class before destroying it. We dont check for noop qdisc here
- * since we do not attach anu such at init.
- */
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.bf_detach.child_qos_tag = cl->nq.qos_tag;
- if (nss_qdisc_node_detach(&q->nq, &cl->nq, &nim,
- NSS_SHAPER_CONFIG_TYPE_BF_DETACH) < 0) {
- nss_qdisc_error("%s: Node detach failed for qdisc %x class %x\n",
- __func__, cl->nq.qos_tag, q->nq.qos_tag);
- return;
- }
-
- /*
- * Now we can destroy the class.
- */
- nss_bf_destroy_class(sch, cl);
- }
- }
- qdisc_class_hash_destroy(&q->clhash);
-
- /*
- * Stop the polling of basic stats
- */
- nss_qdisc_stop_basic_stats_polling(&q->nq);
-
- /*
- * Now we can go ahead and destroy the qdisc.
- * Note: We dont have to detach ourself from our parent because this
- * will be taken care of by the graft call.
- */
- nss_qdisc_destroy(&q->nq);
- nss_qdisc_info("Nssbf destroyed %p\n", sch);
-}
-
-static int nss_bf_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct nss_bf_sched_data *q = qdisc_priv(sch);
- unsigned char *b = skb_tail_pointer(skb);
- struct tc_nssbf_qopt qopt;
- struct nlattr *nest;
-
- nss_qdisc_info("In bf dump qdisc\n");
-
- nest = nla_nest_start(skb, TCA_OPTIONS);
- if (nest == NULL) {
- goto nla_put_failure;
- }
-
- qopt.defcls = q->defcls;
- NLA_PUT(skb, TCA_NSSBF_QDISC_PARMS, sizeof(qopt), &qopt);
- nla_nest_end(skb, nest);
-
- return skb->len;
-
- nla_put_failure:
- nlmsg_trim(skb, b);
- return -1;
-}
-
-static int nss_bf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- return nss_qdisc_enqueue(skb, sch);
-}
-
-static struct sk_buff *nss_bf_dequeue(struct Qdisc *sch)
-{
- return nss_qdisc_dequeue(sch);
-}
-
-static unsigned int nss_bf_drop(struct Qdisc *sch)
-{
- printk("In bf drop\n");
- return nss_qdisc_drop(sch);
-}
-
-const struct Qdisc_class_ops nss_bf_class_ops = {
- .change = nss_bf_change_class,
- .delete = nss_bf_delete_class,
- .graft = nss_bf_graft_class,
- .leaf = nss_bf_leaf_class,
- .qlen_notify = nss_bf_qlen_notify,
- .get = nss_bf_get_class,
- .put = nss_bf_put_class,
- .dump = nss_bf_dump_class,
- .dump_stats = nss_bf_dump_class_stats,
- .walk = nss_bf_walk
-};
-
-struct Qdisc_ops nss_bf_qdisc_ops __read_mostly = {
- .id = "nssbf",
- .init = nss_bf_init_qdisc,
- .change = nss_bf_change_qdisc,
- .reset = nss_bf_reset_qdisc,
- .destroy = nss_bf_destroy_qdisc,
- .dump = nss_bf_dump_qdisc,
- .enqueue = nss_bf_enqueue,
- .dequeue = nss_bf_dequeue,
- .peek = qdisc_peek_dequeued,
- .drop = nss_bf_drop,
- .cl_ops = &nss_bf_class_ops,
- .priv_size = sizeof(struct nss_bf_sched_data),
- .owner = THIS_MODULE
-};
-
diff --git a/nss_qdisc/nss_bf.h b/nss_qdisc/nss_bf.h
deleted file mode 100644
index d7da15c..0000000
--- a/nss_qdisc/nss_bf.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-extern struct Qdisc_ops nss_bf_qdisc_ops;
diff --git a/nss_qdisc/nss_blackhole.c b/nss_qdisc/nss_blackhole.c
deleted file mode 100644
index 6a4e753..0000000
--- a/nss_qdisc/nss_blackhole.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_qdisc.h"
-
-/*
- * nss_blackhole private qdisc structure
- */
-struct nss_blackhole_sched_data {
- struct nss_qdisc nq; /* Common base class for all nss qdiscs */
- u8 set_default; /* Flag to set qdisc as default qdisc for enqueue */
-};
-
-/*
- * nss_blackhole_enqueue()
- * Enqueue API for nss blackhole qdisc.
- */
-static int nss_blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- return nss_qdisc_enqueue(skb, sch);
-}
-
-/*
- * nss_blackhole_dequeue()
- * Dequeue API for nss blackhole qdisc.
- */
-static struct sk_buff *nss_blackhole_dequeue(struct Qdisc *sch)
-{
- return nss_qdisc_dequeue(sch);
-}
-
-/*
- * nss_blackhole_drop()
- * The following function drops a packet from HLOS queue.
- *
- * Note, this does not drop packets from queues in the NSS. We do not support that.
- */
-static unsigned int nss_blackhole_drop(struct Qdisc *sch)
-{
- nss_qdisc_info("%s: qdisc %x dropping\n", __func__, sch->handle);
- return nss_qdisc_drop(sch);
-}
-
-/*
- * nss_blackhole_reset()
- * Resets the nss blackhole qdisc.
- */
-static void nss_blackhole_reset(struct Qdisc *sch)
-{
- nss_qdisc_info("%s: qdisc %x resetting\n", __func__, sch->handle);
- nss_qdisc_reset(sch);
-}
-
-/*
- * nss_blackhole_destroy()
- * Destroys the nss blackhole qdisc.
- */
-static void nss_blackhole_destroy(struct Qdisc *sch)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)qdisc_priv(sch);
-
- /*
- * Stop the polling of basic stats
- */
- nss_qdisc_stop_basic_stats_polling(nq);
-
- nss_qdisc_info("%s: destroying qdisc %x\n", __func__, sch->handle);
- nss_qdisc_destroy(nq);
-}
-
-/*
- * nss_blackhole policy structure
- */
-static const struct nla_policy nss_blackhole_policy[TCA_NSSBLACKHOLE_MAX + 1] = {
- [TCA_NSSBLACKHOLE_PARMS] = { .len = sizeof(struct tc_nssblackhole_qopt) },
-};
-
-/*
- * nss_blackhole_change()
- * Function call used to configure the parameters of the nss blackhole qdisc.
- */
-static int nss_blackhole_change(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_blackhole_sched_data *q;
- struct nlattr *na[TCA_NSSBLACKHOLE_MAX + 1];
- struct tc_nssblackhole_qopt *qopt;
- int err;
- struct nss_if_msg nim;
-
- q = qdisc_priv(sch);
-
- if (opt == NULL) {
- return -EINVAL;
- }
-
- err = nla_parse_nested(na, TCA_NSSBLACKHOLE_MAX, opt, nss_blackhole_policy);
- if (err < 0)
- return err;
-
- if (na[TCA_NSSBLACKHOLE_PARMS] == NULL)
- return -EINVAL;
-
- qopt = nla_data(na[TCA_NSSBLACKHOLE_PARMS]);
-
- /*
- * Required for basic stats display
- */
- sch->limit = 0;
-
- q->set_default = qopt->set_default;
- nss_qdisc_info("%s: qdisc set_default = %u\n", __func__, qopt->set_default);
-
- /*
- * Underneath nss_bloackhole uses a fifo in the NSS. This is why we are sending down a configuration
- * message to a fifo node. There are no blackhole shaper in the NSS as yet.
- *
- * Note: We simply set the limit of fifo to zero to get the blackhole behavior.
- */
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.fifo_param.limit = 0;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.fifo_param.drop_mode = NSS_SHAPER_FIFO_DROP_MODE_TAIL;
- if (nss_qdisc_configure(&q->nq, &nim, NSS_SHAPER_CONFIG_TYPE_FIFO_CHANGE_PARAM) < 0) {
- nss_qdisc_error("%s: qdisc %x configuration failed\n", __func__, sch->handle);
- return -EINVAL;
- }
-
- /*
- * There is nothing we need to do if the qdisc is not
- * set as default qdisc.
- */
- if (q->set_default == 0)
- return 0;
-
- /*
- * Set this qdisc to be the default qdisc for enqueuing packets.
- */
- if (nss_qdisc_set_default(&q->nq) < 0) {
- nss_qdisc_error("%s: qdisc %x set_default failed\n", __func__, sch->handle);
- return -EINVAL;
- }
-
- nss_qdisc_info("%s: qdisc %x set as default\n", __func__, q->nq.qos_tag);
- return 0;
-}
-
-/*
- * nss_blackhole_init()
- * Initializes a nss blackhole qdisc.
- */
-static int nss_blackhole_init(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
-
- if (opt == NULL)
- return -EINVAL;
-
- nss_qdisc_info("%s: qdisc %x initializing\n", __func__, sch->handle);
- nss_blackhole_reset(sch);
-
- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0) < 0)
- return -EINVAL;
-
- nss_qdisc_info("%s: qdisc %x initialized with parent %x\n", __func__, sch->handle, sch->parent);
- if (nss_blackhole_change(sch, opt) < 0) {
- nss_qdisc_destroy(nq);
- return -EINVAL;
- }
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(nq);
-
- return 0;
-}
-
-/*
- * nss_blackhole_dump()
- * Dumps qdisc parameters for nss blackhole.
- */
-static int nss_blackhole_dump(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct nss_blackhole_sched_data *q;
- struct nlattr *opts = NULL;
- struct tc_nssblackhole_qopt opt;
-
- nss_qdisc_info("%s: qdisc %x dumping!\n", __func__, sch->handle);
-
- q = qdisc_priv(sch);
- if (q == NULL) {
- return -1;
- }
-
- opt.set_default = q->set_default;
-
- opts = nla_nest_start(skb, TCA_OPTIONS);
- if (opts == NULL) {
- goto nla_put_failure;
- }
- if (nla_put(skb, TCA_NSSBLACKHOLE_PARMS, sizeof(opt), &opt))
- goto nla_put_failure;
-
- return nla_nest_end(skb, opts);
-
-nla_put_failure:
- nla_nest_cancel(skb, opts);
- return -EMSGSIZE;
-}
-
-/*
- * nss_blackhole_peek()
- * Peeks the first packet in queue for this qdisc.
- *
- * Note: This just peeks at the first packet in what is present in HLOS. This does not
- * perform an actual peak into the queue in the NSS. Given the async delay between
- * the processors, there is less use in implementing this function.
- */
-static struct sk_buff *nss_blackhole_peek(struct Qdisc *sch)
-{
- nss_qdisc_info("%s: qdisc %x peeked\n", __func__, sch->handle);
- return nss_qdisc_peek(sch);
-}
-
-/*
- * Registration structure for nss blackhole qdisc
- */
-struct Qdisc_ops nss_blackhole_qdisc_ops __read_mostly = {
- .id = "nssblackhole",
- .priv_size = sizeof(struct nss_blackhole_sched_data),
- .enqueue = nss_blackhole_enqueue,
- .dequeue = nss_blackhole_dequeue,
- .peek = nss_blackhole_peek,
- .drop = nss_blackhole_drop,
- .init = nss_blackhole_init,
- .reset = nss_blackhole_reset,
- .destroy = nss_blackhole_destroy,
- .change = nss_blackhole_change,
- .dump = nss_blackhole_dump,
- .owner = THIS_MODULE,
-};
diff --git a/nss_qdisc/nss_blackhole.h b/nss_qdisc/nss_blackhole.h
deleted file mode 100644
index 58dce8b..0000000
--- a/nss_qdisc/nss_blackhole.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-extern struct Qdisc_ops nss_blackhole_qdisc_ops;
diff --git a/nss_qdisc/nss_codel.c b/nss_qdisc/nss_codel.c
deleted file mode 100644
index 36517d7..0000000
--- a/nss_qdisc/nss_codel.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_qdisc.h"
-
-struct nss_codel_stats {
- u32 peak_queue_delay; /* Peak delay experienced by a dequeued packet */
- u32 peak_drop_delay; /* Peak delay experienced by a packet that is dropped */
-};
-
-struct nss_codel_sched_data {
- struct nss_qdisc nq; /* Common base class for all nss qdiscs */
- u32 target; /* Acceptable value of queue delay */
- u32 limit; /* Length of queue */
- u32 interval; /* Monitoring interval */
- u8 set_default; /* Flag to set qdisc as default qdisc for enqueue */
- struct nss_codel_stats stats; /* Contains nss_codel related stats */
-};
-
-static int nss_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- return nss_qdisc_enqueue(skb, sch);
-}
-
-static struct sk_buff *nss_codel_dequeue(struct Qdisc *sch)
-{
- return nss_qdisc_dequeue(sch);
-}
-
-static unsigned int nss_codel_drop(struct Qdisc *sch)
-{
- return nss_qdisc_drop(sch);
-}
-
-static void nss_codel_reset(struct Qdisc *sch)
-{
- nss_qdisc_info("nss_codel resetting!");
- nss_qdisc_reset(sch);
-}
-
-static void nss_codel_destroy(struct Qdisc *sch)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
- /*
- * Stop the polling of basic stats
- */
- nss_qdisc_stop_basic_stats_polling(nq);
- nss_qdisc_destroy(nq);
- nss_qdisc_info("nss_codel destroyed");
-}
-
-static const struct nla_policy nss_codel_policy[TCA_NSSCODEL_MAX + 1] = {
- [TCA_NSSCODEL_PARMS] = { .len = sizeof(struct tc_nsscodel_qopt) },
-};
-
-static int nss_codel_change(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_codel_sched_data *q;
- struct nlattr *na[TCA_NSSCODEL_MAX + 1];
- struct tc_nsscodel_qopt *qopt;
- struct nss_if_msg nim;
- int err;
- struct net_device *dev = qdisc_dev(sch);
-
- q = qdisc_priv(sch);
-
- if (opt == NULL)
- return -EINVAL;
-
- err = nla_parse_nested(na, TCA_NSSCODEL_MAX, opt, nss_codel_policy);
- if (err < 0)
- return err;
-
- if (na[TCA_NSSCODEL_PARMS] == NULL)
- return -EINVAL;
-
- qopt = nla_data(na[TCA_NSSCODEL_PARMS]);
-
- if (!qopt->target || !qopt->interval) {
- nss_qdisc_error("nss_codel requires a non-zero value for target "
- "and interval\n");
- return -EINVAL;
- }
-
- if (!qopt->limit)
- qopt->limit = dev->tx_queue_len ? : 1;
-
- q->target = qopt->target;
- q->limit = qopt->limit;
- q->interval = qopt->interval;
- q->set_default = qopt->set_default;
-
- /*
- * Required for basic stats display
- */
- sch->limit = qopt->limit;
-
- nss_qdisc_info("Target:%u Limit:%u Interval:%u set_default = %u\n",
- q->target, q->limit, q->interval, qopt->set_default);
-
-
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- /*
- * Target and interval time needs to be provided in milliseconds
- * (tc provides us the time in mircoseconds and therefore we divide by 1000)
- */
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.codel_param.qlen_max = q->limit;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.codel_param.cap.interval = q->interval/1000;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.codel_param.cap.target = q->target/1000;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.codel_param.cap.mtu = psched_mtu(dev);
- nss_qdisc_info("%s: MTU size of interface %s is %u bytes\n", __func__, dev->name,
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.codel_param.cap.mtu);
-
- if (nss_qdisc_configure(&q->nq, &nim,
- NSS_SHAPER_CONFIG_TYPE_CODEL_CHANGE_PARAM) < 0) {
- return -EINVAL;
- }
-
- /*
- * There is nothing we need to do if the qdisc is not
- * set as default qdisc.
- */
- if (!q->set_default)
- return 0;
-
- /*
- * Set this qdisc to be the default qdisc for enqueuing packets.
- */
- if (nss_qdisc_set_default(&q->nq) < 0)
- return -EINVAL;
-
- return 0;
-}
-
-static int nss_codel_init(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
-
- if (opt == NULL)
- return -EINVAL;
-
- nss_codel_reset(sch);
- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_CODEL, 0) < 0)
- return -EINVAL;
-
- if (nss_codel_change(sch, opt) < 0) {
- nss_qdisc_destroy(nq);
- return -EINVAL;
- }
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(nq);
-
- return 0;
-}
-
-static int nss_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct nss_codel_sched_data *q;
- struct nlattr *opts = NULL;
- struct tc_nsscodel_qopt opt;
-
- nss_qdisc_info("NssCodel Dumping!");
-
- q = qdisc_priv(sch);
- if (q == NULL) {
- return -1;
- }
-
- opt.target = q->target;
- opt.limit = q->limit;
- opt.interval = q->interval;
- opt.set_default = q->set_default;
- opts = nla_nest_start(skb, TCA_OPTIONS);
- if (opts == NULL) {
- goto nla_put_failure;
- }
- if (nla_put(skb, TCA_NSSCODEL_PARMS, sizeof(opt), &opt))
- goto nla_put_failure;
-
- return nla_nest_end(skb, opts);
-
-nla_put_failure:
- nla_nest_cancel(skb, opts);
- return -EMSGSIZE;
-}
-
-static int nss_codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
-{
- struct nss_codel_sched_data *q = qdisc_priv(sch);
- struct tc_nsscodel_xstats st = {
- .peak_queue_delay = q->nq.basic_stats_latest.packet_latency_peak_msec_dequeued,
- .peak_drop_delay = q->nq.basic_stats_latest.packet_latency_peak_msec_dropped,
- };
-
- return gnet_stats_copy_app(d, &st, sizeof(st));
-}
-
-static struct sk_buff *nss_codel_peek(struct Qdisc *sch)
-{
- nss_qdisc_info("Nsscodel Peeking");
- return nss_qdisc_peek(sch);
-}
-
-
-struct Qdisc_ops nss_codel_qdisc_ops __read_mostly = {
- .id = "nsscodel",
- .priv_size = sizeof(struct nss_codel_sched_data),
- .enqueue = nss_codel_enqueue,
- .dequeue = nss_codel_dequeue,
- .peek = nss_codel_peek,
- .drop = nss_codel_drop,
- .init = nss_codel_init,
- .reset = nss_codel_reset,
- .destroy = nss_codel_destroy,
- .change = nss_codel_change,
- .dump = nss_codel_dump,
- .dump_stats = nss_codel_dump_stats,
- .owner = THIS_MODULE,
-};
diff --git a/nss_qdisc/nss_codel.h b/nss_qdisc/nss_codel.h
deleted file mode 100644
index d01643b..0000000
--- a/nss_qdisc/nss_codel.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-extern struct Qdisc_ops nss_codel_qdisc_ops;
diff --git a/nss_qdisc/nss_fifo.c b/nss_qdisc/nss_fifo.c
deleted file mode 100644
index 7f4ab45..0000000
--- a/nss_qdisc/nss_fifo.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_qdisc.h"
-
-struct nss_fifo_sched_data {
- struct nss_qdisc nq; /* Common base class for all nss qdiscs */
- u32 limit; /* Queue length in packets */
- /* TODO: Support for queue length in bytes */
- u8 set_default; /* Flag to set qdisc as default qdisc for enqueue */
-};
-
-static int nss_fifo_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- return nss_qdisc_enqueue(skb, sch);
-}
-
-static struct sk_buff *nss_fifo_dequeue(struct Qdisc *sch)
-{
- return nss_qdisc_dequeue(sch);
-}
-
-static unsigned int nss_fifo_drop(struct Qdisc *sch)
-{
- nss_qdisc_info("nss_fifo dropping");
- return nss_qdisc_drop(sch);
-}
-
-static void nss_fifo_reset(struct Qdisc *sch)
-{
- nss_qdisc_info("nss_fifo resetting!");
- nss_qdisc_reset(sch);
-}
-
-static void nss_fifo_destroy(struct Qdisc *sch)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)qdisc_priv(sch);
-
- /*
- * Stop the polling of basic stats
- */
- nss_qdisc_stop_basic_stats_polling(nq);
-
- nss_qdisc_destroy(nq);
- nss_qdisc_info("nss_fifo destroyed");
-}
-
-static const struct nla_policy nss_fifo_policy[TCA_NSSFIFO_MAX + 1] = {
- [TCA_NSSFIFO_PARMS] = { .len = sizeof(struct tc_nssfifo_qopt) },
-};
-
-static int nss_fifo_change(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_fifo_sched_data *q;
- struct nlattr *na[TCA_NSSFIFO_MAX + 1];
- struct tc_nssfifo_qopt *qopt;
- int err;
- struct nss_if_msg nim;
-
- q = qdisc_priv(sch);
-
- if (opt == NULL) {
- return -EINVAL;
- }
-
- err = nla_parse_nested(na, TCA_NSSFIFO_MAX, opt, nss_fifo_policy);
- if (err < 0)
- return err;
-
- if (na[TCA_NSSFIFO_PARMS] == NULL)
- return -EINVAL;
-
- qopt = nla_data(na[TCA_NSSFIFO_PARMS]);
-
- if (!qopt->limit)
- qopt->limit = qdisc_dev(sch)->tx_queue_len ? : 1;
-
- q->limit = qopt->limit;
-
- /*
- * Required for basic stats display
- */
- sch->limit = qopt->limit;
-
- q->set_default = qopt->set_default;
- nss_qdisc_info("%s: limit:%u set_default:%u\n", __func__, qopt->limit, qopt->set_default);
-
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.fifo_param.limit = q->limit;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.fifo_param.drop_mode = NSS_SHAPER_FIFO_DROP_MODE_TAIL;
- if (nss_qdisc_configure(&q->nq, &nim, NSS_SHAPER_CONFIG_TYPE_FIFO_CHANGE_PARAM) < 0) {
- nss_qdisc_error("%s: nss_fifo %p configuration failed\n", __func__, sch);
- return -EINVAL;
- }
-
- /*
- * There is nothing we need to do if the qdisc is not
- * set as default qdisc.
- */
- if (q->set_default == 0)
- return 0;
-
- /*
- * Set this qdisc to be the default qdisc for enqueuing packets.
- */
- if (nss_qdisc_set_default(&q->nq) < 0) {
- nss_qdisc_error("%s: nss_fifo %p set_default failed\n", __func__, sch);
- return -EINVAL;
- }
-
- nss_qdisc_info("%s: nss_fifo queue (qos_tag:%u) set as default\n", __func__, q->nq.qos_tag);
- return 0;
-}
-
-static int nss_fifo_init(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
-
- if (opt == NULL)
- return -EINVAL;
-
- nss_qdisc_info("Initializing Fifo - type %d\n", NSS_SHAPER_NODE_TYPE_FIFO);
- nss_fifo_reset(sch);
-
- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0) < 0)
- return -EINVAL;
-
- nss_qdisc_info("NSS fifo initialized - handle %x parent %x\n", sch->handle, sch->parent);
- if (nss_fifo_change(sch, opt) < 0) {
- nss_qdisc_destroy(nq);
- return -EINVAL;
- }
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(nq);
-
- return 0;
-}
-
-static int nss_fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct nss_fifo_sched_data *q;
- struct nlattr *opts = NULL;
- struct tc_nssfifo_qopt opt;
-
- nss_qdisc_info("Nssfifo Dumping!");
-
- q = qdisc_priv(sch);
- if (q == NULL) {
- return -1;
- }
-
- opt.limit = q->limit;
- opt.set_default = q->set_default;
-
- opts = nla_nest_start(skb, TCA_OPTIONS);
- if (opts == NULL) {
- goto nla_put_failure;
- }
- if (nla_put(skb, TCA_NSSFIFO_PARMS, sizeof(opt), &opt))
- goto nla_put_failure;
-
- return nla_nest_end(skb, opts);
-
-nla_put_failure:
- nla_nest_cancel(skb, opts);
- return -EMSGSIZE;
-}
-
-static struct sk_buff *nss_fifo_peek(struct Qdisc *sch)
-{
- nss_qdisc_info("Nssfifo Peeking");
- return nss_qdisc_peek(sch);
-}
-
-struct Qdisc_ops nss_pfifo_qdisc_ops __read_mostly = {
- .id = "nsspfifo",
- .priv_size = sizeof(struct nss_fifo_sched_data),
- .enqueue = nss_fifo_enqueue,
- .dequeue = nss_fifo_dequeue,
- .peek = nss_fifo_peek,
- .drop = nss_fifo_drop,
- .init = nss_fifo_init,
- .reset = nss_fifo_reset,
- .destroy = nss_fifo_destroy,
- .change = nss_fifo_change,
- .dump = nss_fifo_dump,
- .owner = THIS_MODULE,
-};
-
-struct Qdisc_ops nss_bfifo_qdisc_ops __read_mostly = {
- .id = "nssbfifo",
- .priv_size = sizeof(struct nss_fifo_sched_data),
- .enqueue = nss_fifo_enqueue,
- .dequeue = nss_fifo_dequeue,
- .peek = nss_fifo_peek,
- .drop = nss_fifo_drop,
- .init = nss_fifo_init,
- .reset = nss_fifo_reset,
- .destroy = nss_fifo_destroy,
- .change = nss_fifo_change,
- .dump = nss_fifo_dump,
- .owner = THIS_MODULE,
-};
diff --git a/nss_qdisc/nss_fifo.h b/nss_qdisc/nss_fifo.h
deleted file mode 100644
index 3635dfe..0000000
--- a/nss_qdisc/nss_fifo.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-extern struct Qdisc_ops nss_pfifo_qdisc_ops;
-extern struct Qdisc_ops nss_bfifo_qdisc_ops;
diff --git a/nss_qdisc/nss_htb.c b/nss_qdisc/nss_htb.c
deleted file mode 100644
index 263f631..0000000
--- a/nss_qdisc/nss_htb.c
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_qdisc.h"
-
-#define NSS_HTB_MAX_PRIORITY 4
-
-/*
- * nss_htb class instance structure
- */
-struct nss_htb_class_data {
- struct nss_qdisc nq; /* Base class used by nss_qdisc */
- struct Qdisc_class_common sch_common; /* Common class structure for scheduler use */
- struct nss_htb_class_data *parent; /* Pointer to our parent class */
- struct Qdisc *qdisc; /* Child qdisc, used by leaf classes */
- int children; /* Count of number of attached child classes */
- bool is_leaf; /* True if leaf class */
-
- u32 rate; /* Allowed bandwidth for this class */
- u32 burst; /* Allowed burst for this class */
- u32 crate; /* Ceil bandwidth for this class */
- u32 cburst; /* Ceil burst for this class */
- u32 quantum; /* Quantum allocation for DRR */
- u32 priority; /* Priority value of this class */
- u32 overhead; /* Overhead in bytes to be added for each packet */
-};
-
-/*
- * nss_htb qdisc instance structure
- */
-struct nss_htb_sched_data {
- struct nss_qdisc nq; /* Base class used by nss_qdisc */
- u16 r2q; /* The rate to quantum conversion ratio */
- struct nss_htb_class_data root; /* Root class */
- struct Qdisc_class_hash clhash; /* Class hash */
-};
-
-/*
- * nss_htb_find_class()
- * Returns a pointer to class if classid matches with a class under this qdisc.
- */
-static inline struct nss_htb_class_data *nss_htb_find_class(u32 classid, struct Qdisc *sch)
-{
- struct nss_htb_sched_data *q = qdisc_priv(sch);
- struct Qdisc_class_common *clc;
- clc = qdisc_class_find(&q->clhash, classid);
- if (clc == NULL) {
- nss_qdisc_warning("%s: cannot find class with classid %x in qdisc %x hash\n",
- __func__, classid, sch->handle);
- return NULL;
- }
- return container_of(clc, struct nss_htb_class_data, sch_common);
-}
-
-/*
- * nss_htb_policy structure
- */
-static const struct nla_policy nss_htb_policy[TCA_NSSHTB_MAX + 1] = {
- [TCA_NSSHTB_CLASS_PARMS] = { .len = sizeof(struct tc_nsshtb_class_qopt) },
-};
-
-/*
- * nss_htb_change_class()
- * Configures a new class.
- */
-static int nss_htb_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
- struct nlattr **tca, unsigned long *arg)
-{
- struct nss_htb_sched_data *q = qdisc_priv(sch);
- struct nss_htb_class_data *cl = (struct nss_htb_class_data *)*arg;
- struct nss_htb_class_data *parent;
- struct nss_qdisc *nq_parent;
- struct nlattr *opt = tca[TCA_OPTIONS];
- struct nlattr *na[TCA_NSSHTB_MAX + 1];
- struct tc_nsshtb_class_qopt *qopt;
- int err;
- struct nss_if_msg nim_config;
- struct net_device *dev = qdisc_dev(sch);
- unsigned int mtu = psched_mtu(dev);
-
- nss_qdisc_trace("%s: configuring htb class %x of qdisc %x\n", __func__, classid, sch->handle);
-
- if (opt == NULL) {
- nss_qdisc_error("%s: passing null opt for configuring htb class %x\n", __func__, classid);
- return -EINVAL;
- }
-
- err = nla_parse_nested(na, TCA_NSSHTB_MAX, opt, nss_htb_policy);
- if (err < 0) {
- nss_qdisc_error("%s: failed to parse configuration parameters for htb class %x\n",
- __func__, classid);
- return err;
- }
-
- if (na[TCA_NSSHTB_CLASS_PARMS] == NULL) {
- nss_qdisc_error("%s: parsed values have no content - htb class %x\n", __func__, classid);
- return -EINVAL;
- }
-
- parent = (parentid == TC_H_ROOT) ? NULL : nss_htb_find_class(parentid, sch);
-
- /*
- * The parent could be the htb qdisc, or a class. We set nq_parent pointer
- * accordingly.
- */
- if (parent) {
- nq_parent = &parent->nq;
- } else {
- nq_parent = &q->nq;
- }
-
- /*
- * If class with a given classid is not found, we allocate a new one
- */
- if (!cl) {
- struct nss_if_msg nim_attach;
-
- /*
- * check for valid classid
- */
- if (!classid || TC_H_MAJ(classid ^ sch->handle) || nss_htb_find_class(classid, sch)) {
- goto failure;
- }
-
- /*
- * TODO: We are not setting a limit on the tree depth
- * do we have to set one?
- */
-
- nss_qdisc_trace("%s: htb class %x not found. Allocating a new class.\n", __func__, classid);
- cl = kzalloc(sizeof(struct nss_htb_class_data), GFP_KERNEL);
-
- if (!cl) {
- nss_qdisc_error("%s: class allocation failed for classid %x\n", __func__, classid);
- goto failure;
- }
-
- nss_qdisc_trace("%s: htb class %x allocated - addr %p\n", __func__, classid, cl);
- cl->parent = parent;
- cl->sch_common.classid = classid;
-
- /*
- * Set this class as leaf. If a new class is attached as
- * child, it will set this value to false during the attach
- * process.
- */
- cl->is_leaf = true;
-
- /*
- * We make the child qdisc a noop qdisc, and
- * set reference count to 1. This is important,
- * reference count should not be 0.
- */
- cl->qdisc = &noop_qdisc;
- atomic_set(&cl->nq.refcnt, 1);
- *arg = (unsigned long)cl;
-
- nss_qdisc_trace("%s: adding class %x to qdisc %x\n", __func__, classid, sch->handle);
-
- /*
- * This is where a class gets initialized. Classes do not have a init function
- * that is registered to Linux. Therefore we initialize the NSSHTB_GROUP shaper
- * here.
- */
- if (nss_qdisc_init(sch, &cl->nq, NSS_SHAPER_NODE_TYPE_HTB_GROUP, classid) < 0) {
- nss_qdisc_error("%s: nss_init for htb class %x failed\n", __func__, classid);
- goto failure;
- }
-
- /*
- * Set qos_tag of parent to which the class needs to e attached to.
- */
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = nq_parent->qos_tag;
-
- /*
- * Set the child to be this class.
- */
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_attach.child_qos_tag = cl->nq.qos_tag;
-
- /*
- * Send node_attach command down to the NSS
- */
- if (nss_qdisc_node_attach(nq_parent, &cl->nq, &nim_attach,
- NSS_SHAPER_CONFIG_TYPE_SHAPER_NODE_ATTACH) < 0) {
- nss_qdisc_error("%s: nss_attach for class %x failed\n", __func__, classid);
- nss_qdisc_destroy(&cl->nq);
- goto failure;
- }
-
- /*
- * We have successfully attached ourselves in the NSS. We can therefore
- * add this class to qdisc hash tree, and increment parent's child count
- * (if parent exists)
- */
- sch_tree_lock(sch);
- qdisc_class_hash_insert(&q->clhash, &cl->sch_common);
- if (parent) {
- parent->children++;
-
- /*
- * Parent can no longer be leaf. Set flag to false.
- */
- parent->is_leaf = false;
- }
- sch_tree_unlock(sch);
-
- /*
- * Hash grow should not come within the tree lock
- */
- qdisc_class_hash_grow(sch, &q->clhash);
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(&cl->nq);
-
- nss_qdisc_trace("%s: class %x successfully allocated and initialized\n", __func__, classid);
- }
-
- qopt = nla_data(na[TCA_NSSHTB_CLASS_PARMS]);
-
- if (qopt->rate && !qopt->burst) {
- nss_qdisc_error("%s: burst needed if rate is non zero - class %x\n", __func__, classid);
- return -EINVAL;
- }
-
- if (!qopt->crate || !qopt->cburst) {
- nss_qdisc_error("%s: crate and cburst need to be non zero - class %x\n",
- __func__, classid);
- return -EINVAL;
- }
-
- if (!(qopt->priority < NSS_HTB_MAX_PRIORITY)) {
- nss_qdisc_error("%s: priority %u of htb class %x greater than max prio %u",
- __func__, qopt->priority, classid, NSS_HTB_MAX_PRIORITY);
- return -EINVAL;
- }
-
- sch_tree_lock(sch);
- cl->rate = qopt->rate;
- cl->burst = qopt->burst;
- cl->crate = qopt->crate;
- cl->cburst = qopt->cburst;
- cl->overhead = qopt->overhead;
- cl->quantum = qopt->quantum;
- cl->priority = qopt->priority;
-
- /*
- * If quantum value is not provided, set it to
- * the interface's MTU value.
- */
- if (!cl->quantum) {
- /*
- * If quantum was not provided, we have two options.
- * One, use r2q and rate to figure out the quantum. Else,
- * use the interface's MTU as the value of quantum.
- */
- if (q->r2q && cl->rate) {
- cl->quantum = (cl->rate / q->r2q) / 8;
- nss_qdisc_info("%s: quantum not provided for htb class %x on interface %s\n"
- "Setting quantum to %uB based on r2q %u and rate %uBps\n",
- __func__, classid, dev->name, cl->quantum, q->r2q, cl->rate / 8);
- } else {
- cl->quantum = mtu;
- nss_qdisc_info("%s: quantum value not provided for htb class %x on interface %s\n"
- "Setting quantum to MTU %uB\n", __func__, classid, dev->name, cl->quantum);
- }
- }
-
- sch_tree_unlock(sch);
-
- /*
- * Fill information that needs to be sent down to the NSS for configuring the
- * htb class.
- */
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.quantum = cl->quantum;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.priority = cl->priority;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.overhead = cl->overhead;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.rate_police.rate = cl->rate;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.rate_police.burst = cl->burst;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.rate_police.max_size = mtu;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.rate_police.short_circuit = false;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.rate_ceil.rate = cl->crate;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.rate_ceil.burst = cl->cburst;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.rate_ceil.max_size = mtu;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_param.rate_ceil.short_circuit = false;
-
- nss_qdisc_info("%s: htb class %x - rate = %ubps burst = %ubytes crate = %ubps cburst = %ubytes MTU = %ubytes "
- "quantum = %ubytes priority = %u\n", __func__, classid, cl->rate, cl->burst, cl->crate,
- cl->cburst, mtu, cl->quantum, cl->priority);
-
- /*
- * Send configure command to the NSS
- */
- if (nss_qdisc_configure(&cl->nq, &nim_config,
- NSS_SHAPER_CONFIG_TYPE_SHAPER_NODE_CHANGE_PARAM) < 0) {
- nss_qdisc_error("%s: failed to send configure message for htb class %x\n", __func__, classid);
- return -EINVAL;
- }
-
- nss_qdisc_info("%s: htb class %x configured successfully\n", __func__, classid);
- return 0;
-
-failure:
- if (cl) {
- kfree(cl);
- }
- return -EINVAL;
-}
-
-/*
- * nss_htb_destroy_class()
- * Detaches all child nodes and destroys the class.
- */
-static void nss_htb_destroy_class(struct Qdisc *sch, struct nss_htb_class_data *cl)
-{
- struct nss_htb_sched_data *q __attribute__((unused)) = qdisc_priv(sch);
- struct nss_if_msg nim;
- struct nss_qdisc *nq_child;
-
- nss_qdisc_trace("%s: destroying htb class %x from qdisc %x\n", __func__,
- cl->nq.qos_tag, sch->handle);
-
- /*
- * We always have to detach the child qdisc, before destroying it.
- */
- if (cl->qdisc != &noop_qdisc) {
- nq_child = qdisc_priv(cl->qdisc);
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_detach.child_qos_tag = nq_child->qos_tag;
- if (nss_qdisc_node_detach(&cl->nq, nq_child, &nim,
- NSS_SHAPER_CONFIG_TYPE_SHAPER_NODE_DETACH) < 0) {
- nss_qdisc_error("%s: failed to detach child %x from class %x\n",
- __func__, cl->qdisc->handle, q->nq.qos_tag);
- return;
- }
- }
-
- /*
- * And now we destroy the child.
- */
- qdisc_destroy(cl->qdisc);
-
- /*
- * Stop the stats polling timer and free class
- */
- nss_qdisc_stop_basic_stats_polling(&cl->nq);
-
- /*
- * Destroy the shaper in NSS
- */
- nss_qdisc_destroy(&cl->nq);
-
- /*
- * Free class
- */
- kfree(cl);
-}
-
-/*
- * nss_htb_delete_class()
- * Detaches a class from operation, but does not destroy it.
- */
-static int nss_htb_delete_class(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_htb_sched_data *q = qdisc_priv(sch);
- struct nss_htb_class_data *cl = (struct nss_htb_class_data *)arg;
- struct nss_if_msg nim;
- int refcnt;
-
- /*
- * If the class still has child nodes, then we do not
- * support deleting it.
- */
- if (cl->children) {
- return -EBUSY;
- }
-
- /*
- * Check if we are root class or not (parent pointer is NULL for a root class)
- */
- if (cl->parent) {
-
- /*
- * The htb class to be detached has a parent class (i.e. not the root class),
- * so we need to send a detach msg to its parent class.
- */
- nss_qdisc_info("%s: detaching from parent htb class %x ", __func__, cl->parent->nq.qos_tag);
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->parent->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_detach.child_qos_tag = cl->nq.qos_tag;
- if (nss_qdisc_node_detach(&q->nq, &cl->nq, &nim, NSS_SHAPER_CONFIG_TYPE_SHAPER_NODE_DETACH) < 0) {
- return -EINVAL;
- }
- } else {
- /*
- * The message to NSS should be sent to the parent of this class
- */
- nss_qdisc_info("%s: detaching from parent htb qdisc %x", __func__, q->nq.qos_tag);
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- if (nss_qdisc_node_detach(&q->nq, &cl->nq, &nim, NSS_SHAPER_CONFIG_TYPE_SHAPER_NODE_DETACH) < 0) {
- return -EINVAL;
- }
- }
-
- sch_tree_lock(sch);
- qdisc_reset(cl->qdisc);
- qdisc_class_hash_remove(&q->clhash, &cl->sch_common);
-
- /*
- * If we are root class, we dont have to update our parent.
- * We simply deduct refcnt and return.
- */
- if (!cl->parent) {
- refcnt = atomic_sub_return(1, &cl->nq.refcnt);
- sch_tree_unlock(sch);
- return 0;
- }
-
- /*
- * We are not root class. Therefore we reduce the children count
- * for our parent and also update its 'is_leaf' status.
- */
- cl->parent->children--;
- if (!cl->parent->children) {
- cl->parent->is_leaf = true;
- }
-
- /*
- * Decrement refcnt and return
- */
- refcnt = atomic_sub_return(1, &cl->nq.refcnt);
- sch_tree_unlock(sch);
-
- return 0;
-}
-
-/*
- * nss_htb_graft_class()
- * Replaces the qdisc attached to the provided class.
- */
-static int nss_htb_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, struct Qdisc **old)
-{
- struct nss_htb_class_data *cl = (struct nss_htb_class_data *)arg;
- struct nss_if_msg nim_detach;
- struct nss_if_msg nim_attach;
- struct nss_qdisc *nq_new = qdisc_priv(new);
- struct nss_qdisc *nq_old;
-
- nss_qdisc_trace("%s: grafting htb class %x\n", __func__, cl->nq.qos_tag);
-
- if (new == NULL) {
- new = &noop_qdisc;
- }
-
- sch_tree_lock(sch);
- *old = cl->qdisc;
- sch_tree_unlock(sch);
-
- /*
- * Since we initially attached a noop qdisc as child (in Linux),
- * we do not perform a detach in the NSS if its a noop qdisc.
- */
- nss_qdisc_info("%s: grafting old: %x with new: %x\n", __func__, (*old)->handle, new->handle);
- if (*old != &noop_qdisc) {
- nss_qdisc_trace("%s: detaching old: %x\n", __func__, (*old)->handle);
- nq_old = qdisc_priv(*old);
- nim_detach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- nim_detach.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_detach.child_qos_tag = nq_old->qos_tag;
- if (nss_qdisc_node_detach(&cl->nq, nq_old, &nim_detach,
- NSS_SHAPER_CONFIG_TYPE_SHAPER_NODE_DETACH) < 0) {
- nss_qdisc_error("%s: detach of old qdisc %x failed\n", __func__, (*old)->handle);
- return -EINVAL;
- }
- }
-
- /*
- * If the new qdisc is a noop qdisc, we do not send down an attach command
- * to the NSS.
- */
- if (new != &noop_qdisc) {
- nss_qdisc_trace("%s: attaching new: %x\n", __func__, new->handle);
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.snc.htb_group_attach.child_qos_tag = nq_new->qos_tag;
- if (nss_qdisc_node_attach(&cl->nq, nq_new, &nim_attach,
- NSS_SHAPER_CONFIG_TYPE_SHAPER_NODE_ATTACH) < 0) {
- nss_qdisc_error("%s: attach of new qdisc %x failed\n", __func__, new->handle);
- return -EINVAL;
- }
- }
-
- /*
- * Attach qdisc once it is done in the NSS
- */
- sch_tree_lock(sch);
- cl->qdisc = new;
- sch_tree_unlock(sch);
- return 0;
-}
-
-/*
- * nss_htb_leaf_class()
- * Returns pointer to qdisc if leaf class.
- */
-static struct Qdisc *nss_htb_leaf_class(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_htb_class_data *cl = (struct nss_htb_class_data *)arg;
- nss_qdisc_trace("%s: htb class %x is leaf %d\n", __func__, cl->nq.qos_tag, cl->is_leaf);
-
- /*
- * Return qdisc pointer if this is level 0 class
- */
- return cl->is_leaf ? cl->qdisc : NULL;
-}
-
-/*
- * nss_htb_qlen_notify()
- * We dont maintain a live set of stats in linux, so this function is not implemented.
- */
-static void nss_htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
-{
- nss_qdisc_trace("%s: qlen notify called for htb qdisc %x\n", __func__, sch->handle);
-
- /*
- * Gets called when qlen of child changes (Useful for deactivating)
- * Not useful for us here.
- */
-}
-
-/*
- * nss_htb_get_class()
- * Fetches the class pointer if provided the classid.
- */
-static unsigned long nss_htb_get_class(struct Qdisc *sch, u32 classid)
-{
- struct nss_htb_class_data *cl = nss_htb_find_class(classid, sch);
-
- if (cl != NULL) {
- nss_qdisc_trace("%s: fetched htb class %x from qdisc %x\n",
- __func__, cl->nq.qos_tag, sch->handle);
- atomic_add(1, &cl->nq.refcnt);
- }
-
- return (unsigned long)cl;
-}
-
-/*
- * nss_htb_put_class()
- * Reduces reference count for this class.
- */
-static void nss_htb_put_class(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_htb_class_data *cl = (struct nss_htb_class_data *)arg;
- nss_qdisc_trace("%s: executing put on htb class %x in qdisc %x\n",
- __func__, cl->nq.qos_tag, sch->handle);
-
- /*
- * We are safe to destroy the qdisc if the reference count
- * goes down to 0.
- */
- if (atomic_sub_return(1, &cl->nq.refcnt) == 0) {
- nss_htb_destroy_class(sch, cl);
- }
-}
-
-/*
- * nss_htb_dump_class()
- * Dumps all configurable parameters pertaining to this class.
- */
-static int nss_htb_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, struct tcmsg *tcm)
-{
- struct nss_htb_class_data *cl = (struct nss_htb_class_data *)arg;
- struct nlattr *opts;
- struct tc_nsshtb_class_qopt qopt;
-
- nss_qdisc_trace("%s: dumping htb class %x of qdisc %x\n", __func__, cl->nq.qos_tag, sch->handle);
-
- qopt.burst = cl->burst;
- qopt.rate = cl->rate;
- qopt.crate = cl->crate;
- qopt.cburst = cl->cburst;
- qopt.overhead = cl->overhead;
- qopt.quantum = cl->quantum;
- qopt.priority = cl->priority;
-
- /*
- * All htb group nodes are root nodes. i.e. they dont
- * have any mode htb groups attached beneath them.
- */
- tcm->tcm_parent = TC_H_ROOT;
- tcm->tcm_handle = cl->sch_common.classid;
- tcm->tcm_info = cl->qdisc->handle;
-
- opts = nla_nest_start(skb, TCA_OPTIONS);
-
- if (opts == NULL) {
- goto nla_put_failure;
- }
-
- NLA_PUT(skb, TCA_NSSHTB_CLASS_PARMS, sizeof(qopt), &qopt);
- return nla_nest_end(skb, opts);
-
-nla_put_failure:
- nla_nest_cancel(skb, opts);
- nss_qdisc_error("%s: htb class %x dumo failed\n", __func__, cl->nq.qos_tag);
- return -EMSGSIZE;
-}
-
-/*
- * nss_htb_dump_class_stats()
- * Dumps class statistics.
- */
-static int nss_htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)arg;
-
- if (gnet_stats_copy_basic(d, &nq->bstats) < 0 ||
- gnet_stats_copy_queue(d, &nq->qstats) < 0) {
- nss_qdisc_error("%s: htb class %x stats dump failed\n", __func__, nq->qos_tag);
- return -1;
- }
-
- return 0;
-}
-
-/*
- * nss_htb_walk()
- * Used to walk the tree.
- */
-static void nss_htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
-{
- struct nss_htb_sched_data *q = qdisc_priv(sch);
- struct hlist_node *n;
- struct nss_htb_class_data *cl;
- unsigned int i;
-
- nss_qdisc_trace("%s: walking htb qdisc %x\n", __func__, sch->handle);
-
- if (arg->stop)
- return;
-
- for (i = 0; i < q->clhash.hashsize; i++) {
- hlist_for_each_entry(cl, n, &q->clhash.hash[i],
- sch_common.hnode) {
- if (arg->count < arg->skip) {
- arg->count++;
- continue;
- }
- if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
- arg->stop = 1;
- return;
- }
- arg->count++;
- }
- }
-}
-
-/*
- * nss_htb_init_qdisc()
- * Initializes the htb qdisc.
- */
-static int nss_htb_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_htb_sched_data *q = qdisc_priv(sch);
- struct tc_nsshtb_qopt *qopt;
- int err;
-
- nss_qdisc_trace("%s: initializing htb qdisc %x\n", __func__, sch->handle);
-
- if (opt == NULL || nla_len(opt) < sizeof(*qopt)) {
- nss_qdisc_error("%s: error in input parameter for htb qdisc %x\n",
- __func__, sch->handle);
- return -EINVAL;
- }
-
- qopt = nla_data(opt);
-
- sch_tree_lock(sch);
- q->r2q = qopt->r2q;
- sch_tree_unlock(sch);
-
- err = qdisc_class_hash_init(&q->clhash);
- if (err < 0) {
- nss_qdisc_error("%s: hash init failed for htb qdisc %x", __func__, sch->handle);
- return err;
- }
-
- /*
- * Initialize the NSSHTB shaper in NSS
- */
- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_HTB, 0) < 0) {
- nss_qdisc_error("%s: failed to initialize htb qdisc %x in nss", __func__, sch->handle);
- return -EINVAL;
- }
-
- nss_qdisc_info("%s: htb qdisc initialized with handle %x\n", __func__, sch->handle);
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(&q->nq);
-
- return 0;
-}
-
-/*
- * nss_htb_change_qdisc()
- * Can be used to configure a htb qdisc.
- */
-static int nss_htb_change_qdisc(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_htb_sched_data *q = qdisc_priv(sch);
- struct tc_nsshtb_qopt *qopt;
-
- nss_qdisc_trace("%s: configuring htb qdisc %x\n", __func__, sch->handle);
- if (opt == NULL || nla_len(opt) < sizeof(*qopt)) {
- nss_qdisc_error("%s: error in configuration parameter for qdisc %x\n",
- __func__, sch->handle);
- return -EINVAL;
- }
-
- qopt = nla_data(opt);
-
- sch_tree_lock(sch);
- q->r2q = qopt->r2q;
- sch_tree_unlock(sch);
-
- return 0;
-}
-
-/*
- * nss_htb_reset_class()
- * Resets child qdisc of class to be reset.
- */
-static void nss_htb_reset_class(struct nss_htb_class_data *cl)
-{
- nss_qdisc_reset(cl->qdisc);
- nss_qdisc_trace("%s: htb class %x reset\n", __func__, cl->nq.qos_tag);
-}
-
-/*
- * nss_htb_reset_qdisc()
- * Resets htb qdisc and its classes.
- */
-static void nss_htb_reset_qdisc(struct Qdisc *sch)
-{
- struct nss_htb_sched_data *q = qdisc_priv(sch);
- struct nss_htb_class_data *cl;
- struct hlist_node *n;
- unsigned int i;
-
- for (i = 0; i < q->clhash.hashsize; i++) {
- hlist_for_each_entry(cl, n, &q->clhash.hash[i], sch_common.hnode)
- nss_htb_reset_class(cl);
- }
-
- nss_qdisc_reset(sch);
- nss_qdisc_trace("%s: nss htb qdisc %x reset\n", __func__, sch->handle);
-}
-
-/*
- * nss_htb_destroy_qdisc()
- * Call to destroy a htb qdisc and its associated classes.
- */
-static void nss_htb_destroy_qdisc(struct Qdisc *sch)
-{
- struct nss_htb_sched_data *q = qdisc_priv(sch);
- struct hlist_node *n, *next;
- struct nss_htb_class_data *cl;
- unsigned int i;
-
- /*
- * Destroy all the classes before the root qdisc is destroyed.
- */
- for (i = 0; i < q->clhash.hashsize; i++) {
- hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i], sch_common.hnode) {
-
- /*
- * If this is the root class, we dont have to destroy it. This will be taken
- * care of by the nss_htb_destroy() function.
- */
- if (cl == &q->root) {
- continue;
- }
-
- /*
- * Reduce refcnt by 1 before destroying. This is to
- * ensure that polling of stat stops properly.
- */
- atomic_sub(1, &cl->nq.refcnt);
-
- /*
- * Now we can destroy the class.
- */
- nss_htb_destroy_class(sch, cl);
- }
- }
- qdisc_class_hash_destroy(&q->clhash);
-
- /*
- * Stop the polling of basic stats
- */
- nss_qdisc_stop_basic_stats_polling(&q->nq);
-
- /*
- * Now we can go ahead and destroy the qdisc.
- * Note: We dont have to detach ourself from our parent because this
- * will be taken care of by the graft call.
- */
- nss_qdisc_destroy(&q->nq);
- nss_qdisc_info("%s: htb qdisc %x destroyed\n", __func__, sch->handle);
-}
-
-/*
- * nss_htb_dump_qdisc()
- * Dumps htb qdisc's configurable parameters.
- */
-static int nss_htb_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct nss_htb_sched_data *q = qdisc_priv(sch);
- unsigned char *b = skb_tail_pointer(skb);
- struct tc_nsshtb_qopt qopt;
- struct nlattr *nest;
-
- nss_qdisc_trace("%s: dumping htb qdisc %x\n", __func__, sch->handle);
-
- nest = nla_nest_start(skb, TCA_OPTIONS);
- if (nest == NULL) {
- goto nla_put_failure;
- }
-
- qopt.r2q = q->r2q;
- NLA_PUT(skb, TCA_NSSHTB_QDISC_PARMS, sizeof(qopt), &qopt);
- nla_nest_end(skb, nest);
-
- return skb->len;
-
- nla_put_failure:
- nlmsg_trim(skb, b);
- return -1;
-}
-
-/*
- * nss_htb_enqueue()
- * Enqueues a skb to htb qdisc.
- */
-static int nss_htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- return nss_qdisc_enqueue(skb, sch);
-}
-
-/*
- * nss_htb_dequeue()
- * Dequeues a skb from htb qdisc.
- */
-static struct sk_buff *nss_htb_dequeue(struct Qdisc *sch)
-{
- return nss_qdisc_dequeue(sch);
-}
-
-/*
- * nss_htb_drop()
- * Drops a single sbk from linux queue, if not empty.
- *
- * Does not drop packets that are queued in the NSS.
- */
-static unsigned int nss_htb_drop(struct Qdisc *sch)
-{
- nss_qdisc_trace("%s: drop called on htb qdisc %x\n", __func__, sch->handle);
- return nss_qdisc_drop(sch);
-}
-
-/*
- * Registration structure for htb class
- */
-const struct Qdisc_class_ops nss_htb_class_ops = {
- .change = nss_htb_change_class,
- .delete = nss_htb_delete_class,
- .graft = nss_htb_graft_class,
- .leaf = nss_htb_leaf_class,
- .qlen_notify = nss_htb_qlen_notify,
- .get = nss_htb_get_class,
- .put = nss_htb_put_class,
- .dump = nss_htb_dump_class,
- .dump_stats = nss_htb_dump_class_stats,
- .walk = nss_htb_walk
-};
-
-/*
- * Registration structure for htb qdisc
- */
-struct Qdisc_ops nss_htb_qdisc_ops __read_mostly = {
- .id = "nsshtb",
- .init = nss_htb_init_qdisc,
- .change = nss_htb_change_qdisc,
- .reset = nss_htb_reset_qdisc,
- .destroy = nss_htb_destroy_qdisc,
- .dump = nss_htb_dump_qdisc,
- .enqueue = nss_htb_enqueue,
- .dequeue = nss_htb_dequeue,
- .peek = qdisc_peek_dequeued,
- .drop = nss_htb_drop,
- .cl_ops = &nss_htb_class_ops,
- .priv_size = sizeof(struct nss_htb_sched_data),
- .owner = THIS_MODULE
-};
diff --git a/nss_qdisc/nss_htb.h b/nss_qdisc/nss_htb.h
deleted file mode 100644
index 5f9cbbd..0000000
--- a/nss_qdisc/nss_htb.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-extern struct Qdisc_ops nss_htb_qdisc_ops;
diff --git a/nss_qdisc/nss_prio.c b/nss_qdisc/nss_prio.c
deleted file mode 100644
index f8e79ba..0000000
--- a/nss_qdisc/nss_prio.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_qdisc.h"
-
-struct nss_prio_sched_data {
- struct nss_qdisc nq; /* Common base class for all nss qdiscs */
- int bands; /* Number of priority bands to use */
- struct Qdisc *queues[TCA_NSSPRIO_MAX_BANDS];
- /* Array of child qdisc holder */
-};
-
-static int nss_prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- return nss_qdisc_enqueue(skb, sch);
-}
-
-static struct sk_buff *nss_prio_dequeue(struct Qdisc *sch)
-{
- return nss_qdisc_dequeue(sch);
-}
-
-static unsigned int nss_prio_drop(struct Qdisc *sch)
-{
- return nss_qdisc_drop(sch);
-}
-
-static struct sk_buff *nss_prio_peek(struct Qdisc *sch)
-{
- return nss_qdisc_peek(sch);
-}
-
-static void nss_prio_reset(struct Qdisc *sch)
-{
- return nss_qdisc_reset(sch);
-}
-
-static void nss_prio_destroy(struct Qdisc *sch)
-{
- struct nss_prio_sched_data *q = qdisc_priv(sch);
- struct nss_if_msg nim;
- int i;
-
- nss_qdisc_info("Destroying prio");
-
- /*
- * Destroy all attached child nodes before destroying prio
- */
- for (i = 0; i < q->bands; i++) {
-
- /*
- * We always detach the shaper in NSS before destroying it.
- * It is very important to check for noop qdisc since those dont
- * exist in the NSS.
- */
- if (q->queues[i] != &noop_qdisc) {
- struct nss_qdisc *nq_child = qdisc_priv(q->queues[i]);
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.prio_detach.priority = i;
- if (nss_qdisc_node_detach(&q->nq, nq_child, &nim,
- NSS_SHAPER_CONFIG_TYPE_PRIO_DETACH) < 0) {
- nss_qdisc_error("%s: Failed to detach child in band %d from prio %x\n",
- __func__, i, q->nq.qos_tag);
- return;
- }
- }
-
- /*
- * We can now destroy it
- */
- qdisc_destroy(q->queues[i]);
- }
-
- /*
- * Stop the polling of basic stats
- */
- nss_qdisc_stop_basic_stats_polling(&q->nq);
-
- /*
- * Destroy the qdisc in NSS
- */
- nss_qdisc_destroy(&q->nq);
-}
-
-static const struct nla_policy nss_prio_policy[TCA_NSSPRIO_MAX + 1] = {
- [TCA_NSSPRIO_PARMS] = { .len = sizeof(struct tc_nssprio_qopt) },
-};
-
-static int nss_prio_change(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_prio_sched_data *q;
- struct nlattr *na[TCA_NSSPRIO_MAX + 1];
- struct tc_nssprio_qopt *qopt;
- int err;
-
- q = qdisc_priv(sch);
-
- if (opt == NULL) {
- return -EINVAL;
- }
-
- err = nla_parse_nested(na, TCA_NSSPRIO_MAX, opt, nss_prio_policy);
- if (err < 0) {
- return err;
- }
-
- if (na[TCA_NSSPRIO_PARMS] == NULL) {
- return -EINVAL;
- }
-
- qopt = nla_data(na[TCA_NSSPRIO_PARMS]);
-
- if (qopt->bands > TCA_NSSPRIO_MAX_BANDS) {
- return -EINVAL;
- }
-
- q->bands = qopt->bands;
- nss_qdisc_info("Bands = %u\n", qopt->bands);
-
- return 0;
-}
-
-static int nss_prio_init(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_prio_sched_data *q = qdisc_priv(sch);
- int i;
-
- if (opt == NULL)
- return -EINVAL;
-
- for (i = 0; i < TCA_NSSPRIO_MAX_BANDS; i++)
- q->queues[i] = &noop_qdisc;
-
- q->bands = 0;
- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_PRIO, 0) < 0)
- return -EINVAL;
-
- nss_qdisc_info("Nssprio initialized - handle %x parent %x\n",
- sch->handle, sch->parent);
-
- if (nss_prio_change(sch, opt) < 0) {
- nss_qdisc_destroy(&q->nq);
- return -EINVAL;
- }
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(&q->nq);
- return 0;
-}
-
-static int nss_prio_dump(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct nss_prio_sched_data *q = qdisc_priv(sch);
- struct nlattr *opts = NULL;
- struct tc_nssprio_qopt qopt;
-
- nss_qdisc_info("Nssprio dumping");
- qopt.bands = q->bands;
-
- opts = nla_nest_start(skb, TCA_OPTIONS);
- if (opts == NULL)
- goto nla_put_failure;
- NLA_PUT(skb, TCA_NSSPRIO_PARMS, sizeof(qopt), &qopt);
- return nla_nest_end(skb, opts);
-
-nla_put_failure:
- nla_nest_cancel(skb, opts);
- return -EMSGSIZE;
-}
-
-static int nss_prio_graft(struct Qdisc *sch, unsigned long arg,
- struct Qdisc *new, struct Qdisc **old)
-{
- struct nss_prio_sched_data *q = qdisc_priv(sch);
- struct nss_qdisc *nq_new = qdisc_priv(new);
- uint32_t band = (uint32_t)(arg - 1);
- struct nss_if_msg nim_attach;
- struct nss_if_msg nim_detach;
-
- nss_qdisc_info("Grafting band %u, available bands %u\n", band, q->bands);
-
- if (new == NULL)
- new = &noop_qdisc;
-
- if (band > q->bands)
- return -EINVAL;
-
- sch_tree_lock(sch);
- *old = q->queues[band];
- q->queues[band] = new;
- qdisc_reset(*old);
- sch_tree_unlock(sch);
-
- nss_qdisc_info("%s:Grafting old: %p with new: %p\n", __func__, *old, new);
- if (*old != &noop_qdisc) {
- struct nss_qdisc *nq_old = qdisc_priv(*old);
- nss_qdisc_info("%s:Detaching old: %p\n", __func__, *old);
- nim_detach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim_detach.msg.shaper_configure.config.msg.shaper_node_config.snc.prio_detach.priority = band;
- if (nss_qdisc_node_detach(&q->nq, nq_old, &nim_detach,
- NSS_SHAPER_CONFIG_TYPE_PRIO_DETACH) < 0) {
- return -EINVAL;
- }
- }
-
- if (new != &noop_qdisc) {
- nss_qdisc_info("%s:Attaching new child with qos tag: %x, priority: %u to "
- "qos_tag: %x\n", __func__, nq_new->qos_tag, band, q->nq.qos_tag);
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.snc.prio_attach.child_qos_tag = nq_new->qos_tag;
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.snc.prio_attach.priority = band;
- if (nss_qdisc_node_attach(&q->nq, nq_new, &nim_attach,
- NSS_SHAPER_CONFIG_TYPE_PRIO_ATTACH) < 0) {
- return -EINVAL;
- }
- }
- nss_qdisc_info("Nssprio grafted");
-
- return 0;
-}
-
-static struct Qdisc *nss_prio_leaf(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_prio_sched_data *q = qdisc_priv(sch);
- uint32_t band = (uint32_t)(arg - 1);
-
- nss_qdisc_info("Nssprio returns leaf\n");
-
- if (band > q->bands)
- return NULL;
-
- return q->queues[band];
-}
-
-static unsigned long nss_prio_get(struct Qdisc *sch, u32 classid)
-{
- struct nss_prio_sched_data *q = qdisc_priv(sch);
- unsigned long band = TC_H_MIN(classid);
-
- nss_qdisc_info("Inside get. Handle - %x Classid - %x Band %lu Available band %u\n", sch->handle, classid, band, q->bands);
-
- if (band > q->bands)
- return 0;
-
- return band;
-}
-
-static void nss_prio_put(struct Qdisc *sch, unsigned long arg)
-{
- nss_qdisc_info("Inside prio get\n");
-}
-
-static void nss_prio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
-{
- struct nss_prio_sched_data *q = qdisc_priv(sch);
- int i;
-
- if (arg->stop)
- return;
-
- for (i = 0; i < q->bands; i++) {
- if (arg->count < arg->skip) {
- arg->count++;
- continue;
- }
- if (arg->fn(sch, i + 1, arg) < 0) {
- arg->stop = 1;
- break;
- }
- arg->count++;
- }
- nss_qdisc_info("Nssprio walk called\n");
-}
-
-static int nss_prio_dump_class(struct Qdisc *sch, unsigned long cl,
- struct sk_buff *skb, struct tcmsg *tcm)
-{
- struct nss_prio_sched_data *q = qdisc_priv(sch);
-
- tcm->tcm_handle |= TC_H_MIN(cl);
- tcm->tcm_info = q->queues[cl - 1]->handle;
-
- nss_qdisc_info("Nssprio dumping class\n");
- return 0;
-}
-
-static int nss_prio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
- struct gnet_dump *d)
-{
- struct nss_prio_sched_data *q = qdisc_priv(sch);
- struct Qdisc *cl_q;
-
- cl_q = q->queues[cl - 1];
- cl_q->qstats.qlen = cl_q->q.qlen;
- if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 ||
- gnet_stats_copy_queue(d, &cl_q->qstats) < 0)
- return -1;
-
- nss_qdisc_info("Nssprio dumping class stats\n");
- return 0;
-}
-
-const struct Qdisc_class_ops nss_prio_class_ops = {
- .graft = nss_prio_graft,
- .leaf = nss_prio_leaf,
- .get = nss_prio_get,
- .put = nss_prio_put,
- .walk = nss_prio_walk,
- .dump = nss_prio_dump_class,
- .dump_stats = nss_prio_dump_class_stats,
-};
-
-struct Qdisc_ops nss_prio_qdisc_ops __read_mostly = {
- .next = NULL,
- .id = "nssprio",
- .priv_size = sizeof(struct nss_prio_sched_data),
- .cl_ops = &nss_prio_class_ops,
- .enqueue = nss_prio_enqueue,
- .dequeue = nss_prio_dequeue,
- .peek = nss_prio_peek,
- .drop = nss_prio_drop,
- .init = nss_prio_init,
- .reset = nss_prio_reset,
- .destroy = nss_prio_destroy,
- .change = nss_prio_change,
- .dump = nss_prio_dump,
- .owner = THIS_MODULE,
-};
-
diff --git a/nss_qdisc/nss_prio.h b/nss_qdisc/nss_prio.h
deleted file mode 100644
index 2833a81..0000000
--- a/nss_qdisc/nss_prio.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-extern struct Qdisc_ops nss_prio_qdisc_ops;
diff --git a/nss_qdisc/nss_qdisc.c b/nss_qdisc/nss_qdisc.c
deleted file mode 100644
index 74d22f7..0000000
--- a/nss_qdisc/nss_qdisc.c
+++ /dev/null
@@ -1,2248 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_qdisc.h"
-
-#include "nss_fifo.h"
-#include "nss_codel.h"
-#include "nss_tbl.h"
-#include "nss_prio.h"
-#include "nss_bf.h"
-#include "nss_wrr.h"
-#include "nss_wfq.h"
-#include "nss_htb.h"
-#include "nss_blackhole.h"
-#include "nss_wred.h"
-
-void *nss_qdisc_ctx; /* Shaping context for nss_qdisc */
-wait_queue_head_t nss_qdics_wq; /* Wait queue used to wait on responses from the NSS */
-
-#define NSS_QDISC_COMMAND_TIMEOUT 5*HZ /* We set 5sec to be the timeout value for responses to */
- /* come back from the NSS */
-
-/*
- * Defines related to root hash maintenance
- */
-#define NSS_QDISC_ROOT_HASH_SIZE 4
-#define NSS_QDISC_ROOT_HASH_MASK (NSS_QDISC_ROOT_HASH_SIZE - 1)
-
-/*
- * nss_qdisc_msg_init()
- * Initialize the qdisc specific message
- */
-static void nss_qdisc_msg_init(struct nss_if_msg *nim, uint16_t if_num, uint32_t msg_type, uint32_t len,
- nss_if_msg_callback_t *cb, void *app_data)
-{
- nss_cmn_msg_init(&nim->cm, if_num, msg_type, len, (void*)cb, app_data);
-}
-
-/*
- * nss_qdisc_get_interface_msg()
- * Returns the correct message that needs to be sent down to the NSS interface.
- */
-static inline int nss_qdisc_get_interface_msg(bool is_bridge, uint32_t msg_type)
-{
- /*
- * We re-assign the message based on whether this is for the I shaper
- * or the B shaper. The is_bridge flag tells if we are on a bridge interface.
- */
- if (is_bridge) {
- switch(msg_type) {
- case NSS_QDISC_IF_SHAPER_ASSIGN:
- return NSS_IF_BSHAPER_ASSIGN;
- case NSS_QDISC_IF_SHAPER_UNASSIGN:
- return NSS_IF_BSHAPER_UNASSIGN;
- case NSS_QDISC_IF_SHAPER_CONFIG:
- return NSS_IF_BSHAPER_CONFIG;
- default:
- nss_qdisc_info("%s: Unknown message type for a bridge - type %d", __func__, msg_type);
- return -1;
- }
- } else {
- switch(msg_type) {
- case NSS_QDISC_IF_SHAPER_ASSIGN:
- return NSS_IF_ISHAPER_ASSIGN;
- case NSS_QDISC_IF_SHAPER_UNASSIGN:
- return NSS_IF_ISHAPER_UNASSIGN;
- case NSS_QDISC_IF_SHAPER_CONFIG:
- return NSS_IF_ISHAPER_CONFIG;
- default:
- nss_qdisc_info("%s: Unknown message type for an interface - type %d", __func__, msg_type);
- return -1;
- }
- }
-}
-
-/*
- * nss_qdisc_get_br_port()
- * Returns the bridge port structure of the bridge to which the device is attached to.
- */
-static inline struct net_bridge_port *nss_qdisc_get_br_port(const struct net_device *dev)
-{
- struct net_bridge_port *br_port;
-
- if (!dev) {
- return NULL;
- }
-
- rcu_read_lock();
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
- br_port = br_port_get_rcu(dev);
-#else
- br_port = rcu_dereference(dev->br_port);
-#endif
- rcu_read_unlock();
-
- return br_port;
-}
-
-/*
- * nss_qdisc_attach_bshaper_callback()
- * Call back funtion for bridge shaper attach to an interface.
- */
-static void nss_qdisc_attach_bshaper_callback(void *app_data, struct nss_if_msg *nim)
-{
- struct Qdisc *sch = (struct Qdisc *)app_data;
- struct nss_qdisc *nq = qdisc_priv(sch);
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_warning("%s: B-shaper attach FAILED - response: %d\n", __func__,
- nim->cm.error);
- atomic_set(&nq->state, NSS_QDISC_STATE_FAILED_RESPONSE);
- return;
- }
-
- nss_qdisc_info("%s: B-shaper attach SUCCESS\n", __func__);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
-}
-
-/*
- * nss_qdisc_attach_bridge()
- * Attaches a given bridge shaper to a given interface (Different from shaper_assign)
- */
-static int nss_qdisc_attach_bshaper(struct Qdisc *sch, uint32_t if_num)
-{
- struct nss_if_msg nim;
- struct nss_qdisc *nq = (struct nss_qdisc *)qdisc_priv(sch);
- int32_t state, rc;
-
- nss_qdisc_info("%s: Attaching B-shaper %u to interface %u\n", __func__,
- nq->shaper_id, if_num);
-
- state = atomic_read(&nq->state);
- if (state != NSS_QDISC_STATE_READY) {
- nss_qdisc_warning("%s: qdisc %p (type %d) is not ready: State - %d\n",
- __func__, sch, nq->type, state);
- return -1;
- }
-
- /*
- * Set shaper node state to IDLE
- */
- atomic_set(&nq->state, NSS_QDISC_STATE_IDLE);
-
- /*
- * Populate the message and send it down
- */
- nss_qdisc_msg_init(&nim, if_num, NSS_IF_BSHAPER_ASSIGN,
- sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_attach_bshaper_callback,
- sch);
- /*
- * Assign the ID of the Bshaper that needs to be assigned to the interface recognized
- * by if_num.
- */
- nim.msg.shaper_assign.shaper_id = nq->shaper_id;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, &nim);
-
- if (rc != NSS_TX_SUCCESS) {
- nss_qdisc_warning("%s: Failed to send bshaper (id: %u) attach for "
- "interface(if_num: %u)\n", __func__, nq->shaper_id, if_num);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- while (NSS_QDISC_STATE_IDLE == (state = atomic_read(&nq->state))) {
- yield();
- }
-
- if (state == NSS_QDISC_STATE_FAILED_RESPONSE) {
- nss_qdisc_error("%s: Failed to attach B-shaper %u to interface %u\n",
- __func__, nq->shaper_id, if_num);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- nss_qdisc_info("%s: Attach of B-shaper %u to interface %u is complete\n",
- __func__, nq->shaper_id, if_num);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return 0;
-}
-
-/*
- * nss_qdisc_detach_bshaper_callback()
- * Call back function for bridge shaper detach
- */
-static void nss_qdisc_detach_bshaper_callback(void *app_data, struct nss_if_msg *nim)
-{
- struct Qdisc *sch = (struct Qdisc *)app_data;
- struct nss_qdisc *nq = qdisc_priv(sch);
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_error("%s: B-shaper detach FAILED - response: %d\n",
- __func__, nim->cm.error);
- atomic_set(&nq->state, NSS_QDISC_STATE_FAILED_RESPONSE);
- return;
- }
-
- nss_qdisc_info("%s: B-shaper detach SUCCESS\n", __func__);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
-}
-
-/*
- * nss_qdisc_detach_bridge()
- * Detaches a given bridge shaper from a given interface (different from shaper unassign)
- */
-static int nss_qdisc_detach_bshaper(struct Qdisc *sch, uint32_t if_num)
-{
- struct nss_if_msg nim;
- struct nss_qdisc *nq = (struct nss_qdisc *)qdisc_priv(sch);
- int32_t state, rc;
-
- nss_qdisc_info("%s: Detaching B-shaper %u from interface %u\n",
- __func__, nq->shaper_id, if_num);
-
- state = atomic_read(&nq->state);
- if (state != NSS_QDISC_STATE_READY) {
- nss_qdisc_warning("%s: qdisc %p (type %d) is not ready: %d\n",
- __func__, sch, nq->type, state);
- return -1;
- }
-
- /*
- * Set shaper node state to IDLE
- */
- atomic_set(&nq->state, NSS_QDISC_STATE_IDLE);
-
- /*
- * Create and send shaper unassign message to the NSS interface
- */
- nss_qdisc_msg_init(&nim, if_num, NSS_IF_BSHAPER_UNASSIGN,
- sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_detach_bshaper_callback,
- sch);
- nim.msg.shaper_unassign.shaper_id = nq->shaper_id;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, &nim);
-
- if (rc != NSS_TX_SUCCESS) {
- nss_qdisc_warning("%s: Failed to send B-shaper (id: %u) detach "
- "for interface(if_num: %u)\n", __func__, nq->shaper_id, if_num);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- nss_qdisc_info("%s: Detach of B-shaper %u to interface %u is complete.",
- __func__, nq->shaper_id, if_num);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return 0;
-}
-
-/*
- * nss_qdisc_refresh_bshaper_assignment()
- * Performs assign on unassign of bshaper for interfaces on the bridge.
- */
-static int nss_qdisc_refresh_bshaper_assignment(struct Qdisc *br_qdisc,
- enum nss_qdisc_bshaper_tasks task)
-{
- struct net_device *dev;
- struct net_device *br_dev = qdisc_dev(br_qdisc);
- struct nss_qdisc *nq;
- struct nss_qdisc_bridge_update br_update;
- int i;
-
- if ((br_qdisc->parent != TC_H_ROOT) && (br_qdisc->parent != TC_H_UNSPEC)) {
- nss_qdisc_error("%s: Qdisc not root qdisc for the bridge interface: "
- "Handle - %x", __func__, br_qdisc->parent);
- return -1;
- }
-
- nq = qdisc_priv(br_qdisc);
-
- /*
- * Initialize the bridge update srtucture.
- */
- br_update.port_list_count = 0;
- br_update.unassign_count = 0;
-
- read_lock(&dev_base_lock);
- dev = first_net_device(&init_net);
- while(dev) {
- struct net_bridge_port *br_port = nss_qdisc_get_br_port(dev);
- int nss_if_num;
-
- nss_qdisc_info("%s: Scanning device %s", __func__, dev->name);
- if (!br_port || !br_port->br) {
- goto nextdev;
- }
-
- /*
- * Dont care if this device is not on the
- * bridge that is of concern.
- */
- if (br_port->br->dev != br_dev) {
- goto nextdev;
- }
-
- /*
- * If the interface is known to NSS then we will have to shape it.
- * Irrespective of whether it has an interface qdisc or not.
- */
- nss_if_num = nss_cmn_get_interface_number(nq->nss_shaping_ctx, dev);
- if (nss_if_num < 0) {
- goto nextdev;
- }
-
- nss_qdisc_info("%s: Will be linking/unlinking %s to/from bridge %s\n", __func__,
- dev->name, br_dev->name);
- br_update.port_list[br_update.port_list_count++] = nss_if_num;
-nextdev:
- dev = next_net_device(dev);
- }
- read_unlock(&dev_base_lock);
-
- nss_qdisc_info("%s: List count %d\n", __func__, br_update.port_list_count);
-
- if (task == NSS_QDISC_SCAN_AND_ASSIGN_BSHAPER) {
- /*
- * Loop through the ports and assign them with B-shapers.
- */
- for (i = 0; i < br_update.port_list_count; i++) {
- if (nss_qdisc_attach_bshaper(br_qdisc, br_update.port_list[i]) >= 0) {
- nss_qdisc_info("%s: Interface %u added to bridge %s\n",
- __func__, br_update.port_list[i], br_dev->name);
- continue;
- }
- nss_qdisc_error("%s: Unable to attach bshaper with shaper-id: %u, "
- "to interface if_num: %d\n", __func__, nq->shaper_id,
- br_update.port_list[i]);
- br_update.unassign_count = i;
- break;
- }
- nss_qdisc_info("%s: Unassign count %d\n", __func__, br_update.unassign_count);
- if (br_update.unassign_count == 0) {
- return 0;
- }
-
- /*
- * In case of a failure, unassign the B-shapers that were assigned above
- */
- for (i = 0; i < br_update.unassign_count; i++) {
- if (nss_qdisc_detach_bshaper(br_qdisc, br_update.port_list[i]) >= 0) {
- continue;
- }
- nss_qdisc_assert(NULL, "%s: Unable to detach bshaper with shaper-id: %u, "
- "from interface if_num: %d\n", __func__, nq->shaper_id,
- br_update.port_list[i]);
- }
-
- nss_qdisc_info("%s: Failed to link interfaces to bridge\n", __func__);
- return -1;
- } else if (task == NSS_QDISC_SCAN_AND_UNASSIGN_BSHAPER) {
- /*
- * Loop through the ports and assign them with B-shapers.
- */
- for (i = 0; i < br_update.port_list_count; i++) {
- if (nss_qdisc_detach_bshaper(br_qdisc, br_update.port_list[i]) >= 0) {
- nss_qdisc_info("%s: Interface %u removed from bridge %s\n",
- __func__, br_update.port_list[i], br_dev->name);
- continue;
- }
- nss_qdisc_assert(NULL, "%s: Unable to detach bshaper with shaper-id: %u, "
- "from interface if_num: %d\n", __func__, nq->shaper_id,
- br_update.port_list[i]);
- }
- }
-
- return 0;
-}
-
-/*
- * nss_qdisc_root_cleanup_final()
- * Performs final cleanup of a root shaper node after all other
- * shaper node cleanup is complete.
- */
-static void nss_qdisc_root_cleanup_final(struct nss_qdisc *nq)
-{
- nss_qdisc_info("%s: Root qdisc %p (type %d) final cleanup\n", __func__,
- nq->qdisc, nq->type);
-
- /*
- * If we are a bridge then we have to unregister for bridge bouncing
- * AND destroy the virtual interface that provides bridge shaping.
- */
- if (nq->is_bridge) {
- /*
- * Unregister for bouncing to the NSS for bridge shaping
- */
- nss_qdisc_info("%s: Unregister for bridge bouncing: %p\n", __func__,
- nq->bounce_context);
- nss_shaper_unregister_shaper_bounce_bridge(nq->nss_interface_number);
-
- /*
- * Unregister the virtual interface we use to act as shaper
- * for bridge shaping.
- */
- nss_qdisc_info("%s: Release root bridge virtual interface: %p\n",
- __func__, nq->virtual_interface_context);
- nss_destroy_virt_if(nq->virtual_interface_context);
- }
-
- /*
- * If we are a virual interface other than a bridge then we simply
- * unregister for interface bouncing and not care about deleting the
- * interface.
- */
- if (nq->is_virtual && !nq->is_bridge) {
- /*
- * Unregister for interface bouncing of packets
- */
- nss_qdisc_info("%s: Unregister for interface bouncing: %p\n",
- __func__, nq->bounce_context);
- nss_shaper_unregister_shaper_bounce_interface(nq->nss_interface_number);
- }
-
- /*
- * Finally unregister for shaping
- */
- nss_qdisc_info("%s: Unregister for shaping\n", __func__);
- nss_shaper_unregister_shaping(nq->nss_shaping_ctx);
-
- /*
- * Now set our final state
- */
- atomic_set(&nq->state, nq->pending_final_state);
-}
-
-/*
- * nss_qdisc_root_cleanup_shaper_unassign_callback()
- * Invoked on the response to a shaper unassign config command issued
- */
-static void nss_qdisc_root_cleanup_shaper_unassign_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_assert(NULL, "%s: Root qdisc %p (type %d) shaper unsassign FAILED\n", __func__, nq->qdisc, nq->type);
- }
-
- nss_qdisc_root_cleanup_final(nq);
-}
-
-/*
- * nss_qdisc_root_cleanup_shaper_unassign()
- * Issue command to unassign the shaper
- */
-static void nss_qdisc_root_cleanup_shaper_unassign(struct nss_qdisc *nq)
-{
- struct nss_if_msg nim;
- nss_tx_status_t rc;
- int msg_type;
-
- nss_qdisc_info("%s: Root qdisc %p (type %d): shaper unassign: %d\n",
- __func__, nq->qdisc, nq->type, nq->shaper_id);
-
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_UNASSIGN);
- nss_qdisc_msg_init(&nim, nq->nss_interface_number, msg_type,
- sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_root_cleanup_shaper_unassign_callback,
- nq);
- nim.msg.shaper_unassign.shaper_id = nq->shaper_id;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, &nim);
-
- if (rc == NSS_TX_SUCCESS) {
- return;
- }
-
- nss_qdisc_error("%s: Root qdisc %p (type %d): unassign command send failed: "
- "%d, shaper id: %d\n", __func__, nq->qdisc, nq->type, rc, nq->shaper_id);
-
- nss_qdisc_root_cleanup_final(nq);
-}
-
-/*
- * nss_qdisc_root_cleanup_free_node_callback()
- * Invoked on the response to freeing a shaper node
- */
-static void nss_qdisc_root_cleanup_free_node_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_assert(NULL, "%s: Root qdisc %p (type %d) free FAILED response "
- "type: %d\n", __func__, nq->qdisc, nq->type,
- nim->msg.shaper_configure.config.response_type);
- }
-
- nss_qdisc_info("%s: Root qdisc %p (type %d) free SUCCESS - response "
- "type: %d\n", __func__, nq->qdisc, nq->type,
- nim->msg.shaper_configure.config.response_type);
-
- nss_qdisc_root_cleanup_shaper_unassign(nq);
-}
-
-/*
- * nss_qdisc_root_cleanup_free_node()
- * Free the shaper node, issue command to do so.
- */
-static void nss_qdisc_root_cleanup_free_node(struct nss_qdisc *nq)
-{
- struct nss_if_msg nim;
- nss_tx_status_t rc;
- int msg_type;
-
- nss_qdisc_info("%s: Root qdisc %p (type %d): freeing shaper node\n",
- __func__, nq->qdisc, nq->type);
-
- /*
- * Construct and send the shaper configure message down to the NSS interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG);
- nss_qdisc_msg_init(&nim, nq->nss_interface_number, msg_type,
- sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_root_cleanup_free_node_callback,
- nq);
- nim.msg.shaper_configure.config.request_type = NSS_SHAPER_CONFIG_TYPE_FREE_SHAPER_NODE;
- nim.msg.shaper_configure.config.msg.free_shaper_node.qos_tag = nq->qos_tag;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, &nim);
-
- if (rc == NSS_TX_SUCCESS) {
- return;
- }
-
- nss_qdisc_error("%s: Qdisc %p (type %d): free command send "
- "failed: %d, qos tag: %x\n", __func__, nq->qdisc, nq->type,
- rc, nq->qos_tag);
-
- /*
- * Move onto unassigning the shaper instead
- */
- nss_qdisc_root_cleanup_shaper_unassign(nq);
-}
-
-/*
- * nss_qdisc_root_init_root_assign_callback()
- * Invoked on the response to assigning shaper node as root
- */
-static void nss_qdisc_root_init_root_assign_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_error("%s: Root assign FAILED for qdisc %p (type %d), "
- "response type: %d\n", __func__, nq->qdisc, nq->type,
- nim->msg.shaper_configure.config.response_type);
- nq->pending_final_state = NSS_QDISC_STATE_ROOT_SET_FAIL;
- nss_qdisc_root_cleanup_free_node(nq);
- return;
- }
-
- nss_qdisc_info("%s: Qdisc %p (type %d): set as root is done. Response - %d"
- , __func__, nq->qdisc, nq->type, nim->msg.shaper_configure.config.response_type);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
-}
-
-/*
- * nss_qdisc_root_init_alloc_node_callback()
- * Invoked on the response to creating a shaper node as root
- */
-static void nss_qdisc_root_init_alloc_node_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
- nss_tx_status_t rc;
- int msg_type;
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_info("%s: Qdisc %p (type %d) root alloc node FAILED "
- "response type: %d\n", __func__, nq->qdisc, nq->type,
- nim->msg.shaper_configure.config.response_type);
-
- nq->pending_final_state = NSS_QDISC_STATE_NODE_ALLOC_FAIL;
-
- /*
- * No shaper node created, cleanup from unsassigning the shaper
- */
- nss_qdisc_root_cleanup_shaper_unassign(nq);
- return;
- }
-
- nss_qdisc_info("%s: Qdisc %p (type %d), shaper node alloc success: %u\n",
- __func__, nq->qdisc, nq->type, nq->shaper_id);
-
- /*
- * Create and send shaper configure message to the NSS interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG);
- nss_qdisc_msg_init(nim, nq->nss_interface_number, msg_type,
- sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *) nss_qdisc_root_init_root_assign_callback,
- nq);
- nim->msg.shaper_configure.config.request_type = NSS_SHAPER_CONFIG_TYPE_SET_ROOT;
- nim->msg.shaper_configure.config.msg.set_root_node.qos_tag = nq->qos_tag;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, nim);
-
- if (rc == NSS_TX_SUCCESS) {
- return;
- }
-
- nss_qdisc_error("%s: Root assign send command failed: %d\n",
- __func__, rc);
-
- nq->pending_final_state = NSS_QDISC_STATE_ROOT_SET_SEND_FAIL;
- nss_qdisc_root_cleanup_free_node(nq);
-}
-
-/*
- * nss_qdisc_root_init_shaper_assign_callback()
- * Invoked on the response to a shaper assign config command issued
- */
-static void nss_qdisc_root_init_shaper_assign_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
- nss_tx_status_t rc;
- int msg_type;
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_warning("%s: Qdisc %x (type %d): shaper assign failed - phys_if response type: %d\n",
- __func__, nq->qos_tag, nq->type, nim->cm.error);
- /*
- * Unable to assign a shaper, perform cleanup from final stage
- */
- nq->pending_final_state = NSS_QDISC_STATE_SHAPER_ASSIGN_FAILED;
- nss_qdisc_root_cleanup_final(nq);
- return;
- }
-
- if (nim->cm.type != NSS_IF_ISHAPER_ASSIGN && nim->cm.type != NSS_IF_BSHAPER_ASSIGN) {
- nss_qdisc_error("%s: Qdisc %x (type %d): shaper assign callback received garbage: %d\n",
- __func__, nq->qos_tag, nq->type, nim->cm.type);
- /*
- * Unable to assign a shaper, perform cleanup from final stage
- */
- nq->pending_final_state = NSS_QDISC_STATE_SHAPER_ASSIGN_FAILED;
- nss_qdisc_root_cleanup_final(nq);
- return;
- } else {
- nss_qdisc_info("%s: Qdisc %x (type %d): shaper assign callback received sane message: %d\n",
- __func__, nq->qos_tag, nq->type, nim->cm.type);
- }
-
- /*
- * Shaper has been allocated and assigned
- */
- nq->shaper_id = nim->msg.shaper_assign.new_shaper_id;
- nss_qdisc_info("%s: Qdisc %p (type %d), shaper assigned: %u\n",
- __func__, nq->qdisc, nq->type, nq->shaper_id);
-
- /*
- * Create and send the shaper configure message to the NSS interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG);
- nss_qdisc_msg_init(nim, nq->nss_interface_number, msg_type, sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_root_init_alloc_node_callback,
- nq);
- nim->msg.shaper_configure.config.request_type = NSS_SHAPER_CONFIG_TYPE_ALLOC_SHAPER_NODE;
- nim->msg.shaper_configure.config.msg.alloc_shaper_node.node_type = nq->type;
- nim->msg.shaper_configure.config.msg.alloc_shaper_node.qos_tag = nq->qos_tag;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, nim);
-
- if (rc == NSS_TX_SUCCESS) {
- return;
- }
-
- /*
- * Unable to send alloc node command, cleanup from unassigning the shaper
- */
- nss_qdisc_error("%s: Qdisc %p (type %d) create command failed: %d\n",
- __func__, nq->qdisc, nq->type, rc);
-
- nq->pending_final_state = NSS_QDISC_STATE_NODE_ALLOC_SEND_FAIL;
- nss_qdisc_root_cleanup_shaper_unassign(nq);
-}
-
-
-/*
- * nss_qdisc_child_cleanup_final()
- * Perform final cleanup of a shaper node after all shaper node
- * cleanup is complete.
- */
-static void nss_qdisc_child_cleanup_final(struct nss_qdisc *nq)
-{
- nss_qdisc_info("%s: Final cleanup type %d: %p\n", __func__,
- nq->type, nq->qdisc);
-
- /*
- * Finally unregister for shaping
- */
- nss_qdisc_info("%s: Unregister for shaping\n", __func__);
- nss_shaper_unregister_shaping(nq->nss_shaping_ctx);
-
- /*
- * Now set our final state
- */
- atomic_set(&nq->state, nq->pending_final_state);
-}
-
-
-/*
- * nss_qdisc_child_cleanup_free_node_callback()
- * Invoked on the response to freeing a child shaper node
- */
-static void nss_qdisc_child_cleanup_free_node_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_info("%s: Qdisc %p (type %d qos_tag %x): child free FAILED response type: %d\n",
- __func__, nq->qdisc, nq->type, nq->qos_tag, nim->msg.shaper_configure.config.response_type);
- return;
- }
-
- nss_qdisc_info("%s: Qdisc %p (type %d): child shaper node "
- "free complete\n", __func__, nq->qdisc, nq->type);
-
- /*
- * Perform final cleanup
- */
- nss_qdisc_child_cleanup_final(nq);
-}
-
-/*
- * nss_qdisc_child_cleanup_free_node()
- * Free the child shaper node, issue command to do so.
- */
-static void nss_qdisc_child_cleanup_free_node(struct nss_qdisc *nq)
-{
- struct nss_if_msg nim;
- nss_tx_status_t rc;
- int msg_type;
-
- nss_qdisc_info("%s: Qdisc %p (type %d qos_tag %x): free shaper node command\n",
- __func__, nq->qdisc, nq->type, nq->qos_tag);
-
- /*
- * Create and send the shaper configure message to the NSS interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG);
- nss_qdisc_msg_init(&nim, nq->nss_interface_number, msg_type, sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_child_cleanup_free_node_callback,
- nq);
- nim.msg.shaper_configure.config.request_type = NSS_SHAPER_CONFIG_TYPE_FREE_SHAPER_NODE;
- nim.msg.shaper_configure.config.msg.free_shaper_node.qos_tag = nq->qos_tag;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, &nim);
-
- if (rc == NSS_TX_SUCCESS) {
- return;
- }
-
- nss_qdisc_error("%s: Qdisc %p (type %d): child free node command send "
- "failed: %d, qos tag: %x\n", __func__, nq->qdisc, nq->type,
- rc, nq->qos_tag);
-
- /*
- * Perform final cleanup
- */
- nss_qdisc_child_cleanup_final(nq);
-}
-
-/*
- * nss_qdisc_child_init_alloc_node_callback()
- * Invoked on the response to creating a child shaper node
- */
-static void nss_qdisc_child_init_alloc_node_callback(void *app_data, struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_error("%s: Qdisc %p (type %d): child alloc node FAILED, response "
- "type: %d\n", __func__, nq->qdisc, nq->type, nim->msg.shaper_configure.config.response_type);
- /*
- * Cleanup from final stage
- */
- nq->pending_final_state = NSS_QDISC_STATE_NODE_ALLOC_FAIL_CHILD;
- nss_qdisc_child_cleanup_final(nq);
- return;
- }
-
- /*
- * Shaper node has been allocated
- */
- nss_qdisc_info("%s: Qdisc %p (type %d): shaper node successfully "
- "created as a child node\n",__func__, nq->qdisc, nq->type);
-
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
-}
-
-/*
- * nss_qdisc_add_to_tail_protected()
- * Adds to list while holding the qdisc lock.
- */
-static inline void nss_qdisc_add_to_tail_protected(struct sk_buff *skb, struct Qdisc *sch)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
-
- /*
- * Since packets can come back from the NSS at any time (in case of bounce),
- * enqueue's and dequeue's can cause corruption, if not done within locks.
- */
- spin_lock_bh(&nq->bounce_protection_lock);
-
- /*
- * We do not use the qdisc_enqueue_tail() API here in order
- * to prevent stats from getting updated by the API.
- */
- __skb_queue_tail(&sch->q, skb);
-
- spin_unlock_bh(&nq->bounce_protection_lock);
-};
-
-/*
- * nss_qdisc_add_to_tail()
- * Adds to list without holding any locks.
- */
-static inline void nss_qdisc_add_to_tail(struct sk_buff *skb, struct Qdisc *sch)
-{
- /*
- * We do not use the qdisc_enqueue_tail() API here in order
- * to prevent stats from getting updated by the API.
- */
- __skb_queue_tail(&sch->q, skb);
-};
-
-/*
- * nss_qdisc_remove_from_tail_protected()
- * Removes from list while holding the qdisc lock.
- */
-static inline struct sk_buff *nss_qdisc_remove_from_tail_protected(struct Qdisc *sch)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
- struct sk_buff *skb;
-
- /*
- * Since packets can come back from the NSS at any time (in case of bounce),
- * enqueue's and dequeue's can cause corruption, if not done within locks.
- */
- spin_lock_bh(&nq->bounce_protection_lock);
-
- /*
- * We use __skb_dequeue() to ensure that
- * stats don't get updated twice.
- */
- skb = __skb_dequeue(&sch->q);
-
- spin_unlock_bh(&nq->bounce_protection_lock);
-
- return skb;
-};
-
-/*
- * nss_qdisc_remove_to_tail_protected()
- * Removes from list without holding any locks.
- */
-static inline struct sk_buff *nss_qdisc_remove_from_tail(struct Qdisc *sch)
-{
- /*
- * We use __skb_dequeue() to ensure that
- * stats don't get updated twice.
- */
- return __skb_dequeue(&sch->q);
-};
-
-/*
- * nss_qdisc_bounce_callback()
- * Enqueues packets bounced back from NSS firmware.
- */
-static void nss_qdisc_bounce_callback(void *app_data, struct sk_buff *skb)
-{
- struct Qdisc *sch = (struct Qdisc *)app_data;
-
- /*
- * Enqueue the packet for transmit and schedule a dequeue
- * This enqueue has to be protected in order to avoid corruption.
- */
- nss_qdisc_add_to_tail_protected(skb, sch);
- __netif_schedule(sch);
-}
-
-/*
- * nss_qdisc_peek()
- * Called to peek at the head of an nss qdisc
- */
-struct sk_buff *nss_qdisc_peek(struct Qdisc *sch)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
- struct sk_buff *skb;
-
- if (!nq->is_virtual) {
- skb = skb_peek(&sch->q);
- } else {
- spin_lock_bh(&nq->bounce_protection_lock);
- skb = skb_peek(&sch->q);
- spin_unlock_bh(&nq->bounce_protection_lock);
- }
-
- return skb;
-}
-
-/*
- * nss_qdisc_drop()
- * Called to drop the packet at the head of queue
- */
-unsigned int nss_qdisc_drop(struct Qdisc *sch)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
- unsigned int ret;
-
- if (!nq->is_virtual) {
- ret = __qdisc_queue_drop_head(sch, &sch->q);
- } else {
- spin_lock_bh(&nq->bounce_protection_lock);
- /*
- * This function is safe to call within locks
- */
- ret = __qdisc_queue_drop_head(sch, &sch->q);
- spin_unlock_bh(&nq->bounce_protection_lock);
- }
-
- return ret;
-}
-
-/*
- * nss_qdisc_reset()
- * Called when a qdisc is reset
- */
-void nss_qdisc_reset(struct Qdisc *sch)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
-
- nss_qdisc_info("%s: Qdisc %p (type %d) resetting\n",
- __func__, sch, nq->type);
-
- /*
- * Delete all packets pending in the output queue and reset stats
- */
- if (!nq->is_virtual) {
- qdisc_reset_queue(sch);
- } else {
- spin_lock_bh(&nq->bounce_protection_lock);
- /*
- * This function is safe to call within locks
- */
- qdisc_reset_queue(sch);
- spin_unlock_bh(&nq->bounce_protection_lock);
- }
-
- nss_qdisc_info("%s: Qdisc %p (type %d) reset complete\n",
- __func__, sch, nq->type);
-}
-
-/*
- * nss_qdisc_enqueue()
- * Generic enqueue call for enqueuing packets into NSS for shaping
- */
-int nss_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
- nss_tx_status_t status;
-
- /*
- * If we are not the root qdisc then we should not be getting packets!!
- */
- if (unlikely(!nq->is_root)) {
- nss_qdisc_error("%s: Qdisc %p (type %d): unexpected packet "
- "for child qdisc - skb: %p\n", __func__, sch, nq->type, skb);
- nss_qdisc_add_to_tail(skb, sch);
- __netif_schedule(sch);
- return NET_XMIT_SUCCESS;
- }
-
- /*
- * Packet enueued in linux for transmit.
- *
- * What we do here depends upon whether we are a bridge or not. If not a
- * bridge then it depends on if we are a physical or virtual interface
- * The decision we are trying to reach is whether to bounce a packet to
- * the NSS to be shaped or not.
- *
- * is_bridge is_virtual Meaning
- * ---------------------------------------------------------------------------
- * false false Physical interface in NSS
- *
- * Action: Simply allow the packet to be dequeued. The packet will be
- * shaped by the interface shaper in the NSS by the usual transmit path.
- *
- *
- * false true Physical interface in Linux.
- * NSS still responsible for shaping
- *
- * Action: Bounce the packet to the NSS virtual interface that represents
- * this Linux physical interface for INTERFACE shaping. When the packet is
- * returned from being shaped we allow it to be dequeued for transmit.
- *
- * true n/a Logical Linux interface.
- * Root qdisc created a virtual interface
- * to represent it in the NSS for shaping
- * purposes.
- *
- * Action: Bounce the packet to the NSS virtual interface (for BRIDGE shaping)
- * the bridge root qdisc created for it. When the packet is returned from being
- * shaped we allow it to be dequeued for transmit.
- */
-
- if (!nq->is_virtual) {
- /*
- * TX to an NSS physical - the shaping will occur as part of normal
- * transmit path.
- */
- nss_qdisc_add_to_tail(skb, sch);
- __netif_schedule(sch);
- return NET_XMIT_SUCCESS;
- }
-
- if (nq->is_bridge) {
- /*
- * TX to a bridge, this is to be shaped by the b shaper on the virtual interface created
- * to represent the bridge interface.
- */
- status = nss_shaper_bounce_bridge_packet(nq->bounce_context, nq->nss_interface_number, skb);
- if (likely(status == NSS_TX_SUCCESS)) {
- return NET_XMIT_SUCCESS;
- }
-
- nss_qdisc_warning("%s: Qdisc %p (type %d): failed to bounce for bridge %d, skb: %p\n",
- __func__, sch, nq->type, nq->nss_interface_number, skb);
- goto enqueue_drop;
- }
-
- /*
- * TX to a physical Linux (NSS virtual). Bounce packet to NSS for
- * interface shaping.
- */
- status = nss_shaper_bounce_interface_packet(nq->bounce_context,
- nq->nss_interface_number, skb);
- if (likely(status == NSS_TX_SUCCESS)) {
- return NET_XMIT_SUCCESS;
- }
-
- /*
- * We failed to bounce the packet for shaping on a virtual interface
- */
- nss_qdisc_warning("%s: Qdisc %p (type %d): failed to bounce for "
- "interface: %d, skb: %p\n", __func__, sch, nq->type,
- nq->nss_interface_number, skb);
-
-enqueue_drop:
- /*
- * We were unable to transmit the packet for bridge shaping.
- * We therefore drop it.
- */
- kfree_skb(skb);
-
- return NET_XMIT_DROP;
-}
-
-/*
- * nss_qdisc_dequeue()
- * Generic dequeue call for dequeuing bounced packets.
- */
-inline struct sk_buff *nss_qdisc_dequeue(struct Qdisc *sch)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
-
- /*
- * We use the protected dequeue API if the interface involves bounce.
- * That is, a bridge or a virtual interface. Else, we use the unprotected
- * API.
- */
- if (nq->is_virtual) {
- return nss_qdisc_remove_from_tail_protected(sch);
- } else {
- return nss_qdisc_remove_from_tail(sch);
- }
-}
-
-/*
- * nss_qdisc_set_default_callback()
- * The callback function for a shaper node set default
- */
-static void nss_qdisc_set_default_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_error("%s: Qdisc %p (type %d): shaper node set default FAILED, response type: %d\n",
- __func__, nq->qdisc, nq->type, nim->msg.shaper_configure.config.response_type);
- atomic_set(&nq->state, NSS_QDISC_STATE_FAILED_RESPONSE);
- return;
- }
-
- nss_qdisc_info("%s: Qdisc %p (type %d): attach complete\n", __func__, nq->qdisc, nq->type);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
-}
-
-/*
- * nss_qdisc_node_set_default()
- * Configuration function that sets shaper node as default for packet enqueue
- */
-int nss_qdisc_set_default(struct nss_qdisc *nq)
-{
- int32_t state, rc;
- int msg_type;
- struct nss_if_msg nim;
- struct nss_qdisc *nq_root;
-
- /*
- * Get root nss qdisc
- */
- if (nq->is_root) {
- nq_root = nq;
- } else {
- struct Qdisc *root = qdisc_root(nq->qdisc);
- nq_root = qdisc_priv(root);
- }
-
- nss_qdisc_info("%s: Setting qdisc %p (type %d) as default\n", __func__,
- nq->qdisc, nq->type);
-
- state = atomic_read(&nq->state);
- if (state != NSS_QDISC_STATE_READY) {
- nss_qdisc_warning("%s: Qdisc %p (type %d): qdisc state not ready: %d\n", __func__,
- nq->qdisc, nq->type, state);
- return -1;
- }
-
- /*
- * Set shaper node state to IDLE
- */
- atomic_set(&nq->state, NSS_QDISC_STATE_IDLE);
-
- /*
- * Create the shaper configure message and send it down to the NSS interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG);
- nss_qdisc_msg_init(&nim, nq->nss_interface_number, msg_type, sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_set_default_callback,
- nq);
- nim.msg.shaper_configure.config.request_type = NSS_SHAPER_CONFIG_TYPE_SET_DEFAULT;
- nim.msg.shaper_configure.config.msg.set_default_node.qos_tag = nq->qos_tag;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, &nim);
-
- if (rc != NSS_TX_SUCCESS) {
- nss_qdisc_warning("%s: Failed to send set default message for "
- "qdisc type %d\n", __func__, nq->type);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- /*
- * Wait until cleanup operation is complete at which point the state
- * shall become idle. NOTE: This relies on the NSS driver to be able
- * to operate asynchronously which means kernel preemption is required.
- */
- while (NSS_QDISC_STATE_IDLE == (state = atomic_read(&nq->state))) {
- yield();
- }
-
- if (state == NSS_QDISC_STATE_FAILED_RESPONSE) {
- nss_qdisc_error("%s: Qdisc %p (type %d): failed to default "
- "State: %d\n", __func__, nq->qdisc, nq->type, state);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- /*
- * Save the default nss qdisc pointer
- */
- spin_lock_bh(&nq_root->lock);
- nq_root->default_nq = nq;
- spin_unlock_bh(&nq_root->lock);
-
- nss_qdisc_info("%s: Qdisc %p (type %d): shaper node default complete\n",
- __func__, nq->qdisc, nq->type);
- return 0;
-}
-
-/*
- * nss_qdisc_node_attach_callback()
- * The callback function for a shaper node attach message
- */
-static void nss_qdisc_node_attach_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_info("%s: Qdisc %p (type %d) shaper node attach FAILED - response "
- "type: %d\n", __func__, nq->qdisc, nq->type,
- nim->msg.shaper_configure.config.response_type);
- atomic_set(&nq->state, NSS_QDISC_STATE_FAILED_RESPONSE);
- return;
- }
-
- nss_qdisc_info("%s: qdisc type %d: %p, attach complete\n", __func__,
- nq->type, nq->qdisc);
-
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
-}
-
-/*
- * nss_qdisc_node_attach()
- * Configuration function that helps attach a child shaper node to a parent.
- */
-int nss_qdisc_node_attach(struct nss_qdisc *nq, struct nss_qdisc *nq_child,
- struct nss_if_msg *nim, int32_t attach_type)
-{
- int32_t state, rc;
- int msg_type;
-
- nss_qdisc_info("%s: Qdisc %p (type %d) attaching\n",
- __func__, nq->qdisc, nq->type);
-
- state = atomic_read(&nq->state);
- if (state != NSS_QDISC_STATE_READY) {
- nss_qdisc_warning("%s: Qdisc %p (type %d): not ready, state: %d\n",
- __func__, nq->qdisc, nq->type, state);
- return -1;
- }
-
- /*
- * Set shaper node state to IDLE
- */
- atomic_set(&nq->state, NSS_QDISC_STATE_IDLE);
-
- /*
- * Create the shaper configure message and send it down to the NSS interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG);
- nss_qdisc_msg_init(nim, nq->nss_interface_number, msg_type, sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_node_attach_callback,
- nq);
- nim->msg.shaper_configure.config.request_type = attach_type;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, nim);
-
- if (rc != NSS_TX_SUCCESS) {
- nss_qdisc_warning("%s: Failed to send configure message for "
- "qdisc type %d\n", __func__, nq->type);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- /*
- * Wait until cleanup operation is complete at which point the state
- * shall become idle. NOTE: This relies on the NSS driver to be able
- * to operate asynchronously which means kernel preemption is required.
- */
- while (NSS_QDISC_STATE_IDLE == (state = atomic_read(&nq->state))) {
- yield();
- }
-
- if (state == NSS_QDISC_STATE_FAILED_RESPONSE) {
- nss_qdisc_error("%s: Qdisc %p (type %d) failed to attach child "
- "node, State: %d\n", __func__, nq->qdisc, nq->type, state);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- spin_lock_bh(&nq_child->lock);
- nq_child->parent = nq;
- spin_unlock_bh(&nq_child->lock);
-
- nss_qdisc_info("%s: Qdisc %p (type %d): shaper node attach complete\n",
- __func__, nq->qdisc, nq->type);
- return 0;
-}
-
-/*
- * nss_qdisc_node_detach_callback()
- * The callback function for a shaper node detach message
- */
-static void nss_qdisc_node_detach_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_info("%s: Qdisc %p (type %d): shaper node detach FAILED - response "
- "type: %d\n", __func__, nq->qdisc, nq->type,
- nim->msg.shaper_configure.config.response_type);
- atomic_set(&nq->state, NSS_QDISC_STATE_FAILED_RESPONSE);
- return;
- }
-
- nss_qdisc_info("%s: Qdisc %p (type %d): detach complete\n",
- __func__, nq->qdisc, nq->type);
-
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
-}
-
-/*
- * nss_qdisc_node_detach()
- * Configuration function that helps detach a child shaper node to a parent.
- */
-int nss_qdisc_node_detach(struct nss_qdisc *nq, struct nss_qdisc *nq_child,
- struct nss_if_msg *nim, int32_t detach_type)
-{
- int32_t state, rc, msg_type;
-
- nss_qdisc_info("%s: Qdisc %p (type %d) detaching\n",
- __func__, nq->qdisc, nq->type);
-
- state = atomic_read(&nq->state);
- if (state != NSS_QDISC_STATE_READY) {
- nss_qdisc_warning("%s: Qdisc %p (type %d): not ready, state: %d\n",
- __func__, nq->qdisc, nq->type, state);
- return -1;
- }
-
- /*
- * Set shaper node state to IDLE
- */
- atomic_set(&nq->state, NSS_QDISC_STATE_IDLE);
-
- /*
- * Create and send the shaper configure message to the NSS interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG);
- nss_qdisc_msg_init(nim, nq->nss_interface_number, msg_type, sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_node_detach_callback,
- nq);
- nim->msg.shaper_configure.config.request_type = detach_type;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, nim);
-
- if (rc != NSS_TX_SUCCESS) {
- nss_qdisc_warning("%s: Qdisc %p (type %d): Failed to send configure "
- "message.", __func__, nq->qdisc, nq->type);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- /*
- * Wait until cleanup operation is complete at which point the state shall become idle.
- * NOTE: This relies on the NSS driver to be able to operate asynchronously which means
- * kernel preemption is required.
- */
- while (NSS_QDISC_STATE_IDLE == (state = atomic_read(&nq->state))) {
- yield();
- }
-
- if (state == NSS_QDISC_STATE_FAILED_RESPONSE) {
- nss_qdisc_error("%s: Qdisc %p (type %d): failed to detach child node, "
- "State: %d\n", __func__, nq->qdisc, nq->type, state);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- spin_lock_bh(&nq_child->lock);
- nq_child->parent = NULL;
- spin_unlock_bh(&nq_child->lock);
-
- nss_qdisc_info("%s: Qdisc %p (type %d): shaper node detach complete\n",
- __func__, nq->qdisc, nq->type);
- return 0;
-}
-
-/*
- * nss_qdisc_configure_callback()
- * The call back function for a shaper node configure message
- */
-static void nss_qdisc_configure_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_info("%s: Qdisc %p (type %d): shaper node configure FAILED "
- "response type: %d\n", __func__, nq->qdisc, nq->type,
- nim->msg.shaper_configure.config.response_type);
- atomic_set(&nq->state, NSS_QDISC_STATE_FAILED_RESPONSE);
- return;
- }
-
- nss_qdisc_info("%s: Qdisc %p (type %d): configuration complete\n",
- __func__, nq->qdisc, nq->type);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
-}
-
-/*
- * nss_qdisc_configure()
- * Configuration function that aids in tuning of queuing parameters.
- */
-int nss_qdisc_configure(struct nss_qdisc *nq,
- struct nss_if_msg *nim, int32_t config_type)
-{
- int32_t state, rc;
- int msg_type;
-
- nss_qdisc_info("%s: Qdisc %p (type %d) configuring\n", __func__, nq->qdisc, nq->type);
-
- state = atomic_read(&nq->state);
- if (state != NSS_QDISC_STATE_READY) {
- nss_qdisc_warning("%s: Qdisc %p (type %d): not ready for configure, "
- "state : %d\n", __func__, nq->qdisc, nq->type, state);
- return -1;
- }
-
- /*
- * Set shaper node state to IDLE
- */
- atomic_set(&nq->state, NSS_QDISC_STATE_IDLE);
-
- /*
- * Create and send the shaper configure message to the NSS interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG);
- nss_qdisc_msg_init(nim, nq->nss_interface_number, msg_type, sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_configure_callback,
- nq);
- nim->msg.shaper_configure.config.request_type = config_type;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, nim);
-
- if (rc != NSS_TX_SUCCESS) {
- nss_qdisc_warning("%s: Qdisc %p (type %d): Failed to send configure "
- "message\n", __func__, nq->qdisc, nq->type);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- /*
- * Wait until cleanup operation is complete at which point the state
- * shall become idle. NOTE: This relies on the NSS driver to be able
- * to operate asynchronously which means kernel preemption is required.
- */
- while (NSS_QDISC_STATE_IDLE == (state = atomic_read(&nq->state))) {
- yield();
- }
-
- if (state == NSS_QDISC_STATE_FAILED_RESPONSE) {
- nss_qdisc_error("%s: Qdisc %p (type %d): failed to configure shaper "
- "node: State: %d\n", __func__, nq->qdisc, nq->type, state);
- atomic_set(&nq->state, NSS_QDISC_STATE_READY);
- return -1;
- }
-
- nss_qdisc_info("%s: Qdisc %p (type %d): shaper node configure complete\n",
- __func__, nq->qdisc, nq->type);
- return 0;
-}
-
-/*
- * nss_qdisc_destroy()
- * Destroys a shaper in NSS, and the sequence is based on the position of
- * this qdisc (child or root) and the interface to which it is attached to.
- */
-void nss_qdisc_destroy(struct nss_qdisc *nq)
-{
- int32_t state;
-
- nss_qdisc_info("%s: Qdisc %p (type %d) destroy\n",
- __func__, nq->qdisc, nq->type);
-
-
- state = atomic_read(&nq->state);
- if (state != NSS_QDISC_STATE_READY) {
- nss_qdisc_warning("%s: Qdisc %p (type %d): destroy not ready, "
- "state: %d\n", __func__, nq->qdisc, nq->type, state);
- return;
- }
-
- /*
- * How we begin to tidy up depends on whether we are root or child
- */
- nq->pending_final_state = NSS_QDISC_STATE_IDLE;
- if (nq->is_root) {
-
- /*
- * If this is root on a bridge interface, then unassign
- * the bshaper from all the attached interfaces.
- */
- if (nq->is_bridge) {
- nss_qdisc_info("%s: Qdisc %p (type %d): is root on bridge. Need to "
- "unassign bshapers from its interfaces\n", __func__, nq->qdisc, nq->type);
- nss_qdisc_refresh_bshaper_assignment(nq->qdisc, NSS_QDISC_SCAN_AND_UNASSIGN_BSHAPER);
- }
-
- /*
- * Begin by freeing the root shaper node
- */
- nss_qdisc_root_cleanup_free_node(nq);
-
- } else {
- nss_qdisc_child_cleanup_free_node(nq);
- }
-
- /*
- * Wait until cleanup operation is complete at which point the state
- * shall become idle. NOTE: This relies on the NSS driver to be able
- * to operate asynchronously which means kernel preemption is required.
- */
- while (NSS_QDISC_STATE_IDLE != (state = atomic_read(&nq->state))) {
- yield();
- }
-
- if (nq->destroy_virtual_interface) {
- nss_destroy_virt_if((void *)nq->nss_interface_number);
- }
-
- nss_qdisc_info("%s: Qdisc %p (type %d): destroy complete\n",
- __func__, nq->qdisc, nq->type);
-}
-
-/*
- * nss_qdisc_init()
- * Initializes a shaper in NSS, based on the position of this qdisc (child or root)
- * and if its a normal interface or a bridge interface.
- */
-int nss_qdisc_init(struct Qdisc *sch, struct nss_qdisc *nq, nss_shaper_node_type_t type, uint32_t classid)
-{
- struct Qdisc *root;
- u32 parent;
- nss_tx_status_t rc;
- struct net_device *dev;
- int32_t state;
- struct nss_if_msg nim;
- int msg_type;
-
- /*
- * Initialize locks
- */
- spin_lock_init(&nq->bounce_protection_lock);
- spin_lock_init(&nq->lock);
-
- /*
- * Record our qdisc and type in the private region for handy use
- */
- nq->qdisc = sch;
- nq->type = type;
-
- /*
- * We dont have to destroy a virtual interface unless
- * we are the ones who created it. So set it to false
- * by default.
- */
- nq->destroy_virtual_interface = false;
-
- /*
- * Set shaper node state to IDLE
- */
- atomic_set(&nq->state, NSS_QDISC_STATE_IDLE);
-
- /*
- * If we are a class, then classid is used as the qos tag.
- * Else the qdisc handle will be used as the qos tag.
- */
- if (classid) {
- nq->qos_tag = classid;
- nq->is_class = true;
- } else {
- nq->qos_tag = (uint32_t)sch->handle;
- nq->is_class = false;
- }
-
- parent = sch->parent;
-
- /*
- * If our parent is TC_H_ROOT and we are not a class, then we are the root qdisc.
- * Note, classes might have its qdisc as root, however we should not set is_root to
- * true for classes. This is the reason why we check for classid.
- */
- if ((sch->parent == TC_H_ROOT) && (!nq->is_class)) {
- nss_qdisc_info("%s: Qdisc %p (type %d) is root\n", __func__, nq->qdisc, nq->type);
- nq->is_root = true;
- root = sch;
- } else {
- nss_qdisc_info("%s: Qdisc %p (type %d) not root\n", __func__, nq->qdisc, nq->type);
- nq->is_root = false;
- root = qdisc_root(sch);
- }
-
- /*
- * Get the net device as it will tell us if we are on a bridge,
- * or on a net device that is represented by a virtual NSS interface (e.g. WIFI)
- */
- dev = qdisc_dev(sch);
- nss_qdisc_info("%s: Qdisc %p (type %d) init dev: %p\n", __func__, nq->qdisc, nq->type, dev);
-
- /*
- * Determine if dev is a bridge or not as this determines if we
- * interract with an I or B shaper.
- */
- if (dev->priv_flags == IFF_EBRIDGE) {
- nss_qdisc_info("%s: Qdisc %p (type %d) init qdisc: %p, is bridge\n",
- __func__, nq->qdisc, nq->type, nq->qdisc);
- nq->is_bridge = true;
- } else {
- nss_qdisc_info("%s: Qdisc %p (type %d) init qdisc: %p, not bridge\n",
- __func__, nq->qdisc, nq->type, nq->qdisc);
- nq->is_bridge = false;
- }
-
- nss_qdisc_info("%s: Qdisc %p (type %d) init root: %p, qos tag: %x, "
- "parent: %x rootid: %s owner: %p\n", __func__, nq->qdisc, nq->type, root,
- nq->qos_tag, parent, root->ops->id, root->ops->owner);
-
- /*
- * The root must be of an nss type (unless we are of course going to be root).
- * This is to prevent mixing NSS qdisc with other types of qdisc.
- */
- if ((parent != TC_H_ROOT) && (root->ops->owner != THIS_MODULE)) {
- nss_qdisc_warning("%s: NSS qdisc %p (type %d) used along with non-NSS qdiscs,"
- " or the interface is currently down", __func__, nq->qdisc, nq->type);
- }
-
- /*
- * Register for NSS shaping
- */
- nq->nss_shaping_ctx = nss_shaper_register_shaping();
- if (!nq->nss_shaping_ctx) {
- nss_qdisc_error("%s: no shaping context returned for type %d\n",
- __func__, nq->type);
- atomic_set(&nq->state, NSS_QDISC_STATE_INIT_FAILED);
- return -1;
- }
-
- /*
- * If we are not the root qdisc then we have a simple enough job to do
- */
- if (!nq->is_root) {
- struct nss_if_msg nim_alloc;
- nss_qdisc_info("%s: Qdisc %p (type %d) initializing non-root qdisc\n",
- __func__, nq->qdisc, nq->type);
-
- /*
- * The device we are operational on MUST be recognised as an NSS interface.
- * NOTE: We do NOT support non-NSS known interfaces in this implementation.
- * NOTE: This will still work where the dev is registered as virtual, in which case
- * nss_interface_number shall indicate a virtual NSS interface.
- */
- nq->nss_interface_number = nss_cmn_get_interface_number(nq->nss_shaping_ctx, dev);
- if (nq->nss_interface_number < 0) {
- nss_qdisc_error("%s: Qdisc %p (type %d) net device unknown to "
- "nss driver %s\n", __func__, nq->qdisc, nq->type, dev->name);
- nss_shaper_unregister_shaping(nq->nss_shaping_ctx);
- atomic_set(&nq->state, NSS_QDISC_STATE_INIT_FAILED);
- return -1;
- }
-
- /*
- * Set the virtual flag
- */
- nq->is_virtual = nss_cmn_interface_is_virtual(nq->nss_shaping_ctx, nq->nss_interface_number);
-
- /*
- * Create a shaper node for requested type.
- * Essentially all we need to do is create the shaper node.
- */
- nss_qdisc_info("%s: Qdisc %p (type %d) non-root (child) create\n",
- __func__, nq->qdisc, nq->type);
-
- /*
- * Create and send the shaper configure message to the interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG);
- nss_qdisc_msg_init(&nim_alloc, nq->nss_interface_number, msg_type, sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_child_init_alloc_node_callback,
- nq);
- nim_alloc.msg.shaper_configure.config.request_type = NSS_SHAPER_CONFIG_TYPE_ALLOC_SHAPER_NODE;
- nim_alloc.msg.shaper_configure.config.msg.alloc_shaper_node.node_type = nq->type;
- nim_alloc.msg.shaper_configure.config.msg.alloc_shaper_node.qos_tag = nq->qos_tag;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, &nim_alloc);
-
- if (rc != NSS_TX_SUCCESS) {
- nss_qdisc_error("%s: Qdisc %p (type %d) create command "
- "failed: %d\n", __func__, nq->qdisc, nq->type, rc);
- nq->pending_final_state = NSS_QDISC_STATE_CHILD_ALLOC_SEND_FAIL;
- nss_qdisc_child_cleanup_final(nq);
- return -1;
- }
-
- /*
- * Wait until init operation is complete.
- * NOTE: This relies on the NSS driver to be able to operate
- * asynchronously which means kernel preemption is required.
- */
- while (NSS_QDISC_STATE_IDLE == (state = atomic_read(&nq->state))) {
- yield();
- }
- nss_qdisc_info("%s: Qdisc %p (type %d): initialised with state: %d\n",
- __func__, nq->qdisc, nq->type, state);
- if (state > 0) {
- return 0;
- }
- return -1;
- }
-
- /*
- * Root qdisc has a lot of work to do. It is responsible for setting up
- * the shaper and creating the root and default shaper nodes. Also, when
- * operating on a bridge, a virtual NSS interface is created to represent
- * bridge shaping. Further, when operating on a bridge, we monitor for
- * bridge port changes and assign B shapers to the interfaces of the ports.
- */
- nss_qdisc_info("%s: init qdisc type %d : %p, ROOT\n", __func__, nq->type, nq->qdisc);
-
- /*
- * Detect if we are operating on a bridge or interface
- */
- if (nq->is_bridge) {
- nss_qdisc_info("%s: Qdisc %p (type %d): initializing root qdisc on "
- "bridge\n", __func__, nq->qdisc, nq->type);
-
- /*
- * As we are a root qdisc on this bridge then we have to create a
- * virtual interface to represent this bridge in the NSS. This will
- * allow us to bounce packets to the NSS for bridge shaping action.
- * Also set the destroy virtual interface flag so that it is destroyed
- * when the module goes down. If this is not done, the OS waits for
- * the interface to be released.
- */
- nq->virtual_interface_context = nss_create_virt_if(dev);
- if (!nq->virtual_interface_context) {
- nss_qdisc_error("%s: Qdisc %p (type %d): cannot create virtual "
- "interface\n", __func__, nq->qdisc, nq->type);
- nss_shaper_unregister_shaping(nq->nss_shaping_ctx);
- atomic_set(&nq->state, NSS_QDISC_STATE_INIT_FAILED);
- return -1;
- }
- nss_qdisc_info("%s: Qdisc %p (type %d): virtual interface registered "
- "in NSS: %p\n", __func__, nq->qdisc, nq->type, nq->virtual_interface_context);
-
- /*
- * Get the virtual interface number, and set the related flags
- */
- nq->nss_interface_number = nss_virt_if_get_interface_num(nq->virtual_interface_context);
- nq->destroy_virtual_interface = true;
- nq->is_virtual = true;
- nss_qdisc_info("%s: Qdisc %p (type %d) virtual interface number: %d\n",
- __func__, nq->qdisc, nq->type, nq->nss_interface_number);
-
- /*
- * The root qdisc will get packets enqueued to it, so it must
- * register for bridge bouncing as it will be responsible for
- * bouncing packets to the NSS for bridge shaping.
- */
- nq->bounce_context = nss_shaper_register_shaper_bounce_bridge(nq->nss_interface_number,
- nss_qdisc_bounce_callback, nq->qdisc, THIS_MODULE);
- if (!nq->bounce_context) {
- nss_qdisc_error("%s: Qdisc %p (type %d): is root but cannot register "
- "for bridge bouncing\n", __func__, nq->qdisc, nq->type);
- nss_destroy_virt_if(nq->virtual_interface_context);
- nss_shaper_unregister_shaping(nq->nss_shaping_ctx);
- atomic_set(&nq->state, NSS_QDISC_STATE_INIT_FAILED);
- return -1;
- }
-
- } else {
- nss_qdisc_info("%s: Qdisc %p (type %d): is interface\n", __func__, nq->qdisc, nq->type);
-
- /*
- * The device we are operational on MUST be recognised as an NSS interface.
- * NOTE: We do NOT support non-NSS known interfaces in this basic implementation.
- * NOTE: This will still work where the dev is registered as virtual, in which case
- * nss_interface_number shall indicate a virtual NSS interface.
- */
- nq->nss_interface_number = nss_cmn_get_interface_number(nq->nss_shaping_ctx, dev);
- if (nq->nss_interface_number < 0) {
- nss_qdisc_error("%s: Qdisc %p (type %d): interface unknown to nss driver %s\n",
- __func__, nq->qdisc, nq->type, dev->name);
- nss_shaper_unregister_shaping(nq->nss_shaping_ctx);
- atomic_set(&nq->state, NSS_QDISC_STATE_INIT_FAILED);
- return -1;
- }
-
- /*
- * Is the interface virtual or not?
- * NOTE: If this interface is virtual then we have to bounce packets to it for shaping
- */
- nq->is_virtual = nss_cmn_interface_is_virtual(nq->nss_shaping_ctx, nq->nss_interface_number);
- if (!nq->is_virtual) {
- nss_qdisc_info("%s: Qdisc %p (type %d): interface %u is physical\n",
- __func__, nq->qdisc, nq->type, nq->nss_interface_number);
- } else {
- nss_qdisc_info("%s: Qdisc %p (type %d): interface %u is virtual\n",
- __func__, nq->qdisc, nq->type, nq->nss_interface_number);
-
- /*
- * Register for interface bounce shaping.
- */
- nq->bounce_context = nss_shaper_register_shaper_bounce_interface(nq->nss_interface_number,
- nss_qdisc_bounce_callback, nq->qdisc, THIS_MODULE);
- if (!nq->bounce_context) {
- nss_qdisc_error("%s: Qdisc %p (type %d): is root but failed "
- "to register for interface bouncing\n", __func__, nq->qdisc, nq->type);
- nss_shaper_unregister_shaping(nq->nss_shaping_ctx);
- atomic_set(&nq->state, NSS_QDISC_STATE_INIT_FAILED);
- return -1;
- }
- }
- }
-
- /*
- * We need to issue a command to establish a shaper on the interface.
- */
-
- /*
- * Create and send the shaper assign message to the NSS interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_ASSIGN);
- nss_qdisc_msg_init(&nim, nq->nss_interface_number, msg_type, sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_root_init_shaper_assign_callback,
- nq);
- nim.msg.shaper_assign.shaper_id = 0; /* Any free shaper will do */
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, &nim);
-
- if (rc != NSS_TX_SUCCESS) {
- nss_qdisc_error("%s: shaper assign command failed: %d\n", __func__, rc);
- nq->pending_final_state = NSS_QDISC_STATE_ASSIGN_SHAPER_SEND_FAIL;
- nss_qdisc_root_cleanup_final(nq);
- /*
- * We dont have to clean up the virtual interface, since this is
- * taken care of by the nss_qdisc_root_cleanup_final() function.
- */
- return -1;
- }
-
- /*
- * Wait until init operation is complete.
- * NOTE: This relies on the NSS driver to be able to operate asynchronously which means
- * kernel preemption is required.
- */
- nss_qdisc_info("%s: Qdisc %p (type %d): Waiting on response from NSS for "
- "shaper assign message\n", __func__, nq->qdisc, nq->type);
- while (NSS_QDISC_STATE_IDLE == (state = atomic_read(&nq->state))) {
- yield();
- }
- nss_qdisc_info("%s: Qdisc %p (type %d): is initialised with state: %d\n",
- __func__, nq->qdisc, nq->type, state);
-
- if (state > 0) {
-
- /*
- * Return if this is not a root qdisc on a bridge interface.
- */
- if (!nq->is_root || !nq->is_bridge) {
- return 0;
- }
-
- nss_qdisc_info("%s: This is a bridge interface. Linking bridge ...\n",
- __func__);
- /*
- * This is a root qdisc added to a bridge interface. Now we go ahead
- * and add this B-shaper to interfaces known to the NSS
- */
- if (nss_qdisc_refresh_bshaper_assignment(nq->qdisc, NSS_QDISC_SCAN_AND_ASSIGN_BSHAPER) < 0) {
- nss_qdisc_destroy(nq);
- nss_qdisc_error("%s: bridge linking failed\n", __func__);
- return -1;
- }
- nss_qdisc_info("%s: Bridge linking complete\n", __func__);
- return 0;
- }
-
- /*
- * Destroy any virtual interfaces created by us before returning a failure.
- */
- if (nq->destroy_virtual_interface) {
- nss_destroy_virt_if(nq->virtual_interface_context);
- }
-
- return -1;
-}
-
-/*
- * nss_qdisc_basic_stats_callback()
- * Invoked after getting basic stats
- */
-static void nss_qdisc_basic_stats_callback(void *app_data,
- struct nss_if_msg *nim)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)app_data;
- struct Qdisc *qdisc = nq->qdisc;
- struct gnet_stats_basic_packed *bstats; /* Basic class statistics */
- struct gnet_stats_queue *qstats; /* Qstats for use by classes */
- atomic_t *refcnt;
-
- if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_qdisc_info("%s: Qdisc %p (type %d): Receive stats FAILED - "
- "response: type: %d\n", __func__, qdisc, nq->type,
- nim->msg.shaper_configure.config.response_type);
- atomic_sub(1, &nq->pending_stat_requests);
- return;
- }
-
- /*
- * Record latest basic stats
- */
- nq->basic_stats_latest = nim->msg.shaper_configure.config.msg.shaper_node_basic_stats_get;
-
- /*
- * Get the right stats pointers based on whether it is a class
- * or a qdisc.
- */
- if (nq->is_class) {
- bstats = &nq->bstats;
- qstats = &nq->qstats;
- refcnt = &nq->refcnt;
- } else {
- bstats = &qdisc->bstats;
- qstats = &qdisc->qstats;
- refcnt = &qdisc->refcnt;
- qdisc->q.qlen = nq->basic_stats_latest.qlen_packets;
- }
-
- /*
- * Get the right stats pointers based on whether it is a class
- * or a qdisc.
- */
- if (nq->is_class) {
- bstats = &nq->bstats;
- qstats = &nq->qstats;
- refcnt = &nq->refcnt;
- } else {
- bstats = &qdisc->bstats;
- qstats = &qdisc->qstats;
- refcnt = &qdisc->refcnt;
- qdisc->q.qlen = nq->basic_stats_latest.qlen_packets;
- }
-
- /*
- * Update qdisc->bstats
- */
- spin_lock_bh(&nq->lock);
- bstats->bytes += (__u64)nq->basic_stats_latest.delta.dequeued_bytes;
- bstats->packets += nq->basic_stats_latest.delta.dequeued_packets;
-
- /*
- * Update qdisc->qstats
- */
- qstats->backlog = nq->basic_stats_latest.qlen_bytes;
-
- qstats->drops += (nq->basic_stats_latest.delta.enqueued_packets_dropped +
- nq->basic_stats_latest.delta.dequeued_packets_dropped);
-
- /*
- * Update qdisc->qstats
- */
- qstats->qlen = nq->basic_stats_latest.qlen_packets;
- qstats->requeues = 0;
- qstats->overlimits += nq->basic_stats_latest.delta.queue_overrun;
- spin_unlock_bh(&nq->lock);
-
- /*
- * All access to nq fields below do not need lock protection. They
- * do not get manipulated on different thread contexts.
- */
- if (atomic_read(refcnt) == 0) {
- atomic_sub(1, &nq->pending_stat_requests);
- wake_up(&nss_qdics_wq);
- return;
- }
-
- /*
- * Requests for stats again, after 1 sec.
- */
- nq->stats_get_timer.expires += HZ;
- if (nq->stats_get_timer.expires <= jiffies) {
- nss_qdisc_warning("losing time %lu, jiffies = %lu\n",
- nq->stats_get_timer.expires, jiffies);
- nq->stats_get_timer.expires = jiffies + HZ;
- }
- add_timer(&nq->stats_get_timer);
-}
-
-/*
- * nss_qdisc_get_stats_timer_callback()
- * Invoked periodically to get updated stats
- */
-static void nss_qdisc_get_stats_timer_callback(unsigned long int data)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)data;
- nss_tx_status_t rc;
- struct nss_if_msg nim;
- int msg_type;
-
- /*
- * Create and send the shaper configure message to the NSS interface
- */
- msg_type = nss_qdisc_get_interface_msg(nq->is_bridge, NSS_QDISC_IF_SHAPER_CONFIG);
- nss_qdisc_msg_init(&nim, nq->nss_interface_number, msg_type, sizeof(struct nss_if_msg),
- (nss_if_msg_callback_t *)nss_qdisc_basic_stats_callback,
- nq);
- nim.msg.shaper_configure.config.request_type = NSS_SHAPER_CONFIG_TYPE_SHAPER_NODE_BASIC_STATS_GET;
- nim.msg.shaper_configure.config.msg.shaper_node_basic_stats_get.qos_tag = nq->qos_tag;
- rc = nss_if_tx_msg(nq->nss_shaping_ctx, &nim);
-
- if (rc != NSS_TX_SUCCESS) {
- nss_qdisc_error("%s: %p: basic stats get failed to send\n",
- __func__, nq->qdisc);
- atomic_sub(1, &nq->pending_stat_requests);
- wake_up(&nss_qdics_wq);
- }
-}
-
-/*
- * nss_qdisc_start_basic_stats_polling()
- * Call to initiate the stats polling timer
- */
-void nss_qdisc_start_basic_stats_polling(struct nss_qdisc *nq)
-{
- init_timer(&nq->stats_get_timer);
- nq->stats_get_timer.function = nss_qdisc_get_stats_timer_callback;
- nq->stats_get_timer.data = (unsigned long)nq;
- nq->stats_get_timer.expires = jiffies + HZ;
- atomic_set(&nq->pending_stat_requests, 1);
- add_timer(&nq->stats_get_timer);
-}
-
-/*
- * nss_qdisc_stop_basic_stats_polling()
- * Call to stop polling of basic stats
- */
-void nss_qdisc_stop_basic_stats_polling(struct nss_qdisc *nq)
-{
- /*
- * If the timer was active, then delete timer and return.
- */
- if (del_timer(&nq->stats_get_timer) > 0) {
- /*
- * The timer was still active (counting down) when it was deleted.
- * Therefore we are sure that there are no pending stats request
- * for which we need to wait for. We can therefore return.
- */
- return;
- }
-
- /*
- * The timer has already fired, which means we have a pending stat response.
- * We will have to wait until we have received the pending response.
- */
- if (!wait_event_timeout(nss_qdics_wq, atomic_read(&nq->pending_stat_requests) == 0,
- NSS_QDISC_COMMAND_TIMEOUT)) {
- nss_qdisc_error("Stats request command for %x timedout!\n", nq->qos_tag);
- }
-}
-
-/*
- * nss_qdisc_if_event_cb()
- * Callback function that is registered to listen to events on net_device.
- */
-static int nss_qdisc_if_event_cb(struct notifier_block *unused,
- unsigned long event, void *ptr)
-{
- struct net_device *dev = (struct net_device *)ptr;
- struct net_device *br;
- struct Qdisc *br_qdisc;
- int if_num, br_num;
-
- switch (event) {
- case NETDEV_BR_JOIN:
- nss_qdisc_info("Reveived NETDEV_BR_JOIN on interface %s\n",
- dev->name);
- case NETDEV_BR_LEAVE:
- nss_qdisc_info("Reveived NETDEV_BR_LEAVE on interface %s\n",
- dev->name);
- br = dev->master;
- if_num = nss_cmn_get_interface_number(nss_qdisc_ctx, dev);
-
- if (br == NULL || br->priv_flags != IFF_EBRIDGE) {
- nss_qdisc_error("Sensed bridge activity on interface %s "
- "that is not on any bridge\n", dev->name);
- break;
- }
-
- br_num = nss_cmn_get_interface_number(nss_qdisc_ctx, br);
- br_qdisc = br->qdisc;
- /*
- * TODO: Properly ensure that the interface and bridge are
- * shaped by us.
- */
- if (if_num < 0 || br_num < 0) {
- nss_qdisc_info("No action taken since if_num is %d for %s "
- "and br_num is %d for bridge %s\n", if_num,
- dev->name, br_num, br->name);
- break;
- }
-
- /*
- * Call attach or detach according as per event type.
- */
- if (event == NETDEV_BR_JOIN) {
- nss_qdisc_info("Instructing interface %s to attach to bridge(%s) "
- "shaping\n", dev->name, br->name);
- nss_qdisc_attach_bshaper(br_qdisc, if_num);
- } else if (event == NETDEV_BR_LEAVE) {
- nss_qdisc_info("Instructing interface %s to detach from bridge(%s) "
- "shaping\n",dev->name, br->name);
- nss_qdisc_detach_bshaper(br_qdisc, if_num);
- }
-
- break;
- default:
- nss_qdisc_info("Received NETDEV_DEFAULT on interface %s\n", dev->name);
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block nss_qdisc_device_notifier = {
- .notifier_call = nss_qdisc_if_event_cb };
-
-/*
- * TODO: Get the bridge related code out into nss_qdisc_bridge.c
- * Get the stats into nss_qdisc_stats.c
- *
- */
-
-/* ================== Module registration ================= */
-
-static int __init nss_qdisc_module_init(void)
-{
- int ret;
- nss_qdisc_info("Module initializing");
- nss_qdisc_ctx = nss_shaper_register_shaping();
-
- /*
- * Initialize the wait queue node
- */
- init_waitqueue_head(&nss_qdics_wq);
-
- ret = register_qdisc(&nss_pfifo_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nsspfifo registered");
-
- ret = register_qdisc(&nss_bfifo_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nssbfifo registered");
-
- ret = register_qdisc(&nss_codel_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nsscodel registered");
-
- ret = register_qdisc(&nss_tbl_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nsstbl registered");
-
- ret = register_qdisc(&nss_prio_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nssprio registered");
-
- ret = register_qdisc(&nss_bf_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nssbf registered");
-
- ret = register_qdisc(&nss_wrr_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nsswrr registered");
-
- ret = register_qdisc(&nss_wfq_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nsswfq registered");
-
- ret = register_qdisc(&nss_htb_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nsshtb registered");
-
- ret = register_qdisc(&nss_blackhole_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nssblackhole registered");
-
- ret = register_qdisc(&nss_red_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nssred registered");
-
- ret = register_qdisc(&nss_wred_qdisc_ops);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nsswred registered");
-
- ret = register_netdevice_notifier(&nss_qdisc_device_notifier);
- if (ret != 0)
- return ret;
- nss_qdisc_info("nss qdisc device notifiers registered");
-
- return 0;
-}
-
-static void __exit nss_qdisc_module_exit(void)
-{
- unregister_qdisc(&nss_pfifo_qdisc_ops);
- nss_qdisc_info("nsspfifo unregistered");
-
- unregister_qdisc(&nss_bfifo_qdisc_ops);
- nss_qdisc_info("nssbfifo unregistered");
-
- unregister_qdisc(&nss_codel_qdisc_ops);
- nss_qdisc_info("nsscodel unregistered");
-
- unregister_qdisc(&nss_tbl_qdisc_ops);
- nss_qdisc_info("nsstbl unregistered");
-
- unregister_qdisc(&nss_prio_qdisc_ops);
- nss_qdisc_info("nssprio unregistered");
-
- unregister_qdisc(&nss_bf_qdisc_ops);
- nss_qdisc_info("nssbf unregistered\n");
-
- unregister_qdisc(&nss_wrr_qdisc_ops);
- nss_qdisc_info("nsswrr unregistered\n");
-
- unregister_qdisc(&nss_wfq_qdisc_ops);
- nss_qdisc_info("nsswfq unregistered\n");
-
- unregister_qdisc(&nss_htb_qdisc_ops);
- nss_qdisc_info("nsshtb unregistered\n");
-
- unregister_qdisc(&nss_blackhole_qdisc_ops);
- nss_qdisc_info("nssblackhole unregistered\n");
-
- unregister_qdisc(&nss_red_qdisc_ops);
- nss_qdisc_info("nssred unregistered\n");
-
- unregister_qdisc(&nss_wred_qdisc_ops);
- nss_qdisc_info("nsswred unregistered\n");
-
- unregister_netdevice_notifier(&nss_qdisc_device_notifier);
-}
-
-module_init(nss_qdisc_module_init)
-module_exit(nss_qdisc_module_exit)
-
-MODULE_LICENSE("GPL");
diff --git a/nss_qdisc/nss_qdisc.h b/nss_qdisc/nss_qdisc.h
deleted file mode 100644
index 84a4944..0000000
--- a/nss_qdisc/nss_qdisc.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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 <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <net/pkt_sched.h>
-#include <net/inet_ecn.h>
-#include <net/netfilter/nf_conntrack.h>
-#include <linux/if_bridge.h>
-#include <linux/list.h>
-#include <linux/version.h>
-#include <br_private.h>
-#include <nss_api_if.h>
-
-/*
- * NSS QDisc debug macros
- */
-#if (NSS_QDISC_DEBUG_LEVEL < 1)
-#define nss_qdisc_assert(c, s, args...)
-#define nss_qdisc_error(fmt, args...)
-#else
-#define nss_qdisc_assert(c, s, args...) if (!(c)) { printk("%d:ASSERT:"s, __LINE__, ##args); BUG(); }
-#define nss_qdisc_error(fmt, args...) printk(KERN_ERR "%d:ERROR:"fmt, __LINE__, ##args)
-#endif
-
-#if (NSS_QDISC_DEBUG_LEVEL < 2)
-#define nss_qdisc_warning(fmt, args...)
-#else
-#define nss_qdisc_warning(fmt, args...) printk(KERN_WARNING "%d:WARN:"fmt, __LINE__, ##args)
-#endif
-
-#if (NSS_QDISC_DEBUG_LEVEL < 3)
-#define nss_qdisc_info(fmt, args...)
-#else
-#define nss_qdisc_info(fmt, args...) printk(KERN_INFO "%d:INFO:"fmt, __LINE__, ##args)
-#endif
-
-#if (NSS_QDISC_DEBUG_LEVEL < 4)
-#define nss_qdisc_trace(fmt, args...)
-#else
-#define nss_qdisc_trace(fmt, args...) printk(KERN_DEBUG "%d:TRACE:"fmt, __LINE__, ##args)
-#endif
-
-/*
- * State values
- */
-#define NSS_QDISC_STATE_IDLE 0
-#define NSS_QDISC_STATE_READY 1
-#define NSS_QDISC_STATE_BUSY 2
-
-#define NSS_QDISC_STATE_INIT_FAILED -1
-#define NSS_QDISC_STATE_ASSIGN_SHAPER_SEND_FAIL -2
-#define NSS_QDISC_STATE_SHAPER_ASSIGN_FAILED -3
-#define NSS_QDISC_STATE_NODE_ALLOC_SEND_FAIL -4
-#define NSS_QDISC_STATE_NODE_ALLOC_FAIL -5
-#define NSS_QDISC_STATE_ROOT_SET_SEND_FAIL -6
-#define NSS_QDISC_STATE_ROOT_SET_FAIL -7
-#define NSS_QDISC_STATE_DEFAULT_SET_SEND_FAIL -8
-#define NSS_QDISC_STATE_DEFAULT_SET_FAIL -9
-#define NSS_QDISC_STATE_CHILD_ALLOC_SEND_FAIL -10
-#define NSS_QDISC_STATE_NODE_ALLOC_FAIL_CHILD -11
-#define NSS_QDISC_STATE_FAILED_RESPONSE -12
-
-#define NSS_QDISC_BRIDGE_PORT_MAX 100
-
-
-struct nss_qdisc {
- struct Qdisc *qdisc; /* Handy pointer back to containing qdisc */
- struct nss_qdisc *parent; /* Pointer to parent nss qdisc */
- struct nss_qdisc *default_nq; /* Default enqueue node */
- void *nss_shaping_ctx; /* NSS context for general operations */
- int32_t nss_interface_number; /* NSS Interface number we are shaping on */
- nss_shaper_node_type_t type; /* Type of shaper node */
- bool is_class; /* True if this represents a class and not a qdisc */
- bool is_root; /* True if root qdisc on a net device */
- bool is_bridge; /* True when qdisc is a bridge */
- bool is_virtual; /* True when the device is represented as a virtual in
- * the NSS e.g. perhaps operating on a wifi interface
- * or bridge.
- */
- bool destroy_virtual_interface; /* Set if the interface is first registered in NSS by
- * us. This means it needs to be un-regisreted when the
- * module goes down.
- */
- atomic_t state; /* < 0: Signal that qdisc has 'failed'. 0
- * indicates 'pending' setup. > 0 is READY.
- * NOTE: volatile AND atomic - this is polled
- * AND is used for syncronisation.
- */
- uint32_t shaper_id; /* Used when is_root. Child qdiscs use this
- * information to know what shaper under
- * which to create shaper nodes
- */
- uint32_t qos_tag; /* QoS tag of this node */
- volatile int32_t pending_final_state; /* Used to let the callback cycle know what
- * state to set the qdisc in on successful
- * completion.
- */
- void *virtual_interface_context; /* Context provided by the NSS driver for
- * new interfaces that are registered.
- */
- void *bounce_context; /* Context for bounce registration. Bounce
- * enables packets to be sent to NSS for
- * shaping purposes, and is returned to
- * Linux for transmit.
- */
- spinlock_t bounce_protection_lock; /* Lock to protect the enqueue and dequeue
- * operation on skb lists triggeret by bounce
- * callbacks.
- */
- void (*stats_update_callback)(void *, struct nss_shaper_configure *);
- /* Stats update callback function for qdisc specific
- * stats update. Currently unused.
- */
- struct gnet_stats_basic_packed bstats; /* Basic class statistics */
- struct gnet_stats_queue qstats; /* Qstats for use by classes */
- atomic_t refcnt; /* Reference count for class use */
- struct timer_list stats_get_timer; /* Timer used to poll for stats */
- atomic_t pending_stat_requests; /* Number of pending stats responses */
- struct nss_shaper_shaper_node_basic_stats_get basic_stats_latest;
- /* Latest stats obtained */
- struct hlist_head *hash; /* Pointer to hash table */
- struct hlist_node hnode; /* Node for participating in a hlist */
- spinlock_t lock; /* Lock to protect the nss qdisc structure */
-};
-
-/*
- * nss_qdisc bridge update structure
- */
-struct nss_qdisc_bridge_update {
- int port_list[NSS_QDISC_BRIDGE_PORT_MAX];
- int port_list_count;
- int unassign_count;
-};
-
-/*
- * Task types for bridge scanner.
- */
-enum nss_qdisc_bshaper_tasks {
- NSS_QDISC_SCAN_AND_ASSIGN_BSHAPER,
- NSS_QDISC_SCAN_AND_UNASSIGN_BSHAPER,
-};
-
-/*
- * Types of messages sent down to NSS interfaces
- */
-enum nss_qdisc_interface_msgs {
- NSS_QDISC_IF_SHAPER_ASSIGN,
- NSS_QDISC_IF_SHAPER_UNASSIGN,
- NSS_QDISC_IF_SHAPER_CONFIG,
-};
-
-/*
- * nss_qdisc_peek()
- * Called to peek at the head of an nss qdisc
- */
-extern struct sk_buff *nss_qdisc_peek(struct Qdisc *sch);
-
-/*
- * nss_qdisc_drop()
- * Called to drop the packet at the head of queue
- */
-extern unsigned int nss_qdisc_drop(struct Qdisc *sch);
-
-/*
- * nss_qdisc_reset()
- * Called when a qdisc is reset
- */
-extern void nss_qdisc_reset(struct Qdisc *sch);
-
-/*
- * nss_qdisc_enqueue()
- * Generic enqueue call for enqueuing packets into NSS for shaping
- */
-extern int nss_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch);
-
-/*
- * nss_qdisc_dequeue()
- * Generic dequeue call for dequeuing bounced packets.
- */
-extern struct sk_buff *nss_qdisc_dequeue(struct Qdisc *sch);
-
-/*
- * nss_qdisc_node_set_default()
- * Configuration function that sets shaper node as default for packet enqueue
- */
-extern int nss_qdisc_set_default(struct nss_qdisc *nq);
-
-/*
- * nss_qdisc_node_attach()
- * Configuration function that helps attach a child shaper node to a parent.
- */
-extern int nss_qdisc_node_attach(struct nss_qdisc *nq, struct nss_qdisc *nq_child,
- struct nss_if_msg *nim, int32_t attach_type);
-
-/*
- * nss_qdisc_node_detach()
- * Configuration function that helps detach a child shaper node to a parent.
- */
-extern int nss_qdisc_node_detach(struct nss_qdisc *nq, struct nss_qdisc *nq_child,
- struct nss_if_msg *nim, int32_t detach_type);
-
-/*
- * nss_qdisc_configure()
- * Configuration function that aids in tuning of queuing parameters.
- */
-extern int nss_qdisc_configure(struct nss_qdisc *nq,
- struct nss_if_msg *nim, int32_t config_type);
-
-/*
- * nss_qdisc_destroy()
- * Destroys a shaper in NSS, and the sequence is based on the position of
- * this qdisc (child or root) and the interface to which it is attached to.
- */
-extern void nss_qdisc_destroy(struct nss_qdisc *nq);
-
-/*
- * nss_qdisc_init()
- * Initializes a shaper in NSS, based on the position of this qdisc (child or root)
- * and if its a normal interface or a bridge interface.
- */
-extern int nss_qdisc_init(struct Qdisc *sch, struct nss_qdisc *nq, nss_shaper_node_type_t type, uint32_t classid);
-
-/*
- * nss_qdisc_start_basic_stats_polling()
- * Call to initiate the stats polling timer
- */
-extern void nss_qdisc_start_basic_stats_polling(struct nss_qdisc *nq);
-
-/*
- * nss_qdisc_stop_basic_stats_polling()
- * Call to stop polling of basic stats
- */
-extern void nss_qdisc_stop_basic_stats_polling(struct nss_qdisc *nq);
diff --git a/nss_qdisc/nss_tbl.c b/nss_qdisc/nss_tbl.c
deleted file mode 100644
index d86e15c..0000000
--- a/nss_qdisc/nss_tbl.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_qdisc.h"
-
-struct nss_tbl_sched_data {
- struct nss_qdisc nq; /* Common base class for all nss qdiscs */
- u32 rate; /* Limiting rate of TBL */
- u32 peakrate; /* Maximum rate to control bursts */
- u32 burst; /* Maximum allowed burst size */
- u32 mtu; /* MTU of the interface attached to */
- struct Qdisc *qdisc; /* Qdisc to which it is attached to */
-};
-
-
-static int nss_tbl_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- return nss_qdisc_enqueue(skb, sch);
-}
-
-static struct sk_buff *nss_tbl_dequeue(struct Qdisc *sch)
-{
- return nss_qdisc_dequeue(sch);
-}
-
-static unsigned int nss_tbl_drop(struct Qdisc *sch)
-{
- return nss_qdisc_drop(sch);
-}
-
-static struct sk_buff *nss_tbl_peek(struct Qdisc *sch)
-{
- return nss_qdisc_peek(sch);
-}
-
-static void nss_tbl_reset(struct Qdisc *sch)
-{
- nss_qdisc_reset(sch);
-}
-
-static void nss_tbl_destroy(struct Qdisc *sch)
-{
- struct nss_tbl_sched_data *q = qdisc_priv(sch);
- struct nss_qdisc *nq_child = (struct nss_qdisc *)qdisc_priv(q->qdisc);
- struct nss_if_msg nim;
-
- /*
- * We must always detach our child node in NSS before destroying it.
- * Also, we make sure we dont send down the command for noop qdiscs.
- */
- if (q->qdisc != &noop_qdisc) {
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- if (nss_qdisc_node_detach(&q->nq, nq_child, &nim,
- NSS_SHAPER_CONFIG_TYPE_TBL_DETACH) < 0) {
- nss_qdisc_error("%s: Failed to detach child %x from nss_tbl %x\n",
- __func__, q->qdisc->handle, q->nq.qos_tag);
- return;
- }
- }
-
- /*
- * Now we can destroy our child qdisc
- */
- qdisc_destroy(q->qdisc);
-
- /*
- * Stop the polling of basic stats and destroy qdisc.
- */
- nss_qdisc_stop_basic_stats_polling(&q->nq);
- nss_qdisc_destroy(&q->nq);
-}
-
-static const struct nla_policy nss_tbl_policy[TCA_NSSTBL_MAX + 1] = {
- [TCA_NSSTBL_PARMS] = { .len = sizeof(struct tc_nsstbl_qopt) },
-};
-
-static int nss_tbl_change(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_tbl_sched_data *q = qdisc_priv(sch);
- struct nlattr *na[TCA_NSSTBL_MAX + 1];
- struct tc_nsstbl_qopt *qopt;
- struct nss_if_msg nim;
- int err;
- struct net_device *dev = qdisc_dev(sch);
-
- if (opt == NULL)
- return -EINVAL;
-
- err = nla_parse_nested(na, TCA_NSSTBL_MAX, opt, nss_tbl_policy);
- if (err < 0)
- return err;
-
- if (na[TCA_NSSTBL_PARMS] == NULL)
- return -EINVAL;
-
- qopt = nla_data(na[TCA_NSSTBL_PARMS]);
-
- /*
- * Set MTU if it wasn't specified explicitely
- */
- if (!qopt->mtu) {
- qopt->mtu = psched_mtu(dev);
- nss_qdisc_info("MTU not provided for nss_tbl. Setting it to %s's default %u bytes\n", dev->name, qopt->mtu);
- }
-
- /*
- * Burst size cannot be less than MTU
- */
- if (qopt->burst < qopt->mtu) {
- nss_qdisc_error("Burst size: %u is less than the specified MTU: %u\n", qopt->burst, qopt->mtu);
- return -EINVAL;
- }
-
- /*
- * Rate can be zero. Therefore we dont do a check on it.
- */
- q->rate = qopt->rate;
- nss_qdisc_info("Rate = %u", qopt->rate);
- q->burst = qopt->burst;
- nss_qdisc_info("Burst = %u", qopt->burst);
- q->mtu = qopt->mtu;
- nss_qdisc_info("MTU = %u", qopt->mtu);
- q->peakrate = qopt->peakrate;
- nss_qdisc_info("Peak Rate = %u", qopt->peakrate);
-
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.tbl_param.lap_cir.rate = q->rate;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.tbl_param.lap_cir.burst = q->burst;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.tbl_param.lap_cir.max_size = q->mtu;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.tbl_param.lap_cir.short_circuit = false;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.tbl_param.lap_pir.rate = q->peakrate;
-
- /*
- * It is important to set these two parameters to be the same as MTU.
- * This ensures bursts from CIR dont go above the specified peakrate.
- */
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.tbl_param.lap_pir.burst = q->mtu;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.tbl_param.lap_pir.max_size = q->mtu;
-
- /*
- * We can short circuit peakrate limiter if it is not being configured.
- */
- if (q->peakrate) {
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.tbl_param.lap_pir.short_circuit = false;
- } else {
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.tbl_param.lap_pir.short_circuit = true;
- }
-
- if (nss_qdisc_configure(&q->nq, &nim, NSS_SHAPER_CONFIG_TYPE_TBL_CHANGE_PARAM) < 0) {
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int nss_tbl_init(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_tbl_sched_data *q = qdisc_priv(sch);
-
- if (opt == NULL)
- return -EINVAL;
-
- q->qdisc = &noop_qdisc;
-
- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_TBL, 0) < 0)
- return -EINVAL;
-
- if (nss_tbl_change(sch, opt) < 0) {
- nss_qdisc_info("Failed to configure tbl\n");
- nss_qdisc_destroy(&q->nq);
- return -EINVAL;
- }
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(&q->nq);
-
- return 0;
-}
-
-static int nss_tbl_dump(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct nss_tbl_sched_data *q = qdisc_priv(sch);
- struct nlattr *opts = NULL;
- struct tc_nsstbl_qopt opt = {
- .rate = q->rate,
- .peakrate = q->peakrate,
- .burst = q->burst,
- .mtu = q->mtu,
- };
-
- nss_qdisc_info("Nsstbl dumping");
- opts = nla_nest_start(skb, TCA_OPTIONS);
- if (opts == NULL)
- goto nla_put_failure;
- NLA_PUT(skb, TCA_NSSTBL_PARMS, sizeof(opt), &opt);
- return nla_nest_end(skb, opts);
-
-nla_put_failure:
- nla_nest_cancel(skb, opts);
- return -EMSGSIZE;
-}
-
-static int nss_tbl_dump_class(struct Qdisc *sch, unsigned long cl,
- struct sk_buff *skb, struct tcmsg *tcm)
-{
- struct nss_tbl_sched_data *q = qdisc_priv(sch);
- nss_qdisc_info("Nsstbl dumping class");
-
- tcm->tcm_handle |= TC_H_MIN(1);
- tcm->tcm_info = q->qdisc->handle;
-
- return 0;
-}
-
-static int nss_tbl_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
- struct Qdisc **old)
-{
- struct nss_tbl_sched_data *q = qdisc_priv(sch);
- struct nss_qdisc *nq_new = (struct nss_qdisc *)qdisc_priv(new);
- struct nss_if_msg nim_attach;
- struct nss_if_msg nim_detach;
-
- if (new == NULL)
- new = &noop_qdisc;
-
- sch_tree_lock(sch);
- *old = q->qdisc;
- q->qdisc = new;
- qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
- qdisc_reset(*old);
- sch_tree_unlock(sch);
-
- nss_qdisc_info("%s:Grafting old: %p with new: %p\n", __func__, *old, new);
- if (*old != &noop_qdisc) {
- struct nss_qdisc *nq_old = (struct nss_qdisc *)qdisc_priv(*old);
- nss_qdisc_info("%s: Detaching old: %p\n", __func__, *old);
- nim_detach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- if (nss_qdisc_node_detach(&q->nq, nq_old, &nim_detach,
- NSS_SHAPER_CONFIG_TYPE_TBL_DETACH) < 0) {
- return -EINVAL;
- }
- }
-
- if (new != &noop_qdisc) {
- nss_qdisc_info("%s: Attaching new: %p\n", __func__, new);
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.snc.tbl_attach.child_qos_tag = nq_new->qos_tag;
- if (nss_qdisc_node_attach(&q->nq, nq_new, &nim_attach,
- NSS_SHAPER_CONFIG_TYPE_TBL_ATTACH) < 0) {
- return -EINVAL;
- }
- }
-
- nss_qdisc_info("Nsstbl grafted");
-
- return 0;
-}
-
-static struct Qdisc *nss_tbl_leaf(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_tbl_sched_data *q = qdisc_priv(sch);
- nss_qdisc_info("Nsstbl returns leaf");
- return q->qdisc;
-}
-
-static unsigned long nss_tbl_get(struct Qdisc *sch, u32 classid)
-{
- return 1;
-}
-
-static void nss_tbl_put(struct Qdisc *sch, unsigned long arg)
-{
-}
-
-static void nss_tbl_walk(struct Qdisc *sch, struct qdisc_walker *walker)
-{
- nss_qdisc_info("Nsstbl walk called");
- if (!walker->stop) {
- if (walker->count >= walker->skip)
- if (walker->fn(sch, 1, walker) < 0) {
- walker->stop = 1;
- return;
- }
- walker->count++;
- }
-}
-
-const struct Qdisc_class_ops nss_tbl_class_ops = {
- .graft = nss_tbl_graft,
- .leaf = nss_tbl_leaf,
- .get = nss_tbl_get,
- .put = nss_tbl_put,
- .walk = nss_tbl_walk,
- .dump = nss_tbl_dump_class,
-};
-
-struct Qdisc_ops nss_tbl_qdisc_ops __read_mostly = {
- .next = NULL,
- .id = "nsstbl",
- .priv_size = sizeof(struct nss_tbl_sched_data),
- .cl_ops = &nss_tbl_class_ops,
- .enqueue = nss_tbl_enqueue,
- .dequeue = nss_tbl_dequeue,
- .peek = nss_tbl_peek,
- .drop = nss_tbl_drop,
- .init = nss_tbl_init,
- .reset = nss_tbl_reset,
- .destroy = nss_tbl_destroy,
- .change = nss_tbl_change,
- .dump = nss_tbl_dump,
- .owner = THIS_MODULE,
-};
-
diff --git a/nss_qdisc/nss_tbl.h b/nss_qdisc/nss_tbl.h
deleted file mode 100644
index d9a9c33..0000000
--- a/nss_qdisc/nss_tbl.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-extern struct Qdisc_ops nss_tbl_qdisc_ops;
diff --git a/nss_qdisc/nss_wfq.h b/nss_qdisc/nss_wfq.h
deleted file mode 100644
index 27b8550..0000000
--- a/nss_qdisc/nss_wfq.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-extern struct Qdisc_ops nss_wfq_qdisc_ops;
diff --git a/nss_qdisc/nss_wred.c b/nss_qdisc/nss_wred.c
deleted file mode 100644
index 875807e..0000000
--- a/nss_qdisc/nss_wred.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_qdisc.h"
-
-#define NSS_WRED_SUPPORT_TRAFFIC_CLASS 6
-#define NSS_WRED_MAX_TRAFFIC_CLASS NSS_WRED_SUPPORT_TRAFFIC_CLASS+1
-
-/*
- * nsswred traffic class structure
- */
-struct nss_wred_traffic_class {
- u32 limit; /* Queue length */
- u32 weight_mode_value; /* Weight mode value */
- struct tc_red_alg_parameter rap;/* Parameters for RED alg */
-};
-
-/*
- * nsswred private qdisc structure
- */
-struct nss_wred_sched_data {
- struct nss_qdisc nq; /* Common base class for all nss qdiscs */
- u32 traffic_classes; /* # of traffic classs in this wred*/
- u32 def_traffic_class; /* Default traffic class if no match */
- tc_nsswred_weight_mode_t weight_mode; /* Weight mode */
- struct nss_wred_traffic_class nwtc[NSS_WRED_MAX_TRAFFIC_CLASS];
- /* Parameters for each traffic class */
- u8 ecn; /* Mark ECN or drop pkt */
- u8 weighted; /* This is a wred or red */
-};
-
-/*
- * nss_wred_enqueue()
- * Enqueue API for nsswred qdisc
- */
-static int nss_wred_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- return nss_qdisc_enqueue(skb, sch);
-}
-
-/*
- * nss_wred_dequeue()
- * Dequeue API for nsswred qdisc
- */
-static struct sk_buff *nss_wred_dequeue(struct Qdisc *sch)
-{
- return nss_qdisc_dequeue(sch);
-}
-
-/*
- * nss_wred_drop()
- * Drops a packet from HLOS queue.
- */
-static unsigned int nss_wred_drop(struct Qdisc *sch)
-{
- nss_qdisc_info("nsswred dropping");
- return nss_qdisc_drop(sch);
-}
-
-/*
- * nss_wred_reset()
- * Reset the nsswred qdisc
- */
-static void nss_wred_reset(struct Qdisc *sch)
-{
- nss_qdisc_info("nsswred resetting!");
- nss_qdisc_reset(sch);
-}
-
-/*
- * nss_wred_destroy()
- * Destroy the nsswred qdisc
- */
-static void nss_wred_destroy(struct Qdisc *sch)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)qdisc_priv(sch);
-
- /*
- * Stop the polling of basic stats
- */
- nss_qdisc_stop_basic_stats_polling(nq);
-
- nss_qdisc_destroy(nq);
- nss_qdisc_info("nsswred destroyed");
-}
-
-/*
- * nsswred policy structure
- */
-static const struct nla_policy nss_wred_policy[TCA_NSSWRED_MAX + 1] = {
- [TCA_NSSWRED_PARMS] = { .len = sizeof(struct tc_nsswred_qopt) },
-};
-
-/*
- * nss_wred_change()
- * Function call to configure the nsswred parameters
- */
-static int nss_wred_change(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_wred_sched_data *q;
- struct nlattr *na[TCA_NSSWRED_MAX + 1];
- struct tc_nsswred_qopt *qopt;
- int err;
- struct nss_if_msg nim;
-
- q = qdisc_priv(sch);
-
- if (opt == NULL) {
- return -EINVAL;
- }
- err = nla_parse_nested(na, TCA_NSSWRED_MAX, opt, nss_wred_policy);
- if (err < 0) {
- return err;
- }
- if (na[TCA_NSSWRED_PARMS] == NULL) {
- return -EINVAL;
- }
- qopt = nla_data(na[TCA_NSSWRED_PARMS]);
-
- nss_qdisc_info("%s: nsswred %x traffic_classes:%d def_traffic_class: %d Weight_Mode:%d ECN:%d\n",
- __func__, sch->handle, qopt->traffic_classes, qopt->def_traffic_class, qopt->weight_mode, qopt->ecn);
-
- if (qopt->traffic_classes) {
- /*
- * This is a wred setup command, do checks again because parameters might not come from tc utility
- */
- if (qopt->traffic_classes > NSS_WRED_SUPPORT_TRAFFIC_CLASS) {
- nss_qdisc_error("%s: nsswred %x traffic classes should not exceeds %d\n", __func__, sch->handle, NSS_WRED_SUPPORT_TRAFFIC_CLASS);
- return -EINVAL;
- }
- if (qopt->def_traffic_class < 1 || qopt->def_traffic_class > qopt->traffic_classes) {
- nss_qdisc_error("%s: nsswred %x invalid default traffic\n", __func__, sch->handle);
- return -EINVAL;
- }
- if (qopt->weight_mode >= TC_NSSWRED_WEIGHT_MODES) {
- nss_qdisc_error("%s: nsswred %x invalid weight_mode\n", __func__, sch->handle);
- return -EINVAL;
- }
- q->traffic_classes = qopt->traffic_classes ;
- q->def_traffic_class = qopt->def_traffic_class;
- q->weight_mode = qopt->weight_mode;
- q->ecn = qopt->ecn;
- q->weighted = 1;
- } else {
- if (qopt->traffic_id) {
- /*
- * This is a wred traffic class command
- */
- if (!q->traffic_classes) {
- nss_qdisc_error("%s: nsswred %x not setup yet, can't accept traffic class configuration\n", __func__, sch->handle);
- return -EINVAL;
- }
- if (!qopt->limit || !qopt->rap.min || !qopt->rap.max || !qopt->weight_mode_value || !qopt->rap.exp_weight_factor) {
- nss_qdisc_error("%s: nsswred %x Requires RED algorithm parameters and weight_mode_value\n", __func__, sch->handle);
- return -EINVAL;
- }
- } else {
- /*
- * This is a red setup command
- */
- if (!qopt->limit || !qopt->rap.exp_weight_factor) {
- nss_qdisc_error("%s: nsswred %x Requires RED algorithm parameters\n", __func__, sch->handle);
- return -EINVAL;
- }
- /*
- * If min/max does not specify, calculated it
- */
- if (!qopt->rap.max) {
- qopt->rap.max = qopt->rap.min ? qopt->rap.min * 3 : qopt->limit / 4;
- }
- if (!qopt->rap.min) {
- qopt->rap.min = qopt->rap.max / 3;
- }
- q->ecn = qopt->ecn;
- }
- q->nwtc[qopt->traffic_id].limit = qopt->limit;
- q->nwtc[qopt->traffic_id].weight_mode_value = qopt->weight_mode_value;
- q->nwtc[qopt->traffic_id].rap.min = qopt->rap.min;
- q->nwtc[qopt->traffic_id].rap.max = qopt->rap.max;
- q->nwtc[qopt->traffic_id].rap.probability = qopt->rap.probability;
- q->nwtc[qopt->traffic_id].rap.exp_weight_factor = qopt->rap.exp_weight_factor;
- }
-
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.limit = qopt->limit;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.weight_mode = qopt->weight_mode;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.weight_mode_value = qopt->weight_mode_value;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.rap.min = qopt->rap.min;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.rap.max = qopt->rap.max;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.rap.probability = qopt->rap.probability;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.rap.exp_weight_factor = qopt->rap.exp_weight_factor;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.traffic_classes = qopt->traffic_classes;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.ecn = qopt->ecn;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.def_traffic_class = qopt->def_traffic_class;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wred_param.traffic_id = qopt->traffic_id;
-
- if (nss_qdisc_configure(&q->nq, &nim, NSS_SHAPER_CONFIG_TYPE_SHAPER_NODE_CHANGE_PARAM) < 0) {
- nss_qdisc_error("%s: nsswred %x configuration failed\n", __func__, sch->handle);
- return -EINVAL;
- }
-
- if (qopt->set_default == 0)
- return 0;
-
- /*
- * Set this qdisc to be the default qdisc for enqueuing packets.
- */
- if (nss_qdisc_set_default(&q->nq) < 0) {
- nss_qdisc_error("%s: nsswred %x set_default failed\n", __func__, sch->handle);
- return -EINVAL;
- }
-
- nss_qdisc_info("%s: nsswred queue (qos_tag:%u) set as default\n", __func__, q->nq.qos_tag);
-
- return 0;
-}
-
-/*
- * nss_wred_init()
- * Init the nsswred qdisc
- */
-static int nss_wred_init(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_qdisc *nq = qdisc_priv(sch);
-
- if (opt == NULL)
- return -EINVAL;
-
- nss_qdisc_info("Initializing Wred - type %d\n", NSS_SHAPER_NODE_TYPE_WRED);
- nss_wred_reset(sch);
-
- if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_WRED, 0) < 0)
- return -EINVAL;
-
- nss_qdisc_info("NSS wred initialized - handle %x parent %x\n", sch->handle, sch->parent);
- if (nss_wred_change(sch, opt) < 0) {
- nss_qdisc_destroy(nq);
- return -EINVAL;
- }
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(nq);
-
- return 0;
-}
-
-/*
- * nss_wred_dump()
- * Dump the parameters of nsswred to tc
- */
-static int nss_wred_dump(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct nss_wred_sched_data *q;
- struct nlattr *opts = NULL;
- struct tc_nsswred_qopt opt;
- int i;
- nss_qdisc_info("Nsswred Dumping!");
-
- q = qdisc_priv(sch);
- if (q == NULL) {
- return -1;
- }
-
- if (q->weighted) {
- opt.traffic_classes = q->traffic_classes;
- opt.def_traffic_class = q->def_traffic_class;
- opt.ecn = q->ecn;
- opt.weight_mode = q->weight_mode;
- for (i = 0 ; i < q->traffic_classes; i++) {
- opt.tntc[i].limit = q->nwtc[i+1].limit;
- opt.tntc[i].weight_mode_value = q->nwtc[i+1].weight_mode_value;
- opt.tntc[i].rap.exp_weight_factor = q->nwtc[i+1].rap.exp_weight_factor;
- opt.tntc[i].rap.min = q->nwtc[i+1].rap.min;
- opt.tntc[i].rap.max = q->nwtc[i+1].rap.max;
- opt.tntc[i].rap.probability = q->nwtc[i+1].rap.probability;
- }
- } else {
- opt.ecn = q->ecn;
- opt.limit = q->nwtc[0].limit;
- opt.rap.min = q->nwtc[0].rap.min;
- opt.rap.max = q->nwtc[0].rap.max;
- opt.rap.exp_weight_factor = q->nwtc[0].rap.exp_weight_factor;
- opt.rap.probability = q->nwtc[0].rap.probability;
- }
-
- opts = nla_nest_start(skb, TCA_OPTIONS);
- if (opts == NULL) {
- goto nla_put_failure;
- }
- if (nla_put(skb, TCA_NSSWRED_PARMS, sizeof(opt), &opt))
- goto nla_put_failure;
-
- return nla_nest_end(skb, opts);
-
-nla_put_failure:
- nla_nest_cancel(skb, opts);
- return -EMSGSIZE;
-}
-
-/*
- * nss_wred_peek()
- * Peeks the first packet in queue for this qdisc
- */
-static struct sk_buff *nss_wred_peek(struct Qdisc *sch)
-{
- nss_qdisc_info("Nsswred Peeking");
- return nss_qdisc_peek(sch);
-}
-
-/*
- * Registration structure for nss_red qdisc
- */
-struct Qdisc_ops nss_red_qdisc_ops __read_mostly = {
- .id = "nssred",
- .priv_size = sizeof(struct nss_wred_sched_data),
- .enqueue = nss_wred_enqueue,
- .dequeue = nss_wred_dequeue,
- .peek = nss_wred_peek,
- .drop = nss_wred_drop,
- .init = nss_wred_init,
- .reset = nss_wred_reset,
- .destroy = nss_wred_destroy,
- .change = nss_wred_change,
- .dump = nss_wred_dump,
- .owner = THIS_MODULE,
-};
-
-/*
- * Registration structure for nss_wred qdisc
- */
-struct Qdisc_ops nss_wred_qdisc_ops __read_mostly = {
- .id = "nsswred",
- .priv_size = sizeof(struct nss_wred_sched_data),
- .enqueue = nss_wred_enqueue,
- .dequeue = nss_wred_dequeue,
- .peek = nss_wred_peek,
- .drop = nss_wred_drop,
- .init = nss_wred_init,
- .reset = nss_wred_reset,
- .destroy = nss_wred_destroy,
- .change = nss_wred_change,
- .dump = nss_wred_dump,
- .owner = THIS_MODULE,
-};
diff --git a/nss_qdisc/nss_wred.h b/nss_qdisc/nss_wred.h
deleted file mode 100644
index 1666400..0000000
--- a/nss_qdisc/nss_wred.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-extern struct Qdisc_ops nss_red_qdisc_ops;
-extern struct Qdisc_ops nss_wred_qdisc_ops;
diff --git a/nss_qdisc/nss_wrr.c b/nss_qdisc/nss_wrr.c
deleted file mode 100644
index f3aa95e..0000000
--- a/nss_qdisc/nss_wrr.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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_qdisc.h"
-
-struct nss_wrr_class_data {
- struct nss_qdisc nq; /* Base class used by nss_qdisc */
- struct Qdisc_class_common cl_common; /* Common class structure */
- u32 quantum; /* Quantum allocation for DRR */
- struct Qdisc *qdisc; /* Pointer to child qdisc */
-};
-
-struct nss_wrr_sched_data {
- struct nss_qdisc nq; /* Base class used by nss_qdisc */
- struct nss_wrr_class_data root; /* root class */
- struct Qdisc_class_hash clhash; /* class hash */
-};
-
-static inline struct nss_wrr_class_data *nss_wrr_find_class(u32 classid,
- struct Qdisc *sch)
-{
- struct nss_wrr_sched_data *q = qdisc_priv(sch);
- struct Qdisc_class_common *clc;
- clc = qdisc_class_find(&q->clhash, classid);
- if (clc == NULL) {
- nss_qdisc_warning("%s: Cannot find class with classid %u in qdisc %p hash table %p\n", __func__, classid, sch, &q->clhash);
- return NULL;
- }
- return container_of(clc, struct nss_wrr_class_data, cl_common);
-}
-
-static const struct nla_policy nss_wrr_policy[TCA_NSSWRR_MAX + 1] = {
- [TCA_NSSWRR_CLASS_PARMS] = { .len = sizeof(struct tc_nsswrr_class_qopt) },
-};
-
-static void nss_wrr_destroy_class(struct Qdisc *sch, struct nss_wrr_class_data *cl)
-{
- struct nss_wrr_sched_data *q = qdisc_priv(sch);
- struct nss_if_msg nim;
-
- nss_qdisc_info("Destroying nss_wrr class %p from qdisc %p\n", cl, sch);
-
- /*
- * Note, this function gets called even for NSSWRR and not just for NSSWRR_GROUP.
- * If this is wrr qdisc then we should not call nss_qdisc_destroy or stop polling
- * for stats. These two actions will happen inside nss_wrr_destroy(), which is called
- * only for the root qdisc.
- */
- if (cl == &q->root) {
- nss_qdisc_info("%s: We do not destroy nss_wrr class %p here since this is "
- "the qdisc %p\n", __func__, cl, sch);
- return;
- }
-
- /*
- * We always have to detach our child qdisc in NSS, before destroying it.
- */
- if (cl->qdisc != &noop_qdisc) {
- struct nss_qdisc *nq_child = qdisc_priv(cl->qdisc);
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- if (nss_qdisc_node_detach(&cl->nq, nq_child, &nim,
- NSS_SHAPER_CONFIG_TYPE_WRR_GROUP_DETACH) < 0) {
- nss_qdisc_error("%s: Failed to detach child %x from class %x\n",
- __func__, cl->qdisc->handle, q->nq.qos_tag);
- return;
- }
- }
-
- /*
- * And now we destroy the child.
- */
- qdisc_destroy(cl->qdisc);
-
- /*
- * Stop the stats polling timer and free class
- */
- nss_qdisc_stop_basic_stats_polling(&cl->nq);
-
- /*
- * Destroy the shaper in NSS
- */
- nss_qdisc_destroy(&cl->nq);
-
- /*
- * Free class
- */
- kfree(cl);
-}
-
-static int nss_wrr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
- struct nlattr **tca, unsigned long *arg)
-{
- struct nss_wrr_sched_data *q = qdisc_priv(sch);
- struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)*arg;
- struct nlattr *opt = tca[TCA_OPTIONS];
- struct nlattr *na[TCA_NSSWRR_MAX + 1];
- struct tc_nsswrr_class_qopt *qopt;
- struct nss_if_msg nim_config;
- struct net_device *dev = qdisc_dev(sch);
- bool new_init = false;
- int err;
-
- nss_qdisc_info("%s: Changing nss_wrr class %u\n", __func__, classid);
- if (opt == NULL)
- return -EINVAL;
-
- err = nla_parse_nested(na, TCA_NSSWRR_MAX, opt, nss_wrr_policy);
- if (err < 0)
- return err;
-
- if (na[TCA_NSSWRR_CLASS_PARMS] == NULL)
- return -EINVAL;
-
- /*
- * If class with a given classid is not found, we allocate a new one
- */
- if (!cl) {
-
- struct nss_if_msg nim_attach;
-
- /*
- * The class does not already exist, we are newly initializing it.
- */
- new_init = true;
-
- nss_qdisc_info("%s: nss_wrr class %u not found. Allocating a new class.\n", __func__, classid);
- cl = kzalloc(sizeof(struct nss_wrr_class_data), GFP_KERNEL);
-
- if (!cl) {
- nss_qdisc_error("%s: Class allocation failed for classid %u\n", __func__, classid);
- return -EINVAL;
- }
-
- nss_qdisc_info("%s: Bf class %u allocated %p\n", __func__, classid, cl);
- cl->cl_common.classid = classid;
-
- /*
- * We make the child qdisc a noop qdisc, and
- * set reference count to 1. This is important,
- * reference count should not be 0.
- */
- cl->qdisc = &noop_qdisc;
- atomic_set(&cl->nq.refcnt, 1);
- *arg = (unsigned long)cl;
-
- nss_qdisc_info("%s: Adding classid %u to qdisc %p hash queue %p\n", __func__, classid, sch, &q->clhash);
-
- /*
- * This is where a class gets initialized. Classes do not have a init function
- * that is registered to Linux. Therefore we initialize the NSSWRR_GROUP shaper
- * here.
- */
- if (nss_qdisc_init(sch, &cl->nq, NSS_SHAPER_NODE_TYPE_WRR_GROUP, classid) < 0) {
- nss_qdisc_error("%s: Nss init for class %u failed\n", __func__, classid);
- return -EINVAL;
- }
-
- /*
- * Set qos_tag of parent to which the class needs to e attached to.
- */
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
-
- /*
- * Set the child to be this class.
- */
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.snc.wrr_attach.child_qos_tag = cl->nq.qos_tag;
-
- /*
- * Send node_attach command down to the NSS
- */
- if (nss_qdisc_node_attach(&q->nq, &cl->nq, &nim_attach,
- NSS_SHAPER_CONFIG_TYPE_WRR_ATTACH) < 0) {
- nss_qdisc_error("%s: Nss attach for class %u failed\n", __func__, classid);
- nss_qdisc_destroy(&cl->nq);
- return -EINVAL;
- }
-
- /*
- * Add class to hash tree once it is attached in the NSS
- */
- sch_tree_lock(sch);
- qdisc_class_hash_insert(&q->clhash, &cl->cl_common);
- sch_tree_unlock(sch);
-
- /*
- * Hash grow should not come within the tree lock
- */
- qdisc_class_hash_grow(sch, &q->clhash);
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(&cl->nq);
-
- nss_qdisc_info("%s: Class %u successfully allocated\n", __func__, classid);
- }
-
- qopt = nla_data(na[TCA_NSSWRR_CLASS_PARMS]);
-
- sch_tree_lock(sch);
-
- /*
- * If the value of quantum is not provided default it based on the type
- * of operation (i.e. wrr or wfq)
- */
- cl->quantum = qopt->quantum;
- if (!cl->quantum) {
- if (strncmp(sch->ops->id, "nss_wrr", 6) == 0) {
- cl->quantum = 1;
- nss_qdisc_info("Quantum value not provided for nss_wrr class on interface %s. "
- "Setting quantum to %up\n", dev->name, cl->quantum);
- } else if (strncmp(sch->ops->id, "nsswfq", 6) == 0) {
- cl->quantum = psched_mtu(dev);
- nss_qdisc_info("Quantum value not provided for nss_wrr class on interface %s. "
- "Setting quantum to %ubytes\n", dev->name, cl->quantum);
- } else {
- nss_qdisc_error("%s: Unsupported parent type", __func__);
- return -EINVAL;
- }
- }
-
- sch_tree_unlock(sch);
-
- /*
- * Fill information that needs to be sent down to the NSS for configuring the
- * bf class.
- */
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- nim_config.msg.shaper_configure.config.msg.shaper_node_config.snc.wrr_group_param.quantum = cl->quantum;
-
- nss_qdisc_info("Quantum = %u\n", cl->quantum);
-
- /*
- * Send configure command to the NSS
- */
- if (nss_qdisc_configure(&cl->nq, &nim_config,
- NSS_SHAPER_CONFIG_TYPE_WRR_GROUP_CHANGE_PARAM) < 0) {
- nss_qdisc_error("%s: Failed to configure class %x\n", __func__, classid);
-
- /*
- * We dont have to destroy the class if this was just a
- * change command.
- */
- if (!new_init) {
- return -EINVAL;
- }
-
- /*
- * Else, we have failed in the NSS and we will have to
- * destroy the class
- */
- nss_wrr_destroy_class(sch, cl);
- return -EINVAL;
- }
-
- nss_qdisc_info("%s: Class %x changed successfully\n", __func__, classid);
- return 0;
-}
-
-static int nss_wrr_delete_class(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_wrr_sched_data *q = qdisc_priv(sch);
- struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)arg;
- struct nss_if_msg nim;
- int refcnt;
-
- /*
- * Since all classes are leaf nodes in our case, we dont have to make
- * that check.
- */
- if (cl == &q->root)
- return -EBUSY;
-
- /*
- * The message to NSS should be sent to the parent of this class
- */
- nss_qdisc_info("%s: Detaching nss_wrr class: %p\n", __func__, cl);
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wrr_detach.child_qos_tag = cl->nq.qos_tag;
- if (nss_qdisc_node_detach(&q->nq, &cl->nq, &nim,
- NSS_SHAPER_CONFIG_TYPE_WRR_DETACH) < 0) {
- return -EINVAL;
- }
-
- sch_tree_lock(sch);
- qdisc_reset(cl->qdisc);
- qdisc_class_hash_remove(&q->clhash, &cl->cl_common);
- refcnt = atomic_sub_return(1, &cl->nq.refcnt);
- sch_tree_unlock(sch);
- if (!refcnt) {
- nss_qdisc_error("%s: Reference count should not be zero for class %p\n", __func__, cl);
- }
-
- return 0;
-}
-
-static int nss_wrr_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
- struct Qdisc **old)
-{
- struct nss_wrr_sched_data *q = qdisc_priv(sch);
- struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)arg;
- struct nss_if_msg nim_detach;
- struct nss_if_msg nim_attach;
- struct nss_qdisc *nq_new = qdisc_priv(new);
-
- nss_qdisc_info("Grafting class %p\n", sch);
-
- if (cl == &q->root) {
- nss_qdisc_error("%p: Can't graft root class\n", cl);
- return -EINVAL;
- }
-
- if (new == NULL)
- new = &noop_qdisc;
-
- sch_tree_lock(sch);
- *old = cl->qdisc;
- sch_tree_unlock(sch);
-
- /*
- * Since we initially attached a noop qdisc as child (in Linux),
- * we do not perform a detach in the NSS if its a noop qdisc.
- */
- nss_qdisc_info("%s:Grafting old: %p with new: %p\n", __func__, *old, new);
- if (*old != &noop_qdisc) {
- struct nss_qdisc *nq_child = qdisc_priv(*old);
- nss_qdisc_info("%s: Detaching old: %p\n", __func__, *old);
- nim_detach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- if (nss_qdisc_node_detach(&cl->nq, nq_child, &nim_detach,
- NSS_SHAPER_CONFIG_TYPE_WRR_GROUP_DETACH) < 0) {
- return -EINVAL;
- }
- }
-
- /*
- * If the new qdisc is a noop qdisc, we do not send down an attach command
- * to the NSS.
- */
- if (new != &noop_qdisc) {
- nss_qdisc_info("%s: Attaching new: %p\n", __func__, new);
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = cl->nq.qos_tag;
- nim_attach.msg.shaper_configure.config.msg.shaper_node_config.snc.wrr_group_attach.child_qos_tag = nq_new->qos_tag;
- if (nss_qdisc_node_attach(&cl->nq, nq_new, &nim_attach,
- NSS_SHAPER_CONFIG_TYPE_WRR_GROUP_ATTACH) < 0) {
- return -EINVAL;
- }
- }
-
- /*
- * Attach qdisc once it is done in the NSS
- */
- sch_tree_lock(sch);
- cl->qdisc = new;
- sch_tree_unlock(sch);
-
- nss_qdisc_info("Nsswrr grafted");
-
- return 0;
-}
-
-static struct Qdisc *nss_wrr_leaf_class(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)arg;
- nss_qdisc_info("nss_wrr class leaf %p\n", cl);
-
- /*
- * Since all nss_wrr groups are leaf nodes, we can always
- * return the attached qdisc.
- */
- return cl->qdisc;
-}
-
-static void nss_wrr_qlen_notify(struct Qdisc *sch, unsigned long arg)
-{
- nss_qdisc_info("nss_wrr qlen notify %p\n", sch);
- /*
- * Gets called when qlen of child changes (Useful for deactivating)
- * Not useful for us here.
- */
-}
-
-static unsigned long nss_wrr_get_class(struct Qdisc *sch, u32 classid)
-{
- struct nss_wrr_class_data *cl = nss_wrr_find_class(classid, sch);
-
- nss_qdisc_info("Get nss_wrr class %p - class match = %p\n", sch, cl);
-
- if (cl != NULL)
- atomic_add(1, &cl->nq.refcnt);
-
- return (unsigned long)cl;
-}
-
-static void nss_wrr_put_class(struct Qdisc *sch, unsigned long arg)
-{
- struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)arg;
- nss_qdisc_info("nss_wrr put class for %p\n", cl);
-
- /*
- * We are safe to destroy the qdisc if the reference count
- * goes down to 0.
- */
- if (atomic_sub_return(1, &cl->nq.refcnt) == 0) {
- nss_wrr_destroy_class(sch, cl);
- }
-}
-
-static int nss_wrr_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb,
- struct tcmsg *tcm)
-{
- struct nss_wrr_class_data *cl = (struct nss_wrr_class_data *)arg;
- struct nlattr *opts;
- struct tc_nsswrr_class_qopt qopt;
-
- nss_qdisc_info("Dumping class %p of Qdisc %x\n", cl, sch->handle);
-
- qopt.quantum = cl->quantum;
-
- /*
- * All bf group nodes are root nodes. i.e. they dont
- * have any mode bf groups attached beneath them.
- */
- tcm->tcm_parent = TC_H_ROOT;
- tcm->tcm_handle = cl->cl_common.classid;
- tcm->tcm_info = cl->qdisc->handle;
-
- opts = nla_nest_start(skb, TCA_OPTIONS);
- if (opts == NULL)
- goto nla_put_failure;
- NLA_PUT(skb, TCA_NSSWRR_CLASS_PARMS, sizeof(qopt), &qopt);
- return nla_nest_end(skb, opts);
-
-nla_put_failure:
- nla_nest_cancel(skb, opts);
- return -EMSGSIZE;
-}
-
-static int nss_wrr_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
-{
- struct nss_qdisc *nq = (struct nss_qdisc *)arg;
-
- if (gnet_stats_copy_basic(d, &nq->bstats) < 0 ||
- gnet_stats_copy_queue(d, &nq->qstats) < 0) {
- return -1;
- }
-
- return 0;
-}
-
-static void nss_wrr_walk(struct Qdisc *sch, struct qdisc_walker *arg)
-{
- struct nss_wrr_sched_data *q = qdisc_priv(sch);
- struct hlist_node *n;
- struct nss_wrr_class_data *cl;
- unsigned int i;
-
- nss_qdisc_info("In nss_wrr walk %p\n", sch);
- if (arg->stop)
- return;
-
- for (i = 0; i < q->clhash.hashsize; i++) {
- hlist_for_each_entry(cl, n, &q->clhash.hash[i],
- cl_common.hnode) {
- if (arg->count < arg->skip) {
- arg->count++;
- continue;
- }
- if (arg->fn(sch, (unsigned long)cl, arg) < 0) {
- arg->stop = 1;
- return;
- }
- arg->count++;
- }
- }
-}
-
-static int nss_wrr_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
-{
- struct nss_wrr_sched_data *q = qdisc_priv(sch);
- int err;
- struct nss_if_msg nim;
-
- nss_qdisc_info("Init nss_wrr qdisc %p\n", sch);
-
- err = qdisc_class_hash_init(&q->clhash);
- if (err < 0)
- return err;
-
- q->root.cl_common.classid = sch->handle;
- q->root.qdisc = &noop_qdisc;
-
- qdisc_class_hash_insert(&q->clhash, &q->root.cl_common);
- qdisc_class_hash_grow(sch, &q->clhash);
-
- /*
- * Initialize the NSSWRR shaper in NSS
- */
- if (nss_qdisc_init(sch, &q->nq, NSS_SHAPER_NODE_TYPE_WRR, 0) < 0)
- return -EINVAL;
-
- /*
- * Configure the qdisc to operate in one of the two modes
- */
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- if (strncmp(sch->ops->id, "nsswrr", 6) == 0) {
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wrr_param.operation_mode = NSS_SHAPER_WRR_MODE_ROUND_ROBIN;
- } else if (strncmp(sch->ops->id, "nsswfq", 6) == 0) {
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wrr_param.operation_mode = NSS_SHAPER_WRR_MODE_FAIR_QUEUEING;
- } else {
- nss_qdisc_error("%s: Unknow qdisc association", __func__);
- nss_qdisc_destroy(&q->nq);
- return -EINVAL;
- }
-
- /*
- * Send configure command to the NSS
- */
- if (nss_qdisc_configure(&q->nq, &nim, NSS_SHAPER_CONFIG_TYPE_WRR_CHANGE_PARAM) < 0) {
- nss_qdisc_error("%s: Failed to configure nss_wrr qdisc %x\n", __func__, q->nq.qos_tag);
- nss_qdisc_destroy(&q->nq);
- return -EINVAL;
- }
-
- nss_qdisc_info("Nsswrr initialized - handle %x parent %x\n", sch->handle, sch->parent);
-
- /*
- * Start the stats polling timer
- */
- nss_qdisc_start_basic_stats_polling(&q->nq);
-
- return 0;
-}
-
-static int nss_wrr_change_qdisc(struct Qdisc *sch, struct nlattr *opt)
-{
- return 0;
-}
-
-static void nss_wrr_reset_class(struct nss_wrr_class_data *cl)
-{
- nss_qdisc_reset(cl->qdisc);
- nss_qdisc_info("Nsswrr class resetted %p\n", cl->qdisc);
-}
-
-static void nss_wrr_reset_qdisc(struct Qdisc *sch)
-{
- struct nss_wrr_sched_data *q = qdisc_priv(sch);
- struct nss_wrr_class_data *cl;
- struct hlist_node *n;
- unsigned int i;
-
- for (i = 0; i < q->clhash.hashsize; i++) {
- hlist_for_each_entry(cl, n, &q->clhash.hash[i], cl_common.hnode)
- nss_wrr_reset_class(cl);
- }
-
- nss_qdisc_reset(sch);
- nss_qdisc_info("Nsswrr qdisc resetted %p\n", sch);
-}
-
-static void nss_wrr_destroy_qdisc(struct Qdisc *sch)
-{
- struct nss_wrr_sched_data *q = qdisc_priv(sch);
- struct hlist_node *n, *next;
- struct nss_wrr_class_data *cl;
- struct nss_if_msg nim;
- unsigned int i;
-
- /*
- * Destroy all the classes before the root qdisc is destroyed.
- */
- for (i = 0; i < q->clhash.hashsize; i++) {
- hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i], cl_common.hnode) {
-
- /*
- * If this is the root class, we dont have to destroy it. This will be taken
- * care of by the nss_wrr_destroy() function.
- */
- if (cl == &q->root) {
- nss_qdisc_info("%s: We do not detach or destroy nss_wrr class %p here since this is "
- "the qdisc %p\n", __func__, cl, sch);
- continue;
- }
-
- /*
- * Reduce refcnt by 1 before destroying. This is to
- * ensure that polling of stat stops properly.
- */
- atomic_sub(1, &cl->nq.refcnt);
-
- /*
- * Detach class before destroying it. We dont check for noop qdisc here
- * since we do not attach anu such at init.
- */
- nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
- nim.msg.shaper_configure.config.msg.shaper_node_config.snc.wrr_detach.child_qos_tag = cl->nq.qos_tag;
- if (nss_qdisc_node_detach(&q->nq, &cl->nq, &nim, NSS_SHAPER_CONFIG_TYPE_WRR_DETACH) < 0) {
- nss_qdisc_error("%s: Node detach failed for qdisc %x class %x\n",
- __func__, cl->nq.qos_tag, q->nq.qos_tag);
- return;
- }
-
- /*
- * Now we can destroy the class.
- */
- nss_wrr_destroy_class(sch, cl);
- }
- }
- qdisc_class_hash_destroy(&q->clhash);
-
- /*
- * Stop the polling of basic stats
- */
- nss_qdisc_stop_basic_stats_polling(&q->nq);
-
- /*
- * Now we can go ahead and destroy the qdisc.
- * Note: We dont have to detach ourself from our parent because this
- * will be taken care of by the graft call.
- */
- nss_qdisc_destroy(&q->nq);
- nss_qdisc_info("Nsswrr destroyed %p\n", sch);
-}
-
-static int nss_wrr_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
-{
- nss_qdisc_info("Nsswrr dumping qdisc\n");
- return skb->len;
-}
-
-static int nss_wrr_enqueue(struct sk_buff *skb, struct Qdisc *sch)
-{
- return nss_qdisc_enqueue(skb, sch);
-}
-
-static struct sk_buff *nss_wrr_dequeue(struct Qdisc *sch)
-{
- return nss_qdisc_dequeue(sch);
-}
-
-static unsigned int nss_wrr_drop(struct Qdisc *sch)
-{
- printk("In nss_wrr drop\n");
- return nss_qdisc_drop(sch);
-}
-
-const struct Qdisc_class_ops nss_wrr_class_ops = {
- .change = nss_wrr_change_class,
- .delete = nss_wrr_delete_class,
- .graft = nss_wrr_graft_class,
- .leaf = nss_wrr_leaf_class,
- .qlen_notify = nss_wrr_qlen_notify,
- .get = nss_wrr_get_class,
- .put = nss_wrr_put_class,
- .dump = nss_wrr_dump_class,
- .dump_stats = nss_wrr_dump_class_stats,
- .walk = nss_wrr_walk
-};
-
-struct Qdisc_ops nss_wrr_qdisc_ops __read_mostly = {
- .id = "nsswrr",
- .init = nss_wrr_init_qdisc,
- .change = nss_wrr_change_qdisc,
- .reset = nss_wrr_reset_qdisc,
- .destroy = nss_wrr_destroy_qdisc,
- .dump = nss_wrr_dump_qdisc,
- .enqueue = nss_wrr_enqueue,
- .dequeue = nss_wrr_dequeue,
- .peek = qdisc_peek_dequeued,
- .drop = nss_wrr_drop,
- .cl_ops = &nss_wrr_class_ops,
- .priv_size = sizeof(struct nss_wrr_sched_data),
- .owner = THIS_MODULE
-};
-
-const struct Qdisc_class_ops nss_wfq_class_ops = {
- .change = nss_wrr_change_class,
- .delete = nss_wrr_delete_class,
- .graft = nss_wrr_graft_class,
- .leaf = nss_wrr_leaf_class,
- .qlen_notify = nss_wrr_qlen_notify,
- .get = nss_wrr_get_class,
- .put = nss_wrr_put_class,
- .dump = nss_wrr_dump_class,
- .dump_stats = nss_wrr_dump_class_stats,
- .walk = nss_wrr_walk
-};
-
-struct Qdisc_ops nss_wfq_qdisc_ops __read_mostly = {
- .id = "nsswfq",
- .init = nss_wrr_init_qdisc,
- .change = nss_wrr_change_qdisc,
- .reset = nss_wrr_reset_qdisc,
- .destroy = nss_wrr_destroy_qdisc,
- .dump = nss_wrr_dump_qdisc,
- .enqueue = nss_wrr_enqueue,
- .dequeue = nss_wrr_dequeue,
- .peek = qdisc_peek_dequeued,
- .drop = nss_wrr_drop,
- .cl_ops = &nss_wrr_class_ops,
- .priv_size = sizeof(struct nss_wrr_sched_data),
- .owner = THIS_MODULE
-};
-
diff --git a/nss_qdisc/nss_wrr.h b/nss_qdisc/nss_wrr.h
deleted file mode 100644
index 7ef5d93..0000000
--- a/nss_qdisc/nss_wrr.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-extern struct Qdisc_ops nss_wrr_qdisc_ops;
diff --git a/nss_stats.c b/nss_stats.c
index 02c20ab..2864c9e 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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.
@@ -114,7 +114,15 @@
"pbuf_default_alloc_fails",
"pbuf_default_free_count",
"pbuf_default_total_count",
- "payload_fails"
+ "payload_fails",
+ "h2n_control_packets",
+ "h2n_control_bytes",
+ "n2h_control_packets",
+ "n2h_control_bytes",
+ "h2n_data_packets",
+ "h2n_data_bytes",
+ "n2h_data_packets",
+ "n2h_data_bytes",
};
/*
@@ -145,7 +153,15 @@
"rx_buffers_cmd_resp",
"rx_buffers_status_sync",
"rx_buffers_crypto",
- "rx_buffers_virtual"
+ "rx_buffers_virtual",
+ "tx_skb_simple",
+ "tx_skb_nr_frags",
+ "tx_skb_fraglist",
+ "rx_skb_simple",
+ "rx_skb_nr_frags",
+ "rx_skb_fraglist",
+ "rx_bad_desciptor",
+ "nss_skb_count"
};
/*
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index 391d503..0dcf4c8 100644
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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.
@@ -73,6 +73,9 @@
extern void nss_tunipip6_register_handler(void);
extern void nss_pppoe_register_handler(void);
extern void nss_freq_register_handler(void);
+#if (NSS_PM_SUPPORT == 1)
+extern void nss_core_freq_register_handler(void);
+#endif
extern void nss_eth_rx_register_handler(void);
extern void nss_lag_register_handler(void);
extern void nss_dynamic_interface_register_handler(void);
@@ -90,10 +93,4 @@
extern void nss_if_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm,
__attribute__((unused))void *app_data);
-/*
- * nss_n2h_tx()
- * API to enable/disable Host RPS support in NSS
- */
-extern nss_tx_status_t nss_n2h_tx(struct nss_ctx_instance *nss_ctx, uint32_t enable_rps);
-
#endif /* __NSS_TX_RX_COMMON_H */
diff --git a/profiler/Makefile b/profiler/Makefile
deleted file mode 100755
index 6ede572..0000000
--- a/profiler/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-##########################################################################
-# Copyright (c) 2014, 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.
-##########################################################################
-
-ccflags-y := -I$(obj) -I$(obj)/.. -I$(obj)/../exports -DNSS_DEBUG_LEVEL=0 #-DPROFILE_DEBUG
-
-obj-m += qca-nss-profile-drv.o
-qca-nss-profile-drv-objs := profile.o
diff --git a/profiler/profile.c b/profiler/profile.c
deleted file mode 100644
index bdc4ada..0000000
--- a/profiler/profile.c
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-/*
- * qsdk/qca/src/qca-nss-drv/profiler/profile.c
- *
- * Implementation for NetAP Profiler
- */
-
-#include <linux/platform_device.h>
-#include <linux/export.h>
-#include <linux/module.h>
-#include <linux/seq_file.h>
-#include <linux/proc_fs.h>
-#include <linux/mm.h>
-#include <linux/mmzone.h>
-#include <linux/fs.h>
-#include <linux/page-flags.h>
-#include <linux/sched.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/thread_info.h>
-
-#define NSS_PKT_STATS_ENABLED 0 /* nss_core.h has no default DEF for NSS_PKT_STATS_ENABLED */
-#include "nss_core.h" /* needs only the number of NSS CORES */
-
-#include "profilenode.h"
-#include "profpkt.h"
-
-/*
- * This is the driver for the NetAP Core profiler. The system interface to the driver is
- * profile_register_performance_counter(), defined in <asm/profile.>
- * a set of proc files (proc/profile/<*>), used by the profiler daemon
- *
- * communication between the profiler components is described in a set of header files.
- * There are multiple versions of these files that must be kept synchronized:
- * in nss/source/pkg/profile
- * in tools/profiler
- * in qsdk/qca/src/qca-nss-drv/profiler
- *
- * profilesample.h specifies the sample format used by pkg/profile, profile driver, and ip3kprof (two versions)
- * profilenode.h specifies the driver node communication between NetAP and the profile driver. (two versions)
- * profpkt.h specifies the network packet format between the profile driver, profile daemon, and ip3kprof (two versions)
- *
- *
- * NSS profile sampler:
- * pkg/profile/src/profile.c
- * pkg/profile/include/profilenode.h
- * pkg/profile/include/profilesample.h
- *
- * profile driver: this code
- * qsdk/qca/src/qca-nss-drv/profiler
- *
- * profilerd: the user daemon that sends data to the tool
- * qsdk/qca/feeds/qca/utils/profilerd
- *
- * ubicom32-prof: the Windows tool
- * tools/profiler/src/(many files)
- *
- */
-
-#ifdef PROFILE_DEBUG
-#define profileDebug(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define profileInfo(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#define profileWarn(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-#define profileDebug(s, ...)
-#define profileInfo(s, ...)
-#define profileWarn(s, ...)
-#endif
-
-static void profiler_handle_reply(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm);
-
-/*
- * LINUX and Ultra counters must all fit in one packet
- */
-#define PROFILE_LINUX_MAX_COUNTERS 40
-static int profile_num_counters = 0;
-static volatile unsigned int *profile_counter[PROFILE_LINUX_MAX_COUNTERS];
-static char profile_name[PROFILE_LINUX_MAX_COUNTERS][PROFILE_COUNTER_NAME_LENGTH];
-
-/*
- * internal function to check if @name has been registered before
- * return the found index, or -1 otherwise
- */
-static int __profile_find_entry(char *name)
-{
- int i;
-
- for (i = 0; i < profile_num_counters; i++) {
- if (!strncasecmp(name, profile_name[i], PROFILE_COUNTER_NAME_LENGTH)) {
- return i;
- }
- }
- return -1;
-}
-
-/*
- * profile_register_performance_counter - register @counter into profile tracking list by key @name
- * @counter: pointer of the counter variable
- * @name: identifier of this counter
- *
- * Returns zero if total entries exceeding PROFILE_LINUX_MAX_COUNTERS
- * non-zero otherwise.
- *
- * Each @name gives unique entry for @counter, by allocating a new array slot or just use existing one.
- * No need of de-registration API, since a loadable module's new insmod, will replace the
- * @counter's * new address at the same profile_counter[] slot.
- */
-int profile_register_performance_counter(volatile unsigned int *counter, char *name)
-{
- int i;
-
- if (profile_num_counters >= PROFILE_LINUX_MAX_COUNTERS) {
- return 0;
- }
-
- i = __profile_find_entry(name);
- if (i < 0) {
- i = profile_num_counters++;
- }
-
- profile_counter[i] = counter;
- strncpy(profile_name[i], name, PROFILE_COUNTER_NAME_LENGTH);
- profile_name[i][PROFILE_COUNTER_NAME_LENGTH - 1] = 0;
-
- return 1;
-}
-
-/*
- * make a packet full of sample data
- */
-static int profile_make_data_packet(char *buf, int blen, struct profile_io *pn)
-{
- int sp_samples = 0; /* separated samples if any */
- int ns; /* number of samples requested */
- struct profile_header ph;
- struct profile_sample_ctrl_header *psc_hd = &pn->pnc.pn2h->psc_header;
-
- if (blen < sizeof(ph) + sizeof(struct profile_sample)) {
- return -EINVAL;
- }
-
- profileDebug("%p stat %x cnt %d %p\n", pn->pnc.pn2h, pn->pnc.pn2h->mh.md_type, psc_hd->count, pn->ccl);
-
- if (pn->pnc.pn2h->mh.md_type == PINGPONG_EMPTY || psc_hd->count < 1) {
- struct profile_n2h_sample_buf *nsb;
- ns = (pn->ccl_read + 1) & (CCL_SIZE-1);
- nsb = pn->ccl + ns;
- if (ns == pn->ccl_write || nsb->mh.md_type != PINGPONG_FULL) {
- profileInfo("%s: waiting more data %x %p : ns %d rd %d wr %d\n", __func__, nsb->mh.md_type, nsb, ns, pn->ccl_read, pn->ccl_write);
- return -EAGAIN;
- }
- pn->ccl_read = ns;
- profileInfo("sp %p => %p rd %d %p\n", pn->pnc.samples, nsb->samples, ns, nsb);
- psc_hd = &nsb->psc_header;
- pn->pnc.pn2h = nsb;
- pn->pnc.samples = nsb->samples;
- pn->pnc.cur = 0;
- }
- pn->pnc.pn2h->mh.md_type = PINGPONG_INUSE;
-
- /*
- * fill in the packet header
- */
- memset(&ph, 0, sizeof(ph));
- ph.pph.magic = htons(PROF_MAGIC + PROFILE_VERSION);
- ph.pph.header_size = sizeof(ph);
- ph.pph.profile_instructions = 0;
- ph.pph.clock_freq = pn->pnc.un.cpu_freq;
- ph.pph.ddr_freq = pn->pnc.un.ddr_freq;
- ph.pph.cpu_id = pn->pnc.un.cpu_id;
- ph.pph.seq_num = htonl(pn->profile_sequence_num);
- ph.pph.sample_stack_words = htonl(PROFILE_STACK_WORDS);
-
- ns = (blen - sizeof(ph)) / sizeof(struct profile_sample);
- profileInfo("%X: blen %d ns = %d psc_hd count %d ssets %d phs %d pss %d\n", pn->profile_sequence_num, blen, ns, psc_hd->count, psc_hd->exh.sample_sets, sizeof(ph), sizeof(struct profile_sample));
- if (ns > psc_hd->count)
- ns = psc_hd->count;
- if (ns == 0) {
- printk("NS should not be 0: rlen %d hd cnt %d\n", blen, psc_hd->count);
- return 0;
- }
-
- /*
- * if buf cannot hold all samples, then samples must be separated by set.
- */
- if (ns < psc_hd->count) {
- ph.exh.sets_map = psc_hd->exh.sets_map; /* save for separating sets */
- do {
- sp_samples += psc_hd->exh.sets_map & 0x0F;
- psc_hd->exh.sets_map >>= 4; /* remove the last set */
- psc_hd->exh.sample_sets--;
- ph.exh.sample_sets++; /* save for restore later */
- } while ((psc_hd->count - sp_samples) > ns);
- ns = psc_hd->count - sp_samples;
- }
- ph.pph.sample_count = ns;
- if (copy_to_user(buf, &ph.pph, sizeof(ph.pph)) != 0) {
- return -EFAULT;
- }
- buf += sizeof(ph.pph);
-
- /*
- * ph.exh is unused dummy; and psc_hd->exh is used directly to avoid double mem copy
- */
- if (copy_to_user(buf, &psc_hd->exh, sizeof(psc_hd->exh)) != 0) {
- return -EFAULT;
- }
- buf += sizeof(psc_hd->exh);
-
- blen = ns * sizeof(struct profile_sample);
- profileDebug("-profile_make_data_packet %p slen %d cur %d dcped %d + %d\n", pn->pnc.samples, blen, pn->pnc.cur, sizeof(ph.pph), sizeof(psc_hd->exh));
- if (copy_to_user(buf, &pn->pnc.samples[pn->pnc.cur], blen) != 0) {
- return -EFAULT;
- }
- pn->pnc.cur += ns;
- psc_hd->count -= ns;
- if (psc_hd->count < 1)
- pn->pnc.pn2h->mh.md_type = PINGPONG_EMPTY;
-
- /*
- * restore left over sample counts; 0s for no one
- */
- if (sp_samples) {
- profileDebug("%d sps %d %d: sets %d : %d map %x <> %x\n", psc_hd->count, ns, sp_samples, psc_hd->exh.sample_sets, ph.exh.sample_sets, psc_hd->exh.sets_map, ph.exh.sets_map);
- psc_hd->exh.sample_sets = ph.exh.sample_sets;
- psc_hd->exh.sets_map = ph.exh.sets_map;
- }
-
- pn->profile_sequence_num++;
- blen += sizeof(ph);
- profileDebug("+profile_make_data_packet %d phd len %d nsp %p rd %d cnt %d\n", blen, sizeof(ph), pn->pnc.pn2h, pn->ccl_read, psc_hd->count);
- return blen;
-}
-
-/*
- * This is no longer needed due to NetAP and Linux use different CPUs, and profile is NetAP only.
- * All related code will be removed after corresponging code in visual tool is corrected; otherwise
- * visual tool will mis-behave
- */
-struct profile_counter profile_builtin_stats[] =
-{
- {
- "Free memory(KB)", 0
- },
- {
- "Max free Block(KB)", 0
- }
-};
-
-/*
- * make a packet full of performance counters
- */
-static int profile_make_stats_packet(char *buf, int bytes, struct profile_io *pn)
-{
- static char prof_pkt[PROFILE_MAX_PACKET_SIZE];
-
- char *ptr;
- int n;
- struct profile_counter *counter_ptr;
- struct profile_header_counters *hdr = (struct profile_header_counters *)prof_pkt;
- struct profile_sample_ctrl_header *psc_hd = &pn->pnc.pn2h->psc_header;
-
- if (bytes > PROFILE_MAX_PACKET_SIZE) {
- bytes = PROFILE_MAX_PACKET_SIZE;
- }
- n = sizeof(profile_builtin_stats) + (pn->pnc.un.num_counters + profile_num_counters) * sizeof(*counter_ptr);
-
- if ((bytes - sizeof(hdr)) < n) {
- profileWarn("room too small %d for cnts %d\n", bytes, n);
- return 0;
- }
-
- hdr->magic = htons(PROF_MAGIC_COUNTERS);
- hdr->ultra_count = htons(pn->pnc.un.num_counters);
- hdr->linux_count = htonl(profile_num_counters + sizeof(profile_builtin_stats) / sizeof(*counter_ptr));
- hdr->ultra_sample_time = psc_hd->exh.clocks;
- hdr->linux_sample_time = psc_hd->exh.clocks; /* QSDK has no time func */
-
- n = pn->pnc.un.num_counters; /* copy NSS counters */
- n *= sizeof(pn->pnc.un.counters[0]);
- ptr = (char*) (hdr + 1);
- memcpy(ptr, (void *)(pn->pnc.un.counters), n);
- ptr += n;
-
- counter_ptr = (struct profile_counter *)ptr;
- for (n = 0; n < profile_num_counters; ++n) {
- counter_ptr->value = htonl(*profile_counter[n]);
- strcpy(counter_ptr->name, profile_name[n]);
- counter_ptr++;
- }
- ptr = (char*)counter_ptr;
-
- /*
- * built in statistics
- profile_get_memory_stats(&total_free, &max_free);
- */
- profile_builtin_stats[0].value = 0;
- profile_builtin_stats[1].value = 0;
- memcpy(ptr, (void *)profile_builtin_stats, sizeof(profile_builtin_stats));
- ptr += sizeof(profile_builtin_stats);
-
- n = ptr - prof_pkt;
- if (copy_to_user(buf, prof_pkt, n) != 0) {
- return -EFAULT;
- }
- return n;
-}
-
-/*
- * space for all memory blocks so we can hold locks for short time when walking tables
- */
-static struct profile_io *node[NSS_MAX_CORES];
-
-static int profile_open(struct inode *inode, struct file *filp)
-{
- int n;
- struct profile_io *pn;
-
- if (filp->private_data)
- printk(KERN_WARNING "%s: %p\n", filp->f_dentry->d_iname, filp->private_data);
-
- n = filp->f_dentry->d_iname[strlen(filp->f_dentry->d_iname) - 1] - '0';
- if (n < 0 || n >= NSS_MAX_CORES)
- n = 0;
- pn = node[n];
- if (!pn) {
- return -ENOENT;
- }
-
- if (!pn->pnc.enabled && nss_get_state(pn->ctx) == NSS_STATE_INITIALIZED) {
- nss_tx_status_t ret;
- pn->pnc.enabled = 1;
- pn->profile_first_packet = 1;
- pn->pnc.un.hd_magic = UBI32_PROFILE_HD_MAGIC | NSS_PROFILER_START_MSG;
- ret = nss_profiler_if_tx_buf(pn->ctx, &pn->pnc.un, sizeof(pn->pnc.un), profiler_handle_reply);
- profileInfo("%s: %d -- %p: ccl %p sp %p\n", __func__, ret, pn, pn->ccl, pn->pnc.samples);
- filp->private_data = pn;
- return 0;
- }
-
- profileWarn("profile ena %d nss stat %x\n", pn->pnc.enabled, nss_get_state(pn->ctx));
- return -EBUSY;
-}
-
-/*
- * return a udp packet ready to send to the profiler tool
- * when there are no packets left to make, return 0
- */
-static int profile_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
-{
- int result = 0;
- int slen = 0;
- struct profile_io *pn = (struct profile_io *)filp->private_data;
- if (!pn) {
- return -ENOENT;
- }
-
- if (!pn->pnc.enabled) {
- return -EPERM;
- }
- if (!pn->pnc.samples) {
- return -ENOMEM;
- }
-
- if (pn->profile_first_packet) {
- result = profile_make_stats_packet(buf, count, pn);
- pn->profile_first_packet = 0;
- profileInfo("%d profile_make_stats_packet %d\n", result, count);
-
-#ifdef PROFILE_SEP_STAT
- /*
- * currectly, stat and sample data are combined in one pkt for efficient;
- * but this is harder to debug and required remote tool to handle
- * packet in all-in-one method instead of individual handler.
- */
- return result;
-#endif
- }
-
- if (result > 0) {
- buf += result;
- count -= result;
- slen = result;
- }
- result = profile_make_data_packet(buf, count, pn);
- if (result == 0) {
- pn->profile_first_packet = 1;
- }
- profileInfo("%d: profile_make_data_packet %d %d\n", result, count, slen);
-
- profileInfo("%d: read\n", pn->pnc.enabled);
- if (pn->pnc.enabled < 0) {
- nss_tx_status_t ret;
- pn->pnc.enabled = 1;
- pn->pnc.un.hd_magic = UBI32_PROFILE_HD_MAGIC | NSS_PROFILER_START_MSG;
- ret = nss_profiler_if_tx_buf(pn->ctx, &pn->pnc.un, sizeof(pn->pnc.un), profiler_handle_reply);
- profileWarn("%s: restart %d -- %p: ccl %p sp %p\n", __func__, ret, pn, pn->ccl, pn->pnc.samples);
- }
-
- return result + slen;
-}
-
-/*
- * the close function paired with profiler_open
- */
-static int profile_release(struct inode *inode, struct file *filp)
-{
- struct profile_io *pn = (struct profile_io *)filp->private_data;
- if (!pn) {
- return -ENOENT;
- }
-
- if (pn->pnc.enabled) {
- nss_tx_status_t ret;
- pn->pnc.enabled = 0;
- pn->pnc.un.hd_magic = UBI32_PROFILE_HD_MAGIC | NSS_PROFILER_STOP_MSG;
- ret = nss_profiler_if_tx_buf(pn->ctx, &pn->pnc.un, sizeof(pn->pnc.un), profiler_handle_reply);
- profileInfo("%s: %p %d\n", __func__, pn, ret);
- return 0;
- }
- profileWarn("%s: attempt closing non-open dev %p\n", __func__, pn);
- pn->profile_first_packet = 1;
- return -EBADF;
-}
-
-#define isspace(c) (c==' ' || c=='\t')
-
-static int parseDbgData(const char *buf, size_t count, struct debug_box *db)
-{
- char *cp;
- int n;
-
- printk("%p: buf (%s) cnt %d\n", buf, buf, count);
- if (sscanf(buf, "%x", (uint32_t *)&db->base_addr) != 1) {
- printk("%s: cannot get base addr\n", __func__);
- return -EINVAL;
- }
-
- cp = strchr(buf, ' ');
- if (!cp) {
-noea: printk("%s: no enough arguments\n", __func__);
- return -EFAULT;
- }
-
- while (isspace(*cp)) cp++;
- if (!strncmp(cp, "mio", 3) || !strncmp(cp, "moveio", 6)) {
- printk("%p: cp (%s)\n", cp, cp);
- cp = strchr(cp, ' ');
- if (!cp) {
- goto noea;
- }
- db->opts |= DEBUG_OPT_MOVEIO;
- }
-
- while (isspace(*cp)) cp++;
- printk("base addr %p -- %s\n", db->base_addr, cp);
-
- if (!strncmp(cp, "read", 4)) {
- cp = strchr(cp, ' ');
- if (cp) {
- while (isspace(*cp)) cp++;
- sscanf(cp, "%x", &db->dlen);
- }
- return 0;
- }
-
- n = 0;
- do {
- while (isspace(*cp)) cp++;
- if (sscanf(cp, "%x", db->data+n) != 1) {
- printk("n %d : %s\n", n, cp);
- break;
- }
- printk("write %x to off %x\n", db->data[n], n * sizeof(db->data[0]));
- n++;
- cp = strchr(cp, ' ');
- } while (cp && n < MAX_DB_WR);
- return n;
-}
-
-/*
- * display memory content read from Phy addr
- */
-static void debug_if_show(struct debug_box *db, int buf_len)
-{
- int i;
-
- for (i=0; i < db->dlen; i++) {
- if ((i & 3) == 0)
- printk("\n%p: ", db->base_addr + i);
- printk("%9x", db->data[i]);
- }
- printk("\ndumped %d (extra 1) blen %d\n", db->dlen, buf_len);
-}
-
-/*
- * show debug message we requested from NSS
- */
-static void profiler_handle_debug_reply(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm)
-{
- debug_if_show((struct debug_box*)&ncm[1], ncm->len);
-}
-
-/*
- * a generic Krait <--> NSS debug interface
- */
-static int debug_if(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
-{
- int result;
- struct debug_box *db;
- struct profile_io *pio = node[0];
-
- if (!pio) {
- return -ENOENT;
- }
-
- if (!pio->pnc.enabled) {
- return -EPERM;
- }
-
- db = (struct debug_box *) &pio->pnc;
- db->dlen = db->opts = 0;
- result = parseDbgData(buf, count, db);
- if (result < 0) {
- return result;
- }
-
- if (!result) {
- db->hd_magic = UBI32_PROFILE_HD_MAGIC | NSS_PROFILER_DEBUG_RD_MSG;
- } else {
- db->hd_magic = UBI32_PROFILE_HD_MAGIC | NSS_PROFILER_DEBUG_WR_MSG;
- db->dlen = result;
- }
- result = nss_profiler_if_tx_buf(pio->ctx, &pio->pnc.un, sizeof(pio->pnc.un), profiler_handle_debug_reply);
- printk("dbg res %d dlen = %d opt %x\n", result, db->dlen, db->opts);
- return count;
-}
-
-static const struct file_operations profile_fops = {
- .open = profile_open,
- .read = profile_read,
- .release = profile_release,
- .write = debug_if,
-};
-
-/*
- * showing sample status on Linux console
- */
-static int profile_rate_show(struct seq_file *m, void *v)
-{
- struct profile_io *pn = node[0];
- if (pn) {
- struct profile_sample_ctrl_header *psc_hd = &pn->pnc.pn2h->psc_header;
- seq_printf(m, "%d samples per second. %d ultra, %d linux virtual counters. %d dropped samples. %d queued of %d max sampels. %d sent packets.\n",
- pn->pnc.un.rate, pn->pnc.un.num_counters, profile_num_counters, psc_hd->dropped_samples, psc_hd->count, psc_hd->max_samples, pn->profile_sequence_num);
- } else {
- seq_printf(m, "Profiler is not initialized.\n");
- }
- return 0;
-}
-
-static int profile_rate_open(struct inode *inode, struct file *filp)
-{
- return single_open(filp, profile_rate_show, NULL);
-}
-
-static int profile_rate_write(struct file *filp, const char *buf, size_t len, loff_t *off)
-{
- *off = 0;
- return 0;
-}
-
-static const struct file_operations profile_rate_fops = {
- .open = profile_rate_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .write = profile_rate_write,
-};
-
-/*
- * hex dump for debug
- */
-static void kxdump(void *buf, int len, const char *who)
-{
- int *ip = (int*) buf;
- int lns = len >> 5; /* 32-B each line */
- if (lns > 4)
- lns = 4;
- printk("%p: kxdump %s: len %d\n", buf, who, len);
- do {
- printk("%x %x %x %x %x %x %x %x\n", ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]);
- ip += 8;
- } while (lns--);
-}
-
-/*
- * check magic # and detect Endian.
- * negtive return means failure.
- * return 1 means need to ntoh swap.
- */
-static int profiler_magic_verify(struct profile_sample_ctrl_header *psc_hd, int buf_len)
-{
- int swap = 0;
- if ((psc_hd->hd_magic & UBI32_PROFILE_HD_MMASK) != UBI32_PROFILE_HD_MAGIC) {
- if ((psc_hd->hd_magic & UBI32_PROFILE_HD_MMASK_REV) != UBI32_PROFILE_HD_MAGIC_REV) {
- kxdump(psc_hd, buf_len, "bad profile packet");
- printk("bad profile packet %x : %d\n", psc_hd->hd_magic, buf_len);
- return -1;
- }
- profileDebug("Profile data in different Endian type %x\n", psc_hd->hd_magic);
- swap = 1;
- psc_hd->hd_magic = ntohl(psc_hd->hd_magic);
- }
- return swap;
-}
-
-/*
- * process profile sample data from NSS
- */
-static void profile_handle_nss_data(void *arg, struct nss_profiler_msg *npm)
-{
- int buf_len = npm->cm.len;
- void *buf = &npm->payload;
- struct profile_io *pn;
- struct profile_n2h_sample_buf *nsb;
- struct profile_sample_ctrl_header *psc_hd = (struct profile_sample_ctrl_header *)buf;
- int ret, wr;
- int swap = 0; /* only for header and info data, not samples */
-
- if (buf_len < (sizeof(struct profile_session) - sizeof(struct profile_counter) * (PROFILE_MAX_APP_COUNTERS))) {
- printk("profile data packet is too small to be useful %d\n", buf_len);
- return;
- }
-
- swap = profiler_magic_verify(psc_hd, buf_len);
- if (swap < 0) {
- return;
- }
-
- pn = (struct profile_io *)arg;
- profileInfo("%s: dlen %d swap %d cmd %x - %d\n", __func__, buf_len, swap, npm->cm.type, (pn->ccl_read - pn->ccl_write) & (CCL_SIZE-1));
- //kxdump(buf, buf_len, "process profile packet");
-
- if (npm->cm.type == NSS_PROFILER_FIXED_INFO_MSG) {
- struct profile_session *pTx = (struct profile_session *)buf;
- if (swap) {
- pn->pnc.un.rate = ntohl(pTx->rate);
- pn->pnc.un.cpu_id = ntohl(pTx->cpu_id);
- pn->pnc.un.cpu_freq = ntohl(pTx->cpu_freq);
- pn->pnc.un.ddr_freq = ntohl(pTx->ddr_freq);
- pn->pnc.un.num_counters = ntohl(pTx->num_counters);
- } else {
- pn->pnc.un = *pTx;
- }
- memcpy(pn->pnc.un.counters, pTx->counters, pn->pnc.un.num_counters * sizeof(pn->pnc.un.counters[0]));
- pn->profile_first_packet = 1;
- return;
- }
-
- wr = (pn->ccl_write + 1) & (CCL_SIZE-1);
- nsb = pn->ccl + wr;
- swap = (pn->ccl_read - wr) & (CCL_SIZE-1); /* PROFILER_FLOWCTRL */
- if (nsb->mh.md_type != PINGPONG_EMPTY || (swap && swap < 5)) {
- if (pn->pnc.enabled > 0) {
- pn->pnc.enabled = -1;
- pn->pnc.un.hd_magic = UBI32_PROFILE_HD_MAGIC | NSS_PROFILER_STOP_MSG;
- ret = nss_profiler_if_tx_buf(pn->ctx, &pn->pnc.un, sizeof(pn->pnc.un), profiler_handle_reply);
- profileWarn("%d temp stop sampling engine %d\n", swap, ret);
- }
- if (swap < 3) {
- profileWarn("w%p.%d: %d no room for new profile samples r%p.%d\n", nsb, wr, swap, pn->ccl+pn->ccl_read, pn->ccl_read);
- return; /* -EMSGSIZE */
- }
- }
- pn->ccl_write = wr;
-
- /*
- * sampling data -- hdr NBO swap is done at NSS side via SWAPB.
- */
- memcpy(&nsb->psc_header, buf, buf_len); /* pn->pnc.pn2h->psc_header = *psc_hd; maybe faster, but take more memory */
-
- nsb->mh.md_type = PINGPONG_FULL;
- //kxdump((void*)(nsb->samples + 23), sizeof(*nsb->samples) << 1, "1st 2 samples");
- if (!wr) {
- /*
- * should be UBI32_PROFILE_HD_MAGIC | NSS_PROFILER_COUNTERS_MSG
- * but FW is hard to change due to packge warehouse, so using
- * STOP/START instead till PROFILER_COUNTERS_MSG done in FW
- */
- pn->pnc.un.hd_magic = UBI32_PROFILE_HD_MAGIC | NSS_PROFILER_STOP_MSG;
- ret = nss_profiler_if_tx_buf(pn->ctx, &pn->pnc.un, sizeof(pn->pnc.un), profiler_handle_reply);
- if (ret == NSS_TX_FAILURE)
- printk("STOP Cmd failed %d %d\n", ret, wr);
- pn->pnc.un.hd_magic = UBI32_PROFILE_HD_MAGIC | NSS_PROFILER_START_MSG;
- ret = nss_profiler_if_tx_buf(pn->ctx, &pn->pnc.un, sizeof(pn->pnc.un), profiler_handle_reply);
- }
- profileInfo("filled %p %p wr %d\n", nsb, nsb->samples, pn->ccl_write);
-}
-
-/*
- * process N2H reply for message we sent to NSS -- currently no action
- */
-static void profiler_handle_reply(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm)
-{
- switch (ncm->response) {
- default:
- nss_warning("%p: profiler had error response %d\n", nss_ctx, ncm->response);
- /*
- * fail through -- no plan to do anything yet
- */
- case NSS_CMN_RESPONSE_ACK:
- return;
- }
-}
-
-/*
- * initialize basic profile data structure
- */
-static void profile_init(struct profile_io *node)
-{
- int n;
-
- memset(&node->pnc, 0, sizeof(node->pnc));
- node->ccl_read = 0;
- node->ccl_write = -1;
- node->pnc.pn2h = node->ccl;
- node->pnc.samples = node->ccl->samples;
-
- for (n = 0; n < CCL_SIZE; n++) {
- node->ccl[n].mh.md_type = PINGPONG_EMPTY;
- node->ccl[n].psc_header.count = 0;
- }
-
- /*
- * sw_ksp is an array of pointers to struct thread_info, the current task executing for each linux virtual processor
- node->sw_ksp_ptr = sw_ksp;
- */
- node->task_offset = offsetof(struct thread_info, task);
- node->pid_offset = offsetof(struct task_struct, tgid);
-}
-
-static struct proc_dir_entry *pdir;
-
-/*
- * init_module cannot call exit_MODULE, so use this wrapper
- */
-void netap_profile_release_resource(void)
-{
- if (pdir) {
- remove_proc_entry("rate", pdir);
- remove_proc_entry("data", pdir);
- remove_proc_entry("data1", pdir);
- }
- kfree(node[0]->ccl);
- kfree(node[0]);
- node[0] = NULL;
-}
-
-/*
- * kernel module entry
- */
-int __init netap_profile_init_module(void)
-{
- /*
- * we need N nodes, not one node + N ctx, for N cores
- */
- node[0] = kmalloc(sizeof(*node[0]) * NSS_MAX_CORES, GFP_KERNEL);
- if (!node[0]) {
- printk(KERN_INFO "Profiler CTRL kmalloc failed.\n");
- return -ENOMEM;
- }
-
- node[0]->ccl = kmalloc(sizeof(*node[0]->ccl) * CCL_SIZE * NSS_MAX_CORES, GFP_KERNEL);
- if (!node[0]->ccl) {
- printk(KERN_INFO "Profiler n2h_sample_buf kmalloc failed.\n");
- kfree(node[0]);
- node[0] = NULL;
- return -ENOMEM;
- }
-
- /*
- * connect to the file system
- */
- pdir = proc_mkdir("profile", NULL);
- if (!pdir ||
- !proc_create("data", 0, pdir, &profile_fops) ||
- !proc_create("data1", 0, pdir, &profile_fops) ||
- !proc_create("rate", 0, pdir, &profile_rate_fops)) {
- netap_profile_release_resource();
- return -ENOMEM;
- }
-
- profile_init(node[0]);
-
- /*
- * attatch the device callback to N2H channel for CPU 0
- */
- node[0]->ctx = nss_profiler_notify_register(NSS_CORE_0, profile_handle_nss_data, node[0]);
-#if NSS_MAX_CORES > 1
- node[1] = node[0] + 1;
- node[1]->ccl = node[0]->ccl + CCL_SIZE;
-
- profile_init(node[1]);
- node[1]->ctx = nss_profiler_notify_register(NSS_CORE_1, profile_handle_nss_data, node[1]);
- profile_register_performance_counter(&node[1]->profile_sequence_num, "Profile1 DRV data packets");
-#endif
-
- profile_register_performance_counter(&node[0]->profile_sequence_num, "Profile0 DRV data packets");
- return 0;
-}
-
-/*
- * kernel module exit
- */
-void __exit netap_profile_exit_module(void)
-{
- nss_profiler_notify_unregister(NSS_CORE_0);
-#if NSS_MAX_CORES > 1
- nss_profiler_notify_unregister(NSS_CORE_1);
-#endif
- netap_profile_release_resource();
-}
-
-module_init(netap_profile_init_module);
-module_exit(netap_profile_exit_module);
-
-MODULE_LICENSE("Dual BSD/GPL");
diff --git a/profiler/profilenode.h b/profiler/profilenode.h
deleted file mode 100644
index 9ffb181..0000000
--- a/profiler/profilenode.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-/*
- * profilenode.h
- * device node for the profiler, to communicate with the linux driver
- *
- * WANRING:
- * This file must present in both nss/source/pkg/profile/include for NSS driver,
- * and linux-nbu/driver/.../nss for Linux driver
- */
-
-#include "profilesample.h"
-
-#define UBI32_PROFILE_HD_MAGIC 0x4F525000 // 0 + "PRO"
-#define UBI32_PROFILE_HD_MAGIC_REV 0x0050524F // different endian
-#define UBI32_PROFILE_HD_MMASK 0xFFFFFF00 // 1st byte is Rx/Tx cmd
-#define UBI32_PROFILE_HD_MMASK_REV 0x00FFFFFF
-
-enum profile_cmds {
- // cmds from HLOS to NSS
- PROFILER_CHANGE_SAMPLING_RATE, // change sampling clock timer
- PROFILER_START, // start/stop sampling engine
- PROFILER_STOP,
- PROFILER_FLOWCTRL, // info how many buffers available
- DEBUG_RD_REQ, // I/O commands h2n
- DEBUG_WR_REQ,
- DEBUG_REPLY, // n2h respond
-
- // data from NSS to HLOS
- PROFILER_FIXED_INFO = 8, // set bit 3 for data
- PROFILER_COUNTERS,
- PROFILER_SAMPLES,
-};
-
-struct profile_sample_ctrl_header {
- uint32_t hd_magic; // cmd + MAGIC for packet and endianess check
-
- /*
- * controlling data need to be sent to and used by upper layer (HLOS)
- */
- uint16_t count; // number of valid samples
- uint16_t max_samples; // how many samples can be in the samples array
- uint32_t dropped_samples; // how many samples did the profiler drop due to buffer overruns
-
- /*
- * info data -- sent to remote profiler tool (need swap)
- */
- struct profile_ext_header exh;
-
-};
-
-/*
- * # of sample buffers in pbuf payload
- */
-#ifndef PBUF_PAYLOAD_SIZE
-#define PBUF_PAYLOAD_SIZE 1792 // for HLOS driver: must sync with pbuf_public
-typedef enum meta_types {
- PINGPONG_EMPTY,
- PINGPONG_FULL,
- PINGPONG_INUSE,
-} flowctrl_t;
-#else
-typedef enum pnode_c2h_metadata_types flowctrl_t; // for NSS driver
-#endif
-
-#define MAX_SAMPLES_PER_PBUF ((PBUF_PAYLOAD_SIZE - sizeof(struct profile_sample_ctrl_header)) / sizeof(struct profile_sample))
-
-struct n2h_meta_header {
- flowctrl_t md_type; // N2H (NSS) and receiver (HLOS) flow control (meta type)
- uint32_t d_len; // total data length start from psc_header
-};
-
-struct profile_session { // use for per session start
- uint32_t hd_magic; // common ovarlay in all headers
- uint32_t num_counters; // how many registered performance (app) counters -- may change
- uint32_t ocm_size;
- uint32_t sram_start;
-
- uint32_t rate; // sampling rate
- uint32_t cpu_id; // chip_id register
- uint32_t cpu_freq; // chip clock
- uint32_t ddr_freq; // DDR MEM speed
- struct profile_counter counters[PROFILE_MAX_APP_COUNTERS];
-};
-
-struct profile_n2h_sample_buf {
- struct n2h_meta_header mh;
-
- struct profile_sample_ctrl_header psc_header; // per sample period
- struct profile_sample samples[MAX_SAMPLES_PER_PBUF]; // per thread samples - for NSS send
-};
-
-struct profile_common {
- struct profile_session un;
- /*
- * changable data sent everything pbuf
- */
- struct profile_n2h_sample_buf *pn2h; // sampling ctrl for this sample period
- struct profile_sample *samples; // samples array was allocated by the linux driver
- // now NSS points it to pbuf + pn2h header
- uint16_t cur; // pos where driver take (read) samples
- int16_t enabled; // Is the profiler enabled to take samples?
-};
-
-/*
- * each buffer holds 4-7 sets (sample intrs) of samples; by average 5 sets per buffer,
- * at 10ms smaple clock, 1s sleep in profilerd requires kernel to have 1000 / 10 / 5 = 20
- * buffer to store one 1s samples. For higher sampling rate, either kernel needs more buffers
- * or profilerd needs less sleep time, but both needs to make match.
- */
-#define CCL_SIZE 32
-
-struct profile_io {
- struct profile_common pnc;
-
- /*
- * control fields - HLOS
- */
- void *ctx; // nss_ctx for Linux driver
- int profile_first_packet;
- int profile_sequence_num;
-
- /*
- * circular buffers for psc_header/samples
- */
- struct profile_n2h_sample_buf *ccl;
- int ccl_read;
- int ccl_write;
-
- /*
- * data from HLOS -- used to generate sample->pid in ULTRA -- no longer needed in NSS
- */
- uint32_t *sw_ksp_ptr; // pointer to array (per hardware thread) of pointers to struct thread_info
- uint32_t task_offset; // offset in bytes in thread_info to task_struct pointer
- uint32_t pid_offset; // offset in bytes in task_struct to the PID
-};
-
-/*
- * Krait <--> NSS debug mechanism. It lays over on profile_n2h_sample_buf.samples (ccl->samples)
- */
-#define MAX_DB_WR 28 // profile_session has 31 4B words data (32W total with hd_magic) and
-#define MAX_DB_RD 30 // common has two more ptrs
-struct debug_box { // this overlays with profile_common (RD) or profile_session (WR)
- uint32_t hd_magic; // cmd + MAGIC for packet and endianess check
-
- uint32_t opts;
- uint32_t *base_addr;
- int32_t dlen; // in 4B words
- uint32_t data[MAX_DB_RD];
-};
-
-#define DEBUG_OPT_BCTRL 1 // basic CTRL
-#define DEBUG_OPT_MOVEIO (1<<1) // force to use moveio in case new OCP range is added
diff --git a/profiler/profilesample.h b/profiler/profilesample.h
deleted file mode 100644
index 72c4afa..0000000
--- a/profiler/profilesample.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-/*
- * profilesample.h
- * Sample format for profiling
- */
-
-#ifndef _PROFILE_SAMPLE_H_
-#define _PROFILE_SAMPLE_H_
-
-#define PROFILE_STACK_WORDS 4
-
-/*
- * Each sample is for an enabled thread, not including the profiling thread.
- * HRT thread sampling is optional.
- * Sampled threads may be active or inactive. Samples are included in thread number
- * order, so each sample interval has a set of samples starting with one from thread 0
- *
- * Samples include bits indicating if this thread is blocked
- */
-#define PROFILE_I_BLOCKED_BIT 5
-#define PROFILE_I_BLOCKED (1 << PROFILE_I_BLOCKED_BIT)
-#define PROFILE_D_BLOCKED_BIT 4
-#define PROFILE_D_BLOCKED (1 << PROFILE_D_BLOCKED_BIT)
-#define PROFILE_BTB_SHIFT 6
-
-#if !defined __unix__ && !defined __ELF__ && !defined __GNUC_
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned int uint32_t;
-#endif
-
-struct profile_sample {
- uint32_t pc; // PC value
- uint32_t pid; // pid for the current process, or 0 if NOMMU or unmapped space
- uint16_t active; // threads are active - for accurate counting
- uint16_t d_blocked; // threads are blocked due to D cache misses : may be removed
- uint16_t i_blocked; // threads are blocked due to I cache misses
- uint8_t cond_codes; // for branch prediction
- uint8_t thread; // 4-bit thread number
- uint32_t a_reg; // source An if PC points to a calli. Otherwise a5 contents for parent of leaf function
- uint32_t parent[PROFILE_STACK_WORDS];
- // return addresses from stack, to find the caller
-};
-
-
-/*
- * variables for all components/modules
- */
-#ifdef ARCH_NUM_THREADS
-#define PROFILE_MAX_THREADS ARCH_NUM_THREADS
-#else
-#define PROFILE_MAX_THREADS 12
-#endif
-
-/*
- * common variables cross profile components/modules
- */
-#define PROFILE_MAX_PACKET_SIZE 1440 // MSS - tcp/ip headers
-
-/*
- * values chosen so all counter values fit in a single 1400 byte UDP packet
- */
-#define PROFILE_COUNTERS 8
-#define PROFILE_COUNTER_NAME_LENGTH 20
-#define PROFILE_MAX_APP_COUNTERS 24
-
-#define PROFILE_MAX_COUNTERS ((PROFILE_MAX_PACKET_SIZE - sizeof(struct profile_header_counters)) / (PROFILE_COUNTER_NAME_LENGTH + 4))
-
-struct profile_counter {
- char name[PROFILE_COUNTER_NAME_LENGTH];
- uint32_t value;
-};
-
-/*
- * sampling period info cross all modules -- use extended struct to avoid copy
- */
-struct profile_ext_header {
- uint16_t d_blocked; // threads are blocked due to D cache misses
- uint16_t i_blocked; // threads are blocked due to I cache misses
- uint16_t high; // threads were enabled high priority -- unused
- uint16_t enabled_threads; // threads were enabled at the last sample time
- uint16_t hrt; // HRT threads
- uint8_t profiler_tid; // thread running the profile sampler
- uint8_t sample_sets; // typical 5-8 sets, and may be 9 - see design doc for details
- uint32_t sets_map; // a set map uses a nibble, 8 maps and 9th is derived
- uint32_t clocks; // system clock timer at last sample
- uint32_t inst_count[PROFILE_MAX_THREADS]; // sampled instruction counts at most recent sample
- uint32_t stats[PROFILE_COUNTERS]; // contents of the cache statistics counters
-};
-
-#endif // _PROFILE_SAMPLE_H_
diff --git a/profiler/profpkt.h b/profiler/profpkt.h
deleted file mode 100644
index 752af06..0000000
--- a/profiler/profpkt.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- **************************************************************************
- * Copyright (c) 2014, 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.
- **************************************************************************
- */
-
-/*
- * profpkt.h
- * profile packet header to communicate with the profiler display tool
- *
- * IMPORTANT! There is a parallel verison of this file for both linux driver and profiler display tool
- *
- * Both this file and profilesample.h file must be placed
- * in dirver/.../nss (for linux driver) and as well as in tools/profiler/include directories
- * (for profilerd.c of profilerd and profile.cpp:1600::on_packet of profile tool).
- *
- * Ubi32 CPU Profiler packet formats for communication between the linux proc driver and the profiler display tool
- */
-
-#include "profilesample.h" // common definitions
-
-#define PROFILE_PORT 51080
-#define PROFILE_CONTROL_PORT 51081
-#define PROFILE_POSIX_NAME_LENGTH 32
-
-/*
- * profile UDP packet format for communicating between ip3k and host
- *
- * every packet starts with a header, followed by samples.
- * samples are only taken for non-hrt threads that are
- * active
- */
-#define PROF_MAGIC 0x3ea0
-#define PROF_MAGIC_COUNTERS 0x9ea0
-#define PROF_MAGIC_MAPS 0xaea0
-
-/*
- * Versions (31 max):
- * 1 to 4 were before 6.0 release, development versions
- * 5 was forward compatible version, shipped with 6.0 and 6.1
- * 6 adds heap packets, and clock_freq to header, shipped with 6.2
- * 7 adds a sequence numbers to check for dropped packets, shipped with 6.3.5
- * 8 adds mqueue timing information, shipped with 6.3.5
- * 9 adds sdram heap size information, shipped with 6.4
- * 10 adds heapmem heap callers and long latency stack traces. shipped with 6.4
- * 11 adds support for Mars (IP5K). shipped with 6.10
- * 12 adds more support for Mars. Shipped with 7.0
- * 13 adds per sample latency measurement. Shipped with 7.2
- * 14 changes the heap format and adds a string packet. Shipped with 7.4
- * 15 adds dsr stats and posix. shipped with 7.6
- * 16 corrects maximum packet count for Ares. ships with 7.9
- * 17 adds a5 register value to sample
- * 18 adds counter support and removes unused header fields
- * 19 adds PID support for MMU profiling
- * 20 changes the protocol for transmitting map PID maps automatically
- * 21 adds support for multiple possible parents, configurable
- */
-
-#define PROFILE_VERSION 21
-
-
-/*
- * Each packet starts with a profile_header, then sample_count samples;
- * samples are gprof samples of pc, the return address, condition codes, and active threads.
- * For performance concern, the field sequence may be reordered to match profilenode to reduce
- * a memory copy.
- */
-struct profile_pkg_header { // in network byte order !
- uint16_t magic; /* magic number and version */
- uint8_t header_size; /* number of bytes in profile header */
- uint8_t sample_count; /* number of samples in the packet */
- uint32_t sample_stack_words; /* number of stack words in the sample */
- uint32_t seq_num; /* to detect dropped profiler packets */
- uint32_t profile_instructions; /* instructions executed by profiler mainline */
-
- uint32_t unused_overlay; // untouched fields below in Linux -- to reduce memcpy
- uint32_t cpu_id; /* CHIP_ID register contents */
- uint32_t clock_freq; /* clock frequency (Hz) of system being analyzed */
- uint32_t ddr_freq; /* DDR clock frequency */
-};
-
-struct profile_header { // in network byte order !
- struct profile_pkg_header pph;
- struct profile_ext_header exh;
-};
-
-struct profile_header_counters {
- uint16_t magic;
- uint16_t ultra_count; // how many ultra counters follow this
- uint32_t ultra_sample_time; // in chip clocks
- uint32_t linux_count; // how many linux counters follow this
- uint32_t linux_sample_time;
-};
-
-/*
- * send memory maps from linux to profiler tool
- */
-
-struct profile_header_maps {
- uint16_t magic; /* magic number and last packet bit */
- uint16_t count;
- uint32_t page_shift;
-};
-
-#define PROFILE_MAP_NUM_TYPES 16
-
-/* size field is pages. True size in bytes is (1 << PAGE_SHIFT) * size */
-#define PROFILE_MAP_TYPE_FREE 0
-#define PROFILE_MAP_TYPE_SMALL 1
-#define PROFILE_MAP_TYPE_FS 2
-#define PROFILE_MAP_TYPE_UNKNOWN_USED 4
-#define PROFILE_MAP_TYPE_TEXT 5
-#define PROFILE_MAP_TYPE_STACK 6
-#define PROFILE_MAP_TYPE_APP_DATA 7
-#define PROFILE_MAP_TYPE_ASHMEM 8
-#define PROFILE_MAP_TYPE_READ_SHARED 9
-#define PROFILE_MAP_TYPE_CACHE 10
-#define PROFILE_MAP_TYPE_VMA_WASTE 11
-#define PROFILE_MAP_RESERVED 15
-
-#define PROFILE_MAP_TYPE_SHIFT 12
-#define PROFILE_MAP_SIZE_MASK 0xfff
-
-struct profile_map {
- uint16_t start; /* start page number of segment, relative to start of OCM (Max 256 MB on IP7K or 1 GB on IP8K, plus 256 KB OCM) */
- uint16_t type_size; /* type (4 bits) of the segment and size (12 bits) in pages. A size of 0 means 4K pages */
-};
-
-#define PROFILE_MAX_MAPS (PROFILE_MAX_PACKET_SIZE - sizeof(struct profile_header_maps)) / sizeof(struct profile_map)