F: examples/ptpclient/
-F: examples/quota_watermark/
-F: doc/guides/sample_app_ug/quota_watermark.rst
-
M: Bruce Richardson <bruce.richardson@intel.com>
M: John McNamara <john.mcnamara@intel.com>
F: examples/rxtx_callbacks/
* Exception Path
* L3 Forwarding in a Virtualization Environment
+ * Quota and Watermark
* vhost-scsi
multi_process
qos_metering
qos_scheduler
- quota_watermark
timer
packet_ordering
vmdq_dcb_forwarding
+++ /dev/null
-.. SPDX-License-Identifier: BSD-3-Clause
- Copyright(c) 2010-2017 Intel Corporation.
-
-Quota and Watermark Sample Application
-======================================
-
-The Quota and Watermark sample application is a simple example of packet
-processing using Data Plane Development Kit (DPDK) that showcases the use
-of a quota as the maximum number of packets enqueue/dequeue at a time and
-low and high thresholds, or watermarks, to signal low and high ring usage
-respectively.
-
-Additionally, it shows how the thresholds can be used to feedback congestion notifications to data producers by
-temporarily stopping processing overloaded rings and sending Ethernet flow control frames.
-
-This sample application is split in two parts:
-
-* qw - The core quota and watermark sample application
-
-* qwctl - A command line tool to alter quota and watermarks while qw is running
-
-Overview
---------
-
-The Quota and Watermark sample application performs forwarding for each packet that is received on a given port.
-The destination port is the adjacent port from the enabled port mask, that is,
-if the first four ports are enabled (port mask 0xf), ports 0 and 1 forward into each other,
-and ports 2 and 3 forward into each other.
-The MAC addresses of the forwarded Ethernet frames are not affected.
-
-Internally, packets are pulled from the ports by the master logical core and put on a variable length processing pipeline,
-each stage of which being connected by rings, as shown in :numref:`figure_pipeline_overview`.
-
-.. _figure_pipeline_overview:
-
-.. figure:: img/pipeline_overview.*
-
- Pipeline Overview
-
-
-An adjustable quota value controls how many packets are being moved through the pipeline per enqueue and dequeue.
-Adjustable threshold values associated with the rings control a back-off mechanism that
-tries to prevent the pipeline from being overloaded by:
-
-* Stopping enqueuing on rings for which the usage has crossed the high watermark threshold
-
-* Sending Ethernet pause frames
-
-* Only resuming enqueuing on a ring once its usage goes below a global low watermark threshold
-
-This mechanism allows congestion notifications to go up the ring pipeline and
-eventually lead to an Ethernet flow control frame being send to the source.
-
-On top of serving as an example of quota and watermark usage,
-this application can be used to benchmark ring based processing pipelines performance using a traffic- generator,
-as shown in :numref:`figure_ring_pipeline_perf_setup`.
-
-.. _figure_ring_pipeline_perf_setup:
-
-.. figure:: img/ring_pipeline_perf_setup.*
-
- Ring-based Processing Pipeline Performance Setup
-
-Compiling the Application
--------------------------
-
-To compile the sample application see :doc:`compiling`.
-
-The application is located in the ``quota_watermark`` sub-directory.
-
-Running the Application
------------------------
-
-The core application, qw, has to be started first.
-
-Once it is up and running, one can alter quota and watermarks while it runs using the control application, qwctl.
-
-Running the Core Application
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The application requires a single command line option:
-
-.. code-block:: console
-
- ./qw/build/qw [EAL options] -- -p PORTMASK
-
-where,
-
--p PORTMASK: A hexadecimal bitmask of the ports to configure
-
-To run the application in a linux environment with four logical cores and ports 0 and 2,
-issue the following command:
-
-.. code-block:: console
-
- ./qw/build/qw -l 0-3 -n 4 -- -p 5
-
-Refer to the *DPDK Getting Started Guide* for general information on running applications and
-the Environment Abstraction Layer (EAL) options.
-
-Running the Control Application
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The control application requires a number of command line options:
-
-.. code-block:: console
-
- ./qwctl/build/qwctl [EAL options] --proc-type=secondary
-
-The --proc-type=secondary option is necessary for the EAL to properly initialize the control application to
-use the same huge pages as the core application and thus be able to access its rings.
-
-To run the application in a linux environment on logical core 0, issue the following command:
-
-.. code-block:: console
-
- ./qwctl/build/qwctl -l 0 -n 4 --proc-type=secondary
-
-Refer to the *DPDK Getting Started* Guide for general information on running applications and
-the Environment Abstraction Layer (EAL) options.
-
-qwctl is an interactive command line that let the user change variables in a running instance of qw.
-The help command gives a list of available commands:
-
-.. code-block:: console
-
- $ qwctl > help
-
-Code Overview
--------------
-
-The following sections provide a quick guide to the application's source code.
-
-Core Application - qw
-~~~~~~~~~~~~~~~~~~~~~
-
-EAL and Drivers Setup
-^^^^^^^^^^^^^^^^^^^^^
-
-The EAL arguments are parsed at the beginning of the main() function:
-
-.. code-block:: c
-
- ret = rte_eal_init(argc, argv);
- if (ret < 0)
- rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n");
-
- argc -= ret;
- argv += ret;
-
-Then, a call to init_dpdk(), defined in init.c, is made to initialize the poll mode drivers:
-
-.. code-block:: c
-
- void
- init_dpdk(void)
- {
- int ret;
-
- /* Bind the drivers to usable devices */
-
- ret = rte_pci_probe();
- if (ret < 0)
- rte_exit(EXIT_FAILURE, "rte_pci_probe(): error %d\n", ret);
-
- if (rte_eth_dev_count_avail() < 2)
- rte_exit(EXIT_FAILURE, "Not enough Ethernet port available\n");
- }
-
-To fully understand this code, it is recommended to study the chapters that relate to the *Poll Mode Driver*
-in the *DPDK Getting Started Guide* and the *DPDK API Reference*.
-
-Shared Variables Setup
-^^^^^^^^^^^^^^^^^^^^^^
-
-The quota and high and low watermark shared variables are put into an rte_memzone using a call to setup_shared_variables():
-
-.. code-block:: c
-
- void
- setup_shared_variables(void)
- {
- const struct rte_memzone *qw_memzone;
-
- qw_memzone = rte_memzone_reserve(QUOTA_WATERMARK_MEMZONE_NAME,
- 3 * sizeof(int), rte_socket_id(), 0);
- if (qw_memzone == NULL)
- rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));
-
- quota = qw_memzone->addr;
- low_watermark = (unsigned int *) qw_memzone->addr + 1;
- high_watermark = (unsigned int *) qw_memzone->addr + 2;
- }
-
-These three variables are initialized to a default value in main() and
-can be changed while qw is running using the qwctl control program.
-
-Application Arguments
-^^^^^^^^^^^^^^^^^^^^^
-
-The qw application only takes one argument: a port mask that specifies which ports should be used by the application.
-At least two ports are needed to run the application and there should be an even number of ports given in the port mask.
-
-The port mask parsing is done in parse_qw_args(), defined in args.c.
-
-Mbuf Pool Initialization
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-Once the application's arguments are parsed, an mbuf pool is created.
-It contains a set of mbuf objects that are used by the driver and the application to store network packets:
-
-.. code-block:: c
-
- /* Create a pool of mbuf to store packets */
- mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 32, 0,
- MBUF_DATA_SIZE, rte_socket_id());
-
- if (mbuf_pool == NULL)
- rte_panic("%s\n", rte_strerror(rte_errno));
-
-The rte_mempool is a generic structure used to handle pools of objects.
-In this case, it is necessary to create a pool that will be used by the driver.
-
-The number of allocated pkt mbufs is MBUF_PER_POOL, with a data room size
-of MBUF_DATA_SIZE each.
-A per-lcore cache of 32 mbufs is kept.
-The memory is allocated in on the master lcore's socket, but it is possible to extend this code to allocate one mbuf pool per socket.
-
-The rte_pktmbuf_pool_create() function uses the default mbuf pool and mbuf
-initializers, respectively rte_pktmbuf_pool_init() and rte_pktmbuf_init().
-An advanced application may want to use the mempool API to create the
-mbuf pool with more control.
-
-Ports Configuration and Pairing
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Each port in the port mask is configured and a corresponding ring is created in the master lcore's array of rings.
-This ring is the first in the pipeline and will hold the packets directly coming from the port.
-
-.. code-block:: c
-
- for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++)
- if (is_bit_set(port_id, portmask)) {
- configure_eth_port(port_id);
- init_ring(master_lcore_id, port_id);
- }
-
- pair_ports();
-
-The configure_eth_port() and init_ring() functions are used to configure a port and a ring respectively and are defined in init.c.
-They make use of the DPDK APIs defined in rte_eth.h and rte_ring.h.
-
-pair_ports() builds the port_pairs[] array so that its key-value pairs are a mapping between reception and transmission ports.
-It is defined in init.c.
-
-Logical Cores Assignment
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-The application uses the master logical core to poll all the ports for new packets and enqueue them on a ring associated with the port.
-
-Each logical core except the last runs pipeline_stage() after a ring for each used port is initialized on that core.
-pipeline_stage() on core X dequeues packets from core X-1's rings and enqueue them on its own rings. See :numref:`figure_threads_pipelines`.
-
-.. code-block:: c
-
- /* Start pipeline_stage() on all the available slave lcore but the last */
-
- for (lcore_id = 0 ; lcore_id < last_lcore_id; lcore_id++) {
- if (rte_lcore_is_enabled(lcore_id) && lcore_id != master_lcore_id) {
- for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++)
- if (is_bit_set(port_id, portmask))
- init_ring(lcore_id, port_id);
-
- rte_eal_remote_launch(pipeline_stage, NULL, lcore_id);
- }
- }
-
-The last available logical core runs send_stage(),
-which is the last stage of the pipeline dequeuing packets from the last ring in the pipeline and
-sending them out on the destination port setup by pair_ports().
-
-.. code-block:: c
-
- /* Start send_stage() on the last slave core */
-
- rte_eal_remote_launch(send_stage, NULL, last_lcore_id);
-
-Receive, Process and Transmit Packets
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. _figure_threads_pipelines:
-
-.. figure:: img/threads_pipelines.*
-
- Threads and Pipelines
-
-
-In the receive_stage() function running on the master logical core,
-the main task is to read ingress packets from the RX ports and enqueue them
-on the port's corresponding first ring in the pipeline.
-This is done using the following code:
-
-.. code-block:: c
-
- lcore_id = rte_lcore_id();
-
- /* Process each port round robin style */
-
- for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
- if (!is_bit_set(port_id, portmask))
- continue;
-
- ring = rings[lcore_id][port_id];
-
- if (ring_state[port_id] != RING_READY) {
- if (rte_ring_count(ring) > *low_watermark)
- continue;
- else
- ring_state[port_id] = RING_READY;
- }
-
- /* Enqueue received packets on the RX ring */
- nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts,
- (uint16_t) *quota);
- ret = rte_ring_enqueue_bulk(ring, (void *) pkts,
- nb_rx_pkts, &free);
- if (RING_SIZE - free > *high_watermark) {
- ring_state[port_id] = RING_OVERLOADED;
- send_pause_frame(port_id, 1337);
- }
-
- if (ret == 0) {
-
- /*
- * Return mbufs to the pool,
- * effectively dropping packets
- */
- for (i = 0; i < nb_rx_pkts; i++)
- rte_pktmbuf_free(pkts[i]);
- }
- }
-
-For each port in the port mask, the corresponding ring's pointer is fetched into ring and that ring's state is checked:
-
-* If it is in the RING_READY state, \*quota packets are grabbed from the port and put on the ring.
- Should this operation make the ring's usage cross its high watermark,
- the ring is marked as overloaded and an Ethernet flow control frame is sent to the source.
-
-* If it is not in the RING_READY state, this port is ignored until the ring's usage crosses the \*low_watermark value.
-
-The pipeline_stage() function's task is to process and move packets from the preceding pipeline stage.
-This thread is running on most of the logical cores to create and arbitrarily long pipeline.
-
-.. code-block:: c
-
- lcore_id = rte_lcore_id();
-
- previous_lcore_id = get_previous_lcore_id(lcore_id);
-
- for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
- if (!is_bit_set(port_id, portmask))
- continue;
-
- tx = rings[lcore_id][port_id];
- rx = rings[previous_lcore_id][port_id];
-
- if (ring_state[port_id] != RING_READY) {
- if (rte_ring_count(tx) > *low_watermark)
- continue;
- else
- ring_state[port_id] = RING_READY;
- }
-
- /* Dequeue up to quota mbuf from rx */
- nb_dq_pkts = rte_ring_dequeue_burst(rx, pkts,
- *quota, NULL);
- if (unlikely(nb_dq_pkts < 0))
- continue;
-
- /* Enqueue them on tx */
- ret = rte_ring_enqueue_bulk(tx, pkts,
- nb_dq_pkts, &free);
- if (RING_SIZE - free > *high_watermark)
- ring_state[port_id] = RING_OVERLOADED;
-
- if (ret == 0) {
-
- /*
- * Return mbufs to the pool,
- * effectively dropping packets
- */
- for (i = 0; i < nb_dq_pkts; i++)
- rte_pktmbuf_free(pkts[i]);
- }
- }
-
-The thread's logic works mostly like receive_stage(),
-except that packets are moved from ring to ring instead of port to ring.
-
-In this example, no actual processing is done on the packets,
-but pipeline_stage() is an ideal place to perform any processing required by the application.
-
-Finally, the send_stage() function's task is to read packets from the last ring in a pipeline and
-send them on the destination port defined in the port_pairs[] array.
-It is running on the last available logical core only.
-
-.. code-block:: c
-
- lcore_id = rte_lcore_id();
-
- previous_lcore_id = get_previous_lcore_id(lcore_id);
-
- for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
- if (!is_bit_set(port_id, portmask)) continue;
-
- dest_port_id = port_pairs[port_id];
- tx = rings[previous_lcore_id][port_id];
-
- if (rte_ring_empty(tx)) continue;
-
- /* Dequeue packets from tx and send them */
-
- nb_dq_pkts = rte_ring_dequeue_burst(tx, (void *) tx_pkts, *quota);
- nb_tx_pkts = rte_eth_tx_burst(dest_port_id, 0, tx_pkts, nb_dq_pkts);
- }
-
-For each port in the port mask, up to \*quota packets are pulled from the last ring in its pipeline and
-sent on the destination port paired with the current port.
-
-Control Application - qwctl
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The qwctl application uses the rte_cmdline library to provide the user with an interactive command line that
-can be used to modify and inspect parameters in a running qw application.
-Those parameters are the global quota and low_watermark value as well as each ring's built-in high watermark.
-
-Command Definitions
-^^^^^^^^^^^^^^^^^^^
-
-The available commands are defined in commands.c.
-
-It is advised to use the cmdline sample application user guide as a reference for everything related to the rte_cmdline library.
-
-Accessing Shared Variables
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The setup_shared_variables() function retrieves the shared variables quota and
-low_watermark from the rte_memzone previously created by qw.
-
-.. code-block:: c
-
- static void
- setup_shared_variables(void)
- {
- const struct rte_memzone *qw_memzone;
-
- qw_memzone = rte_memzone_lookup(QUOTA_WATERMARK_MEMZONE_NAME);
- if (qw_memzone == NULL)
- rte_exit(EXIT_FAILURE, "Couldn't find memzone\n");
-
- quota = qw_memzone->addr;
-
- low_watermark = (unsigned int *) qw_memzone->addr + 1;
- high_watermark = (unsigned int *) qw_memzone->addr + 2;
- }
DIRS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ptpclient
DIRS-$(CONFIG_RTE_LIBRTE_METER) += qos_meter
DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += qos_sched
-DIRS-y += quota_watermark
DIRS-$(CONFIG_RTE_ETHDEV_RXTX_CALLBACKS) += rxtx_callbacks
DIRS-y += service_cores
DIRS-y += skeleton
'netmap_compat', 'ntb', 'packet_ordering',
'performance-thread', 'ptpclient',
'qos_meter', 'qos_sched',
- 'quota_watermark', 'rxtx_callbacks',
+ 'rxtx_callbacks',
'server_node_efd', 'service_cores',
'skeleton', 'tep_termination',
'timer', 'vdpa',
+++ /dev/null
-# SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2010-2014 Intel Corporation
-
-ifeq ($(RTE_SDK),)
-$(error "Please define RTE_SDK environment variable")
-endif
-
-# Default target, detect a build directory, by looking for a path with a .config
-RTE_TARGET ?= $(notdir $(abspath $(dir $(firstword $(wildcard $(RTE_SDK)/*/.config)))))
-
-include $(RTE_SDK)/mk/rte.vars.mk
-
-DIRS-$(CONFIG_RTE_EXEC_ENV_LINUX) += qw
-DIRS-$(CONFIG_RTE_EXEC_ENV_LINUX) += qwctl
-
-include $(RTE_SDK)/mk/rte.extsubdir.mk
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#ifndef _CONF_H_
-#define _CONF_H_
-
-#define RING_SIZE 1024
-#define MAX_PKT_QUOTA 64
-
-#define RX_DESC_PER_QUEUE 1024
-#define TX_DESC_PER_QUEUE 1024
-
-#define MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE
-#define MBUF_PER_POOL 8192
-
-#define QUOTA_WATERMARK_MEMZONE_NAME "qw_global_vars"
-
-#endif /* _CONF_H_ */
+++ /dev/null
-# SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2018 Intel Corporation
-
-# meson file, for building this example as part of a main DPDK build.
-#
-# To build this example as a standalone application with an already-installed
-# DPDK instance, use 'make'
-
-# Example app currently unsupported by meson build
-build = false
+++ /dev/null
-# SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2010-2014 Intel Corporation
-
-ifeq ($(RTE_SDK),)
-$(error "Please define RTE_SDK environment variable")
-endif
-
-# Default target, detect a build directory, by looking for a path with a .config
-RTE_TARGET ?= $(notdir $(abspath $(dir $(firstword $(wildcard $(RTE_SDK)/*/.config)))))
-
-include $(RTE_SDK)/mk/rte.vars.mk
-
-# binary name
-APP = qw
-
-# all source are stored in SRCS-y
-SRCS-y := args.c init.c main.c
-
-CFLAGS += -O3 -DQW_SOFTWARE_FC
-CFLAGS += $(WERROR_FLAGS)
-
-include $(RTE_SDK)/mk/rte.extapp.mk
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <rte_common.h>
-#include <rte_lcore.h>
-
-#include "args.h"
-
-
-unsigned int portmask = 0;
-
-
-static void
-usage(const char *prgname)
-{
- fprintf(stderr, "Usage: %s [EAL args] -- -p <portmask>\n"
- "-p PORTMASK: hexadecimal bitmask of NIC ports to configure\n",
- prgname);
-}
-
-static unsigned long
-parse_portmask(const char *portmask_str)
-{
- return strtoul(portmask_str, NULL, 16);
-}
-
-static void
-check_core_count(void)
-{
- if (rte_lcore_count() < 3)
- rte_exit(EXIT_FAILURE,
- "At least 3 cores need to be passed in the coremask\n");
-}
-
-static void
-check_portmask_value(unsigned int portmask)
-{
- unsigned int port_nb = 0;
-
- port_nb = __builtin_popcount(portmask);
-
- if (port_nb == 0)
- rte_exit(EXIT_FAILURE,
- "At least 2 ports need to be passed in the portmask\n");
-
- if (port_nb % 2 != 0)
- rte_exit(EXIT_FAILURE,
- "An even number of ports is required in the portmask\n");
-}
-
-int
-parse_qw_args(int argc, char **argv)
-{
- int opt;
-
- while ((opt = getopt(argc, argv, "h:p:")) != -1) {
- switch (opt) {
- case 'h':
- usage(argv[0]);
- break;
- case 'p':
- portmask = parse_portmask(optarg);
- break;
- default:
- usage(argv[0]);
- }
- }
-
- check_core_count();
- check_portmask_value(portmask);
-
- return 0;
-}
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#ifndef _ARGS_H_
-#define _ARGS_H_
-
-extern unsigned int portmask;
-
-int parse_qw_args(int argc, char **argv);
-
-#endif /* _ARGS_H_ */
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/mman.h>
-
-#include <rte_eal.h>
-
-#include <rte_common.h>
-#include <rte_errno.h>
-#include <rte_ethdev.h>
-#include <rte_memzone.h>
-#include <rte_ring.h>
-#include <rte_string_fns.h>
-
-#include "args.h"
-#include "init.h"
-#include "main.h"
-#include "../include/conf.h"
-
-
-static struct rte_eth_conf port_conf = {
- .rxmode = {
- .split_hdr_size = 0,
- },
- .txmode = {
- .mq_mode = ETH_DCB_NONE,
- },
-};
-
-static struct rte_eth_fc_conf fc_conf = {
- .mode = RTE_FC_TX_PAUSE,
- .high_water = 80 * 510 / 100,
- .low_water = 60 * 510 / 100,
- .pause_time = 1337,
- .send_xon = 0,
-};
-
-
-void configure_eth_port(uint16_t port_id)
-{
- int ret;
- uint16_t nb_rxd = RX_DESC_PER_QUEUE;
- uint16_t nb_txd = TX_DESC_PER_QUEUE;
- struct rte_eth_rxconf rxq_conf;
- struct rte_eth_txconf txq_conf;
- struct rte_eth_dev_info dev_info;
- struct rte_eth_conf local_port_conf = port_conf;
-
- rte_eth_dev_stop(port_id);
-
- rte_eth_dev_info_get(port_id, &dev_info);
- if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
- local_port_conf.txmode.offloads |=
- DEV_TX_OFFLOAD_MBUF_FAST_FREE;
- ret = rte_eth_dev_configure(port_id, 1, 1, &local_port_conf);
- if (ret < 0)
- rte_exit(EXIT_FAILURE, "Cannot configure port %u (error %d)\n",
- (unsigned int) port_id, ret);
-
- ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd);
- if (ret < 0)
- rte_exit(EXIT_FAILURE,
- "Cannot adjust number of descriptors for port %u (error %d)\n",
- (unsigned int) port_id, ret);
-
- /* Initialize the port's RX queue */
- rxq_conf = dev_info.default_rxconf;
- rxq_conf.offloads = local_port_conf.rxmode.offloads;
- ret = rte_eth_rx_queue_setup(port_id, 0, nb_rxd,
- rte_eth_dev_socket_id(port_id),
- &rxq_conf,
- mbuf_pool);
- if (ret < 0)
- rte_exit(EXIT_FAILURE,
- "Failed to setup RX queue on port %u (error %d)\n",
- (unsigned int) port_id, ret);
-
- /* Initialize the port's TX queue */
- txq_conf = dev_info.default_txconf;
- txq_conf.offloads = local_port_conf.txmode.offloads;
- ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd,
- rte_eth_dev_socket_id(port_id),
- &txq_conf);
- if (ret < 0)
- rte_exit(EXIT_FAILURE,
- "Failed to setup TX queue on port %u (error %d)\n",
- (unsigned int) port_id, ret);
-
- /* Initialize the port's flow control */
- ret = rte_eth_dev_flow_ctrl_set(port_id, &fc_conf);
- if (ret < 0)
- rte_exit(EXIT_FAILURE,
- "Failed to setup hardware flow control on port %u (error %d)\n",
- (unsigned int) port_id, ret);
-
- /* Start the port */
- ret = rte_eth_dev_start(port_id);
- if (ret < 0)
- rte_exit(EXIT_FAILURE, "Failed to start port %u (error %d)\n",
- (unsigned int) port_id, ret);
-
- /* Put it in promiscuous mode */
- ret = rte_eth_promiscuous_enable(port_id);
- if (ret != 0)
- rte_exit(EXIT_FAILURE,
- "Failed to enable promiscuous mode for port %u: %s\n",
- port_id, rte_strerror(-ret));
-}
-
-void
-init_dpdk(void)
-{
- if (rte_eth_dev_count_avail() < 2)
- rte_exit(EXIT_FAILURE, "Not enough ethernet port available\n");
-}
-
-void init_ring(int lcore_id, uint16_t port_id)
-{
- struct rte_ring *ring;
- char ring_name[RTE_RING_NAMESIZE];
-
- snprintf(ring_name, RTE_RING_NAMESIZE,
- "core%d_port%d", lcore_id, port_id);
- ring = rte_ring_create(ring_name, RING_SIZE, rte_socket_id(),
- RING_F_SP_ENQ | RING_F_SC_DEQ);
-
- if (ring == NULL)
- rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));
-
- *high_watermark = 80 * RING_SIZE / 100;
-
- rings[lcore_id][port_id] = ring;
-}
-
-void
-pair_ports(void)
-{
- uint16_t i, j;
-
- /* Pair ports with their "closest neighbour" in the portmask */
- for (i = 0; i < RTE_MAX_ETHPORTS; i++)
- if (is_bit_set(i, portmask))
- for (j = i + 1; j < RTE_MAX_ETHPORTS; j++)
- if (is_bit_set(j, portmask)) {
- port_pairs[i] = j;
- port_pairs[j] = i;
- i = j;
- break;
- }
-}
-
-void
-setup_shared_variables(void)
-{
- const struct rte_memzone *qw_memzone;
-
- qw_memzone = rte_memzone_reserve(QUOTA_WATERMARK_MEMZONE_NAME,
- 3 * sizeof(int), rte_socket_id(), 0);
- if (qw_memzone == NULL)
- rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));
-
- quota = qw_memzone->addr;
- low_watermark = (unsigned int *) qw_memzone->addr + 1;
- high_watermark = (unsigned int *) qw_memzone->addr + 2;
-}
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#ifndef _INIT_H_
-#define _INIT_H_
-
-void configure_eth_port(uint16_t port_id);
-void init_dpdk(void);
-void init_ring(int lcore_id, uint16_t port_id);
-void pair_ports(void);
-void setup_shared_variables(void);
-
-#endif /* _INIT_H_ */
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#include <rte_eal.h>
-
-#include <rte_common.h>
-#include <rte_debug.h>
-#include <rte_errno.h>
-#include <rte_ethdev.h>
-#include <rte_launch.h>
-#include <rte_lcore.h>
-#include <rte_log.h>
-#include <rte_mbuf.h>
-#include <rte_ring.h>
-
-#include <rte_byteorder.h>
-
-#include "args.h"
-#include "main.h"
-#include "init.h"
-#include "../include/conf.h"
-
-
-#ifdef QW_SOFTWARE_FC
-#define SEND_PAUSE_FRAME(port_id, duration) send_pause_frame(port_id, duration)
-#else
-#define SEND_PAUSE_FRAME(port_id, duration) do { } while(0)
-#endif
-
-#define ETHER_TYPE_FLOW_CONTROL 0x8808
-
-struct ether_fc_frame {
- uint16_t opcode;
- uint16_t param;
-} __attribute__((__packed__));
-
-
-int *quota;
-unsigned int *low_watermark;
-unsigned int *high_watermark;
-
-uint16_t port_pairs[RTE_MAX_ETHPORTS];
-
-struct rte_ring *rings[RTE_MAX_LCORE][RTE_MAX_ETHPORTS];
-struct rte_mempool *mbuf_pool;
-
-
-static void send_pause_frame(uint16_t port_id, uint16_t duration)
-{
- struct rte_mbuf *mbuf;
- struct ether_fc_frame *pause_frame;
- struct rte_ether_hdr *hdr;
- struct rte_ether_addr mac_addr;
- int ret;
-
- RTE_LOG_DP(DEBUG, USER1,
- "Sending PAUSE frame (duration=%d) on port %d\n",
- duration, port_id);
-
- ret = rte_eth_macaddr_get(port_id, &mac_addr);
- if (ret != 0) {
- RTE_LOG_DP(ERR, USER1,
- "Failed to get MAC address (port %u): %s\n",
- port_id, rte_strerror(-ret));
- return;
- }
-
- /* Get a mbuf from the pool */
- mbuf = rte_pktmbuf_alloc(mbuf_pool);
- if (unlikely(mbuf == NULL))
- return;
-
- /* Prepare a PAUSE frame */
- hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
- pause_frame = (struct ether_fc_frame *) &hdr[1];
-
- rte_ether_addr_copy(&mac_addr, &hdr->s_addr);
-
- void *tmp = &hdr->d_addr.addr_bytes[0];
- *((uint64_t *)tmp) = 0x010000C28001ULL;
-
- hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_FLOW_CONTROL);
-
- pause_frame->opcode = rte_cpu_to_be_16(0x0001);
- pause_frame->param = rte_cpu_to_be_16(duration);
-
- mbuf->pkt_len = 60;
- mbuf->data_len = 60;
-
- rte_eth_tx_burst(port_id, 0, &mbuf, 1);
-}
-
-/**
- * Get the previous enabled lcore ID
- *
- * @param lcore_id
- * The current lcore ID.
- * @return
- * The previous enabled lcore_id or -1 if not found.
- */
-static unsigned int
-get_previous_lcore_id(unsigned int lcore_id)
-{
- int i;
-
- for (i = lcore_id - 1; i >= 0; i--)
- if (rte_lcore_is_enabled(i))
- return i;
-
- return -1;
-}
-
-/**
- * Get the last enabled lcore ID
- *
- * @return
- * The last enabled lcore_id.
- */
-static unsigned int
-get_last_lcore_id(void)
-{
- int i;
-
- for (i = RTE_MAX_LCORE; i >= 0; i--)
- if (rte_lcore_is_enabled(i))
- return i;
-
- return 0;
-}
-
-static void
-receive_stage(__attribute__((unused)) void *args)
-{
- int i, ret;
-
- uint16_t port_id;
- uint16_t nb_rx_pkts;
-
- unsigned int lcore_id;
- unsigned int free;
-
- struct rte_mbuf *pkts[MAX_PKT_QUOTA];
- struct rte_ring *ring;
- enum ring_state ring_state[RTE_MAX_ETHPORTS] = { RING_READY };
-
- lcore_id = rte_lcore_id();
-
- RTE_LOG(INFO, USER1,
- "%s() started on core %u\n", __func__, lcore_id);
-
- while (1) {
-
- /* Process each port round robin style */
- for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
-
- if (!is_bit_set(port_id, portmask))
- continue;
-
- ring = rings[lcore_id][port_id];
-
- if (ring_state[port_id] != RING_READY) {
- if (rte_ring_count(ring) > *low_watermark)
- continue;
- else
- ring_state[port_id] = RING_READY;
- }
-
- /* Enqueue received packets on the RX ring */
- nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts,
- (uint16_t) *quota);
- ret = rte_ring_enqueue_bulk(ring, (void *) pkts,
- nb_rx_pkts, &free);
- if (RING_SIZE - free > *high_watermark) {
- ring_state[port_id] = RING_OVERLOADED;
- send_pause_frame(port_id, 1337);
- }
-
- if (ret == 0) {
-
- /*
- * Return mbufs to the pool,
- * effectively dropping packets
- */
- for (i = 0; i < nb_rx_pkts; i++)
- rte_pktmbuf_free(pkts[i]);
- }
- }
- }
-}
-
-static int
-pipeline_stage(__attribute__((unused)) void *args)
-{
- int i, ret;
- int nb_dq_pkts;
-
- uint16_t port_id;
-
- unsigned int lcore_id, previous_lcore_id;
- unsigned int free;
-
- void *pkts[MAX_PKT_QUOTA];
- struct rte_ring *rx, *tx;
- enum ring_state ring_state[RTE_MAX_ETHPORTS] = { RING_READY };
-
- lcore_id = rte_lcore_id();
- previous_lcore_id = get_previous_lcore_id(lcore_id);
-
- RTE_LOG(INFO, USER1,
- "%s() started on core %u - processing packets from core %u\n",
- __func__, lcore_id, previous_lcore_id);
-
- while (1) {
-
- for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
-
- if (!is_bit_set(port_id, portmask))
- continue;
-
- tx = rings[lcore_id][port_id];
- rx = rings[previous_lcore_id][port_id];
-
- if (ring_state[port_id] != RING_READY) {
- if (rte_ring_count(tx) > *low_watermark)
- continue;
- else
- ring_state[port_id] = RING_READY;
- }
-
- /* Dequeue up to quota mbuf from rx */
- nb_dq_pkts = rte_ring_dequeue_burst(rx, pkts,
- *quota, NULL);
- if (unlikely(nb_dq_pkts < 0))
- continue;
-
- /* Enqueue them on tx */
- ret = rte_ring_enqueue_bulk(tx, pkts,
- nb_dq_pkts, &free);
- if (RING_SIZE - free > *high_watermark)
- ring_state[port_id] = RING_OVERLOADED;
-
- if (ret == 0) {
-
- /*
- * Return mbufs to the pool,
- * effectively dropping packets
- */
- for (i = 0; i < nb_dq_pkts; i++)
- rte_pktmbuf_free(pkts[i]);
- }
- }
- }
-
- return 0;
-}
-
-static int
-send_stage(__attribute__((unused)) void *args)
-{
- uint16_t nb_dq_pkts;
-
- uint16_t port_id;
- uint16_t dest_port_id;
-
- unsigned int lcore_id, previous_lcore_id;
-
- struct rte_ring *tx;
- struct rte_mbuf *tx_pkts[MAX_PKT_QUOTA];
-
- lcore_id = rte_lcore_id();
- previous_lcore_id = get_previous_lcore_id(lcore_id);
-
- RTE_LOG(INFO, USER1,
- "%s() started on core %u - processing packets from core %u\n",
- __func__, lcore_id, previous_lcore_id);
-
- while (1) {
-
- /* Process each ring round robin style */
- for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
-
- if (!is_bit_set(port_id, portmask))
- continue;
-
- dest_port_id = port_pairs[port_id];
- tx = rings[previous_lcore_id][port_id];
-
- if (rte_ring_empty(tx))
- continue;
-
- /* Dequeue packets from tx and send them */
- nb_dq_pkts = (uint16_t) rte_ring_dequeue_burst(tx,
- (void *) tx_pkts, *quota, NULL);
- rte_eth_tx_burst(dest_port_id, 0, tx_pkts, nb_dq_pkts);
-
- /* TODO: Check if nb_dq_pkts == nb_tx_pkts? */
- }
- }
-
- return 0;
-}
-
-int
-main(int argc, char **argv)
-{
- int ret;
- unsigned int lcore_id, master_lcore_id, last_lcore_id;
-
- uint16_t port_id;
-
- rte_log_set_global_level(RTE_LOG_INFO);
-
- ret = rte_eal_init(argc, argv);
- if (ret < 0)
- rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n");
-
- argc -= ret;
- argv += ret;
-
- init_dpdk();
- setup_shared_variables();
-
- *quota = 32;
- *low_watermark = 60 * RING_SIZE / 100;
-
- last_lcore_id = get_last_lcore_id();
- master_lcore_id = rte_get_master_lcore();
-
- /* Parse the application's arguments */
- ret = parse_qw_args(argc, argv);
- if (ret < 0)
- rte_exit(EXIT_FAILURE, "Invalid quota/watermark argument(s)\n");
-
- /* Create a pool of mbuf to store packets */
- mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 32, 0,
- MBUF_DATA_SIZE, rte_socket_id());
- if (mbuf_pool == NULL)
- rte_panic("%s\n", rte_strerror(rte_errno));
-
- for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++)
- if (is_bit_set(port_id, portmask)) {
- configure_eth_port(port_id);
- init_ring(master_lcore_id, port_id);
- }
-
- pair_ports();
-
- /*
- * Start pipeline_connect() on all the available slave lcores
- * but the last
- */
- for (lcore_id = 0 ; lcore_id < last_lcore_id; lcore_id++) {
- if (rte_lcore_is_enabled(lcore_id) &&
- lcore_id != master_lcore_id) {
-
- for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++)
- if (is_bit_set(port_id, portmask))
- init_ring(lcore_id, port_id);
-
- rte_eal_remote_launch(pipeline_stage,
- NULL, lcore_id);
- }
- }
-
- /* Start send_stage() on the last slave core */
- rte_eal_remote_launch(send_stage, NULL, last_lcore_id);
-
- /* Start receive_stage() on the master core */
- receive_stage(NULL);
-
- return 0;
-}
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#ifndef _MAIN_H_
-#define _MAIN_H_
-
-#include "../include/conf.h"
-
-enum ring_state {
- RING_READY,
- RING_OVERLOADED,
-};
-
-extern int *quota;
-extern unsigned int *low_watermark;
-extern unsigned int *high_watermark;
-
-extern uint16_t port_pairs[RTE_MAX_ETHPORTS];
-
-extern struct rte_ring *rings[RTE_MAX_LCORE][RTE_MAX_ETHPORTS];
-extern struct rte_mempool *mbuf_pool;
-
-
-static inline int
-is_bit_set(int i, unsigned int mask)
-{
- return (1 << i) & mask;
-}
-
-#endif /* _MAIN_H_ */
+++ /dev/null
-# SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2010-2014 Intel Corporation
-
-ifeq ($(RTE_SDK),)
-$(error "Please define RTE_SDK environment variable")
-endif
-
-# Default target, detect a build directory, by looking for a path with a .config
-RTE_TARGET ?= $(notdir $(abspath $(dir $(firstword $(wildcard $(RTE_SDK)/*/.config)))))
-
-include $(RTE_SDK)/mk/rte.vars.mk
-
-# binary name
-APP = qwctl
-
-# all source are stored in SRCS-y
-SRCS-y := commands.c qwctl.c
-
-CFLAGS += -O3
-CFLAGS += $(WERROR_FLAGS)
-
-include $(RTE_SDK)/mk/rte.extapp.mk
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <termios.h>
-
-#include <cmdline_rdline.h>
-#include <cmdline_parse.h>
-#include <cmdline_parse_num.h>
-#include <cmdline_parse_string.h>
-#include <cmdline.h>
-
-#include <rte_ring.h>
-
-#include "qwctl.h"
-#include "../include/conf.h"
-
-
-/**
- * help command
- */
-
-struct cmd_help_tokens {
- cmdline_fixed_string_t verb;
-};
-
-cmdline_parse_token_string_t cmd_help_verb =
- TOKEN_STRING_INITIALIZER(struct cmd_help_tokens, verb, "help");
-
-static void
-cmd_help_handler(__attribute__((unused)) void *parsed_result,
- struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- cmdline_printf(cl, "Available commands:\n"
- "- help\n"
- "- set [ring_name|variable] <value>\n"
- "- show [ring_name|variable]\n"
- "\n"
- "Available variables:\n"
- "- low_watermark\n"
- "- quota\n"
- "- ring names follow the core%%u_port%%u format\n");
-}
-
-cmdline_parse_inst_t cmd_help = {
- .f = cmd_help_handler,
- .data = NULL,
- .help_str = "show help",
- .tokens = {
- (void *) &cmd_help_verb,
- NULL,
- },
-};
-
-
-/**
- * set command
- */
-
-struct cmd_set_tokens {
- cmdline_fixed_string_t verb;
- cmdline_fixed_string_t variable;
- uint32_t value;
-};
-
-cmdline_parse_token_string_t cmd_set_verb =
- TOKEN_STRING_INITIALIZER(struct cmd_set_tokens, verb, "set");
-
-cmdline_parse_token_string_t cmd_set_variable =
- TOKEN_STRING_INITIALIZER(struct cmd_set_tokens, variable, NULL);
-
-cmdline_parse_token_num_t cmd_set_value =
- TOKEN_NUM_INITIALIZER(struct cmd_set_tokens, value, UINT32);
-
-static void
-cmd_set_handler(__attribute__((unused)) void *parsed_result,
- struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_set_tokens *tokens = parsed_result;
- struct rte_ring *ring;
-
- if (!strcmp(tokens->variable, "quota")) {
-
- if (tokens->value > 0 && tokens->value <= MAX_PKT_QUOTA)
- *quota = tokens->value;
- else
- cmdline_printf(cl, "quota must be between 1 and %u\n",
- MAX_PKT_QUOTA);
- }
-
- else if (!strcmp(tokens->variable, "low_watermark")) {
-
- if (tokens->value <= 100)
- *low_watermark = tokens->value * RING_SIZE / 100;
- else
- cmdline_printf(cl,
- "low_watermark must be between 0%% and 100%%\n");
- }
-
- else {
-
- ring = rte_ring_lookup(tokens->variable);
- if (ring == NULL)
- cmdline_printf(cl, "Cannot find ring \"%s\"\n",
- tokens->variable);
- else
- if (tokens->value >= *low_watermark * 100 / RING_SIZE
- && tokens->value <= 100)
- *high_watermark = tokens->value *
- RING_SIZE / 100;
- else
- cmdline_printf(cl,
- "ring high watermark must be between %u%% and 100%%\n",
- *low_watermark * 100 / RING_SIZE);
- }
-}
-
-cmdline_parse_inst_t cmd_set = {
- .f = cmd_set_handler,
- .data = NULL,
- .help_str = "Set a variable value",
- .tokens = {
- (void *) &cmd_set_verb,
- (void *) &cmd_set_variable,
- (void *) &cmd_set_value,
- NULL,
- },
-};
-
-
-/**
- * show command
- */
-
-struct cmd_show_tokens {
- cmdline_fixed_string_t verb;
- cmdline_fixed_string_t variable;
-};
-
-cmdline_parse_token_string_t cmd_show_verb =
- TOKEN_STRING_INITIALIZER(struct cmd_show_tokens, verb, "show");
-
-cmdline_parse_token_string_t cmd_show_variable =
- TOKEN_STRING_INITIALIZER(struct cmd_show_tokens,
- variable, NULL);
-
-
-static void
-cmd_show_handler(__attribute__((unused)) void *parsed_result,
- struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_show_tokens *tokens = parsed_result;
- struct rte_ring *ring;
-
- if (!strcmp(tokens->variable, "quota"))
- cmdline_printf(cl, "Global quota: %d\n", *quota);
-
- else if (!strcmp(tokens->variable, "low_watermark"))
- cmdline_printf(cl, "Global low_watermark: %u\n",
- *low_watermark);
-
- else {
-
- ring = rte_ring_lookup(tokens->variable);
- if (ring == NULL)
- cmdline_printf(cl, "Cannot find ring \"%s\"\n",
- tokens->variable);
- else
- rte_ring_dump(stdout, ring);
- }
-}
-
-cmdline_parse_inst_t cmd_show = {
- .f = cmd_show_handler,
- .data = NULL,
- .help_str = "Show a variable value",
- .tokens = {
- (void *) &cmd_show_verb,
- (void *) &cmd_show_variable,
- NULL,
- },
-};
-
-
-cmdline_parse_ctx_t qwctl_ctx[] = {
- (cmdline_parse_inst_t *)&cmd_help,
- (cmdline_parse_inst_t *)&cmd_set,
- (cmdline_parse_inst_t *)&cmd_show,
- NULL,
-};
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#ifndef _COMMANDS_H_
-#define _COMMANDS_H_
-
-#include <cmdline_parse.h>
-
-extern cmdline_parse_ctx_t qwctl_ctx[];
-
-#endif /* _COMMANDS_H_ */
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <termios.h>
-#include <unistd.h>
-#include <sys/mman.h>
-
-#include <rte_eal.h>
-
-#include <rte_log.h>
-#include <rte_memzone.h>
-
-#include <cmdline_rdline.h>
-#include <cmdline_parse.h>
-#include <cmdline_socket.h>
-#include <cmdline.h>
-
-
-#include "qwctl.h"
-#include "commands.h"
-#include "../include/conf.h"
-
-
-int *quota;
-unsigned int *low_watermark;
-unsigned int *high_watermark;
-
-
-static void
-setup_shared_variables(void)
-{
- const struct rte_memzone *qw_memzone;
-
- qw_memzone = rte_memzone_lookup(QUOTA_WATERMARK_MEMZONE_NAME);
- if (qw_memzone == NULL)
- rte_exit(EXIT_FAILURE, "Couldn't find memzone\n");
-
- quota = qw_memzone->addr;
- low_watermark = (unsigned int *) qw_memzone->addr + 1;
- high_watermark = (unsigned int *) qw_memzone->addr + 2;
-}
-
-int main(int argc, char **argv)
-{
- int ret;
- struct cmdline *cl;
-
- rte_log_set_global_level(RTE_LOG_INFO);
-
- ret = rte_eal_init(argc, argv);
- if (ret < 0)
- rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n");
-
- setup_shared_variables();
-
- cl = cmdline_stdin_new(qwctl_ctx, "qwctl> ");
- if (cl == NULL)
- rte_exit(EXIT_FAILURE, "Cannot create cmdline instance\n");
-
- cmdline_interact(cl);
- cmdline_stdin_exit(cl);
-
- return 0;
-}
+++ /dev/null
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#ifndef _MAIN_H_
-#define _MAIN_H_
-
-extern int *quota;
-extern unsigned int *low_watermark;
-extern unsigned int *high_watermark;
-
-#endif /* _MAIN_H_ */