Message ID | 1445546631-22732-2-git-send-email-bill.fischofer@linaro.org |
---|---|
State | Superseded |
Headers | show |
Reviewed-by: Petri Savolainen <petri.savolainen@nokia.com> Bill, did you run 'make doxygen-html'? Not sure if @def ODP_PACKET_GREEN works when it's actually an enum. Anyway, it's in the correct file now. -Petri > -----Original Message----- > From: lng-odp [mailto:lng-odp-bounces@lists.linaro.org] On Behalf Of EXT > Bill Fischofer > Sent: Thursday, October 22, 2015 11:44 PM > To: lng-odp@lists.linaro.org > Cc: Barry Spinney > Subject: [lng-odp] [API-NEXT PATCHv6 1/4] api: tm: add tm API definitions > > From: Barry Spinney <spinney@ezchip.com> > > This introduces an API for configuring and using Traffic Management > systems. > > The purpose of this API is as a general packet scheduling system that > accepts packets from input queues and applies strict priority > scheduling, weighted fair queuing scheduling and/or bandwidth controls > to decide which input packet should be chosen as the next output > packet and when this output packet can be sent onwards. > > Signed-off-by: Barry Spinney <spinney@ezchip.com> > Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org> > --- > include/odp.h | 1 + > include/odp/api/packet.h | 69 + > include/odp/api/traffic_mngr.h | 1611 > ++++++++++++++++++++ > .../linux-generic/include/odp/plat/packet_types.h | 11 + > .../include/odp/plat/traffic_mngr_types.h | 185 +++ > platform/linux-generic/include/odp/traffic_mngr.h | 35 + > .../linux-generic/include/odp_packet_internal.h | 5 + > 7 files changed, 1917 insertions(+) > create mode 100644 include/odp/api/traffic_mngr.h > create mode 100644 platform/linux- > generic/include/odp/plat/traffic_mngr_types.h > create mode 100644 platform/linux-generic/include/odp/traffic_mngr.h > > diff --git a/include/odp.h b/include/odp.h > index 825c7e1..f6a6ea9 100644 > --- a/include/odp.h > +++ b/include/odp.h > @@ -56,6 +56,7 @@ extern "C" { > #include <odp/thrmask.h> > #include <odp/spinlock_recursive.h> > #include <odp/rwlock_recursive.h> > +#include <odp/traffic_mngr.h> > > #ifdef __cplusplus > } > diff --git a/include/odp/api/packet.h b/include/odp/api/packet.h > index 5d46b7b..0680b3f 100644 > --- a/include/odp/api/packet.h > +++ b/include/odp/api/packet.h > @@ -48,6 +48,26 @@ extern "C" { > * Invalid packet segment > */ > > + /** > + * @typedef odp_packet_color_t > + * Color of packet for shaper/drop processing > + */ > + > + /** > + * @def ODP_PACKET_GREEN > + * Packet is green > + */ > + > + /** > + * @def ODP_PACKET_YELLOW > + * Packet is yellow > + */ > + > + /** > + * @def ODP_PACKET_RED > + * Packet is red > + */ > + > /* > * > * Alloc and free > @@ -700,6 +720,55 @@ odp_packet_seg_t odp_packet_last_seg(odp_packet_t > pkt); > */ > odp_packet_seg_t odp_packet_next_seg(odp_packet_t pkt, odp_packet_seg_t > seg); > > +/** > + * Get packet color > + * > + * @param pkt Packet handle > + * @return packet color > + */ > +odp_packet_color_t odp_packet_color(odp_packet_t pkt); > + > +/** > + * Set packet color > + * > + * @param pkt Packet handle > + * @param color Color to set > + */ > +void odp_packet_color_set(odp_packet_t pkt, odp_packet_color_t color); > + > +/** > + * Get drop eligible status > + * > + * @param pkt Packet handle > + * @return Packet drop eligibility status > + * @retval 0 Packet is not drop eligible > + * @retval 1 Packet is drop > + */ > +odp_bool_t odp_packet_drop_eligible(odp_packet_t pkt); > + > +/** > + * Set drop eligible status > + * > + * @param pkt Packet handle > + * @param status Drop eligibility status > + */ > +void odp_packet_drop_eligible_set(odp_packet_t pkt, odp_bool_t status); > + > +/** > + * Get shaper length adjustment > + * > + * @param pkt Packet handle > + * @return Shaper adjustment (-128..127) > + */ > +int8_t odp_packet_shaper_len_adjust(odp_packet_t pkt); > + > +/** > + * Set shaper length adjustment > + * > + * @param pkt Packet handle > + * @param adj Signed adjustment value > + */ > +void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, int8_t adj); > > /* > * > diff --git a/include/odp/api/traffic_mngr.h > b/include/odp/api/traffic_mngr.h > new file mode 100644 > index 0000000..2459a8b > --- /dev/null > +++ b/include/odp/api/traffic_mngr.h > @@ -0,0 +1,1611 @@ > +/** Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#ifndef ODP_TRAFFIC_MNGR_H_ > +#define ODP_TRAFFIC_MNGR_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include <odp/std_types.h> > +#include <odp/packet_io.h> > + > +/** > + * @file > + * > + */ > + > +/** @defgroup odp_traffic_mngr ODP TRAFFIC MNGR > + * @{ > + * > + * An API for configuring and using Traffic Management systems > + * > + * This file forms a simple interface for creating, configuring and using > + * Traffic Management (TM) subsystems. By TM subsystem it is meant a > general > + * packet scheduling system that accepts packets from input queues and > applies > + * strict priority scheduling, weighted fair queueing scheduling and/or > + * bandwidth controls to decide which input packet should be chosen as the > + * next output packet and when this output packet can be sent onwards. > + * > + * A given platform supporting this TM API could support one or more pure > + * hardware based packet scheduling systems, one or more pure software > + * based systems or one or more hybrid systems - where because of > + * hardware constraints some of the packet scheduling is done in hardware > + * and some is done in software. In addition, there may also be > additional > + * API's beyond those described here for (a) controlling advanced > capabilities > + * supported by specific hardware, software or hybrid subsystems or (b) > + * dealing with constraints and limitations of specific implementations. > + * The intention here is to be the simplest API that covers the vast > majority > + * of packet scheduling requirements. > + * > + * Often a TM subsystem's output(s) will be directly connected > + * to a device's physical (or virtual) output interfaces/links, in which > case > + * sometimes such a system will be called an Egress Packet Scheduler or an > + * Output Link Shaper, etc.. While the TM subsystems configured by this > API > + * can be used in such a way, this API equally well supports the ability > to > + * have the TM subsystem's outputs connect to other TM subsystem input > queues > + * or general software queues or even some combination of these three > cases. > + * > + * <H2>TM Algorithms</H2> > + * > + * The packet scheduling/dropping techniques that can be applied to input > + * traffic include any mixture of the following: > + * <ol> > + * <li> Strict Priority scheduling. > + * <li> Weighted Fair Queueing scheduling (WFQ). > + * <li> Bandwidth Shaping. > + * <li> Weighted Random Early Discard (WRED). > + * </ol> > + * Note that Bandwidth Shaping is the only feature that can cause packets > + * to be "delayed", and Weighted Random Early Discard is the only feature > + * (other than input queues becoming full) that can cause packets to be > + * dropped. > + * > + * <H3>Strict Priority Scheduling</H3> > + * Strict Priority Scheduling (or just priority for short), is a technique > + * where input queues and the packets from them, are assigned a priority > + * value in the range 0 .. ODP_TM_MAX_PRIORITIES - 1. At all times > packets > + * the the smallest priority value will be chosen ahead of packets with a > + * numerically larger priority value. This is called strict priority > + * scheduling because the algorithm strictly enforces the scheduling of > + * higher priority packets over lower priority packets. > + * > + * <H3>Bandwidth Shaping</H3> > + * Bandwidth Shaping (or often just Shaping) is the term used here for the > + * idea of controlling packet rates using single rate and/or dual rate > token > + * bucket algorithms. For single rate shaping a rate (the commit rate) > and > + * a "burst size" (the maximum commit count) are configured. Then an > + * internal signed integer counter called the commitCnt is maintained such > + * that if the commitCnt is positive then packets are eligible to be sent. > + * When such a packet is actually sent then its commitCnt is decremented > + * (usually by its length, but one could decrement by 1 for each packet > + * instead). The commitCnt is then incremented periodically based upon > the > + * configured rate, so that this technique causes the traffic to be > limited > + * to the commit rate over the long term, while allowing some ability to > + * exceed this rate for a very short time (based on the burst size) in > order > + * to catch up if the traffic input temporarily drops below the commit > rate. > + * > + * Dual Rate Shaping is designed to allow certain traffic flows to fairly > + * send more than their assigned commit rate when the scheduler has > excess > + * capacity. The idea being that it may be better to allow some types of > + * traffic to send more than their committed bandwidth rather than letting > + * the TM outputs be idle. The configuration of Dual Rate Shaping > requires > + * additionally a peak rate and a peak burst size. The peak rate must be > + * greater than the related comls mit rate, but the burst sizes have no > similar > + * constraint. Also for every input priority that has Dual Rate shaping > + * enabled, there needs to be an additional equal or lower priority (equal > or > + * higher numeric priority value) assigned. Then if the traffic exceeds > its > + * commit rate but not its peak rate, the "excess" traffic will be sent at > the > + * lower priority level - which by the strict priority algorithm should > + * cause no degradation of the higher priority traffic, while allowing for > + * less idle outputs. > + * > + * <H3>Weighted Fair Queuing</H3> > + * Weighted Fair Queuing (WFQ) is used to arbitrate amongst multiple input > + * packets with the same priority. Each input can be assigned a weight in > the > + * range MIN_WFQ_WEIGHT..MAX_WFQ_WEIGHT (nominally 1..255) that affects > the way > + * the algorithm chooses the next packet. If all of the weights are equal > AND > + * all of the input packets are the same length then the algorithm is > + * equivalent to a round robin scheduling. If all of the weights are > equal > + * but the packets have different lengths then the WFQ algorithm will > attempt > + * to choose the packet such that inputs each get a fair share of the > + * bandwidth - in other words it implements a weighted round robin > algorithm > + * where the weighting is based on frame length. > + * > + * When the input weights are not all equal and the input packet lengths > vary > + * then the WFQ algorithm will schedule packets such that the packet with > + * the lowest "Virtual Finish Time" is chosen first. An input packet's > + * Virtual Finish Time is roughly calculated based on the WFQ object's > base > + * Virtual Finish Time when the packet becomes the first packet in its > queue > + * plus its frame length divided by its weight. > + * @code > + * virtualFinishTime = wfqVirtualTimeBase + (pktLength / wfqWeight) > + * @endcode > + * In a system running at full capacity with no bandwidth limits - over > the > + * long term - each input fan-in's average transmit rate will be the same > + * fraction of the output bandwidth as the fraction of its weight divided > by > + * the sum of all of the WFQ fan-in weights. Hence larger WFQ weights > result > + * in better "service" for a given fan-in. > + * @code > + * totalWfqWeight = 0; > + * for (each fan-in entity - fanIn - feeding this WFQ scheduler) > + * totalWfqWeight += fanIn->sfqWeight; > + * > + * fanIn->avgTransmitRate = avgOutputRate * fanIn->sfqWeight / > totalWfqWeight; > + * @endcode > + * > + * <H3>Weighted Random Early Discard</H3> > + * The Weighted Random Early Discard (WRED) algorithm deals with the > situation > + * where an input packet rate exceeds some output rate (including > + * the case where Bandwidth Shaping limits some output rates). Without > WRED > + * enabled and configured, the TM system will just implement a tail > dropping > + * scheme whereby whichever packet is unlucky enough to arrive when an TM > + * input queue is full will be discarded regardless of priority or any > other > + * consideration. > + * WRED allows one to configure the system to use a better/fairer > algorithm > + * than simple tail dropping. It works by measuring the "fullness" of > + * various packet queues and converting this percentage into a probability > + * of random packet dropping with the help of some configurable > parameters. > + * Then a random number is picked and together with the drop probability, > + * a decision is made to accept the packet or drop it. > + * A basic parameterization of WRED requires three parameters: > + * <ol> > + * <li> the maximum queue level (which could be either a maximum number of > + * packets or a maximum amount of memory (i.e. bytes/buffers) used), > + * <li> a starting threshold - which is a number in the range 0..100 > + * representing a percentage of the maximum queue level at which the > + * drop probability becomes non-zero, > + * <li> a drop probability - which is a number in the range 0..100 > + * representing a probability (0 means no drop and 100 means > + * certain drop) - which is used when the queue is near 100% full. > + * </ol> > + * > + * Note that all packet drops for a TM system only occur when a new packet > + * arrives at a given TM system input queue. At that time either the WRED > + * algorithm, if enabled for this input queue, or the "input queue full" > + * tail drop algorithm will make a drop/no drop decision. After this > point, > + * any packets not dropped, will at some point be sent out a TM output - > + * assuming that the topology is fully connected and enabled. > + * > + * <H2>Hierarchical Scheduling and tm_nodes</H2> > + * This API supports the ability to do Hierarchical Scheduling whereby the > + * final scheduling decision is controlled by equal priority schedulers, > + * strict priority multiplexers, bandwidth shapers - at multiple levels - > all > + * forming a tree rooted at a single egress object. In other words, all > + * tm_queues and tm_nodes have the property that their logical "output" > feeds > + * into one fan-in of a subsequent tm_node or egresss object - forming a > proper > + * tree. See the following link - > + * <A HREF="diagram1.svg">Example Tm_node</A> - for an example. > + * > + * Multi-level/hierarchical scheduling adds both great control and > significant > + * complexity. Logically, despite the implication of the tm_node tree > + * diagrams, there are no queues between the levels of hierarchy. Instead > all > + * packets are held in their input queue, until such time that the > totality of > + * all of the tm_nodes in the single path from input queue to output > object > + * agrees that this packet should be the next to be chosen to leave the TM > + * system through the output object "portal". Hence what flows from level > to > + * level is the "local choice" of what packet/tm_queue should next be > + * serviced. > + * > + * <H3>tm_nodes</H3> > + * Tm_nodes are the main "entity"/object that a TM system is composed of. > + * Each tm_node is a mini-TM subsystem of its own, but the interconnection > + * and interplay of a multi-level "tree" of tm_nodes can allow the user > + * to specify some very sophisticated behaviours. > + * Each tm_node can contain a set of scheduler (one per strict priority > level), > + * a strict priority multiplexer, a bandwidth shaper and a WRED component > - or > + * a subset of these. > + * > + * In its full generality an tm_node consists of a set of "fan-in" > connections > + * to preceding tm_queues or tm_nodes. The fan-in for a single tm_node > + * can range from 1 to many many thousands. This fan-in is divided first > + * into a WFQ scheduler per priority level. So if 4 priority levels are > + * implemented by this tm_node, there would be 4 WFQ schedulers - each > with > + * its own unique fan-in. After the WFQ schedulers a priority chooser > comes > + * next - where it will always choose the highest priority WFQ output > + * available. The output of the priority chooser then feeds a bandwidth > + * shaper function which then finally uses the shaper's propagation table > + * to determine its output packet and its priority. This output could > + * then be remapped via a priority map profile and then becomes one of the > + * input fan-in to perhaps another level of tm_nodes, and so on. > + * > + * During this process it is important to remember that the bandwidth > shaping > + * function never causes packets to be dropped. Instead all packet drops > + * occur because of tm_queue fullness or be running the WRED algorithm > + * at the time a new packet attempts to be appended to the end of some > + * input queue. > + * > + * The WRED profile associated with an tm_node considers the entire set of > + * tm_queues feeding directly or indirectly into it as its measure of > + * queue fullness. > + * > + * <H3>tm_queues</H3> > + * tm_queues are the second major type of "entity"/object that a TM > + * system is composed of. All packets MUST first enter the TM system via > + * some tm_queue. Then logically, the head packets of all of the > tm_queues > + * are examined simultaneously by the entire TM system, and ONE tm_queue > is > + * chosen send its head packet out of the TM system's egress. Abstractly > + * packets stay in the tm_queue until they are chosen at which time they > are > + * instantly transferred from tm_queue to/through the corresponding TM > egress. > + * It is also important to note that packets in the same tm_queue MUST > always > + * stay in order. In other words, the second packet in an tm_queue must > never > + * leave the TM system through a TM egress spigot before the first packet > has > + * left the system. So tm_queue packet order must always be maintained. > + * > + * <H3>TM egress</H3> > + * Note that TM egress objects are NOT referred to as queues, because in > + * many/most cases they don't have multi-packet structure but instead are > + * viewed as a port/spigot through which the TM system schedules and > finally > + * transfers input packets through. > + * > + * <H2>Ideal versus Actual Behavior</H2> > + * It is important to recognize the difference between the "abstract" > + * mathematical model of the prescribed behavior and real implementations. > + * The model describes the Ideal, but theoretically desired behavior, but > such > + * an Ideal is generally not practical to implement. Instead, one > understands > + * that virtually all Real TM systems attempt to approximate the Ideal > behavior > + * as given by the TM configuration as best as they can - while still > + * attaining high packet processing performance. The idea is that instead > of > + * trying too hard to be "perfect" at the granularity of say microseconds, > it > + * may be better to instead try to match the long term Ideal behavior over > a > + * much more reasonable period of time like a millisecond. It is > generally > + * better to have a stable implementation that when averaged over a period > of > + * several milliseconds matches the Ideal behavior very closely than to > have > + * an implementation that is perhaps more accurate over a period of > + * microseconds, but whose millisecond averaged behavior drifts away from > the > + * Ideal case. > + * > + * <H2>Other TM Concepts</H2> > + * > + * <H3>Profiles</H3> > + * This specification often packages related TM system parameters into > + * records/objects called profiles. These profiles can then be associated > with > + * various entities like tm_nodes and tm_queue's. This way the amount of > + * storage associated with setting related parameters can be reduced and > + * in addition it is common to re-use the same set of parameter set over > + * and over again, and also to be able to change the parameter set once > + * and have it affect lots of entities with which it is associated > with/applied > + * to. > + * > + * <H3>Absolute Limits versus odp_tm_capability_t</H3> > + * This header file defines some constants representing the absolute > maximum > + * settings for any TM system, though in most cases a TM system can (and > + * should) be created/instantiated with smaller values, since lower values > + * will often result in faster operation and/or less memory used. > + */ > + > +/** > + * @def ODP_TM_MAX_NUM_SYSTEMS > + * The maximum number of TM systems that may be created. On some > platforms > + * this might be much more limited to as little as one hardware TM system. > + */ > + > +/** > + * @def ODP_TM_MAX_PRIORITIES > + * The largest range of priorities that any TM system can support. All > strict > + * priority values MUST in the range 0..ODP_TM_MAX_PRIORITIES-1. > + */ > + > +/** > + * @def ODP_TM_MAX_LEVELS > + * The largest range of tm_node levels that any TM system can support. > Hence > + * all tm_node level values MUST be in the range 0..ODP_TM_MAX_LEVELS-1. > + * Smaller tm_node levels are associated with tm_nodes closer to the TM > system > + * egress. > + */ > + > +/** > + * @def ODP_TM_MIN_SCHED_WEIGHT > + * The smallest SCHED weight is 1 (i.e. 0 is not a legal WFQ/WRR value). > + */ > + > +/** > + * @def ODP_TM_MAX_SCHED_WEIGHT > + * The largest weight any TM system can support (at least from a > configuration > + * standpoint). A given TM system could have a smaller value. > + */ > + > +/** > + * @def ODP_TM_MAX_TM_QUEUES > + * The largest number of tm_queues that can handled by any one TM system. > + */ > + > +/** > + * @def ODP_TM_MAX_NUM_OUTPUTS > + * The largest number of outputs that can be configured for any one TM > system. > + */ > + > +/** > + * @def ODP_TM_MAX_NUM_TM_NODES > + * The largest number of tm_nodes that can be in existence for any one TM > + * system. > + */ > + > +/** > + * @def ODP_TM_MAX_TM_NODE_FANIN > + * The largest number of fan-in "inputs" that can be simultaneously > connected > + * to a single tm_node. > + * @todo Does this need to be as large as ODP_TM_MAX_TM_QUEUES? > + */ > + > +/** > + * @def ODP_TM_MIN_SHAPER_BW > + * The largest amound of bandwidth that any shaper's peak or commit rate > can > + * be set to. It is in units of 1000 bytes/second. > + */ > + > +/** > + * @def ODP_TM_MAX_SHAPER_BW > + * The largest amound of bandwidth that any shaper's peak or commit rate > can > + * be set to. It is in units of 1000 bytes/second. > + */ > + > +/** > + * @def ODP_NUM_SHAPER_COLORS > + * The number of enumeration values defined in the odp_tm_shaper_color_t > type. > + */ > + > +/** > + * @def ODP_TM_INVALID_PRIORITY > + * Used to indicate an invalid priority value. > + */ > + > +/** > + * @typedef odp_tm_percent_t > + * Is used when specifying fields that are percentages. It is a fixed > point > + * integer whose units are 1/100 of a percent. Hence 100% is represented > as > + * the integer value 10000. Note that because it is often used as a ratio > of > + * the current queue value and maximum queue threshold, it can be > 100%, > but > + * in any event will never be larger than 500% (i.e. it MUST be capped at > + * 50000). > + */ > + > +/** > + * @typedef odp_tm_t > + * Each odp_tm_t value represents a specific TM system. Almost all > functions > + * in this API require a odp_tm_t value - either directly as a function > + * parameter or indirectly by having another ODP TM handle value as a > function > + * parameter. > + */ > + > +/** > + * @typedef odp_tm_queue_t > + * Each odp_tm_queue_t value is an opaque ODP handle representing a > specific > + * tm_queue within a specific TM system. > + */ > + > +/** > + * @typedef odp_tm_node_t > + * Each odp_tm_queue_t value is an opaque ODP handle representing a > specific > + * tm node within a specific TM system. > + */ > + > +/** > + * @typedef odp_tm_shaper_t > + * Each odp_tm_shaper_t value is an opaque ODP handle representing a > specific > + * shaper profile usable across all TM systems described by this API. A > given > + * shaper profile can then be attached to any tm_queue or tm_node. > + */ > + > +/** > + * @typedef odp_tm_sched_t > + * Each odp_tm_sched_t value is an opaque ODP handle representing a > specific > + * tm_node scheduler profile usable across all TM systems described by > this > + * API. A given tm_node scheduler profile can then be attached to any > + * tm_node. > + */ > + > +/** > + * @typedef odp_tm_threshold_t > + * Each odp_tm_threshold_t value is an opaque ODP handle representing a > + * specific queue threshold profile usable across all TM systems described > by > + * this API. A given queue threshold profile can then be attached to any > + * tm_queue or tm_node. > + */ > + > +/** > + * @typedef odp_tm_wred_t > + * Each odp_tm_wred_t value is an opaque ODP handle representing a > specific > + * WRED profile usable across all TM systems described by this API. A > given > + * WRED profile can then be attached to any tm_queue or tm_node. > + */ > + > +/** > + * @def ODP_TM_INVALID > + * Constant that can be used with any ODP TM handle type and indicates > that > + * this value does NOT represent a valid TM object. > + */ > + > +/** > + * @def ODP_TM_ROOT > + * Constant that is used to refer to the egress/root node of the TM > subsystem's > + * tree/hierarchy of nodes. > + */ > + > +/** The odp_tm_capability_t type is used to describe the feature set and > limits > + * of a TM system. It is passed to the odp_tm_create() function > indirectly > + * by being part of the odp_tm_params_t record. > + */ > +typedef struct { > + /** max_tm_queues specifies the maximum number of tm_queues that > can > + * be in existence for this TM System. > + */ > + uint32_t max_tm_queues; > + > + /** max_fanin_per_level specifies the maximum number of fan_in link > + * to any given scheduler (whether weighted or using fair queueing or > + * round robin) belonging to tm_nodes at the given level. > + */ > + uint32_t max_fanin_per_level[ODP_TM_MAX_LEVELS]; > + > + /** max_priority specifies the maximum number of strict priority > + * levels used by any tm_queue or tm_node. Note that any given > + * tm_queue or tm_node can use a subset of these levels. max_priority > + * must be in the range 0..ODP_TM_MAX_PRIORITIES - 1. Note that lower > + * numeric values represent higher (more important or time critical) > + * priorities. > + */ > + uint8_t max_priority; > + > + /** max_levels specifies that maximum number of levels of > hierarchical > + * scheduling allowed by this TM System. This is a count of the > + * tm_node stages and does not include tm_queues or tm_egress objects. > + * Hence any given tm_node will have associated tm_node_level in the > + * range 0 to max_levels - 1, where tm_node's at level 0 output's only > + * go to egress objects and tm_nodes whose level is max_levels - 1 > + * have their fan_in only from tm_queues. > + */ > + uint8_t max_levels; > + > + /** tm_queue_shaper_supported indicates that the tm_queues support > + * proper TM shaping. Note that TM Shaping is NOT the same thing as > + * Ingress Metering/Policing as specified by RFC 2697 (A Single Rate > + * Three Color Marker) or RFC 2698 (A Two Rate Three Color Marker). > + * These RFC's can be used for a Diffserv traffic conditioner, or > + * other ingress policing. They make no mention of and have no > + * algorithms for delaying packets - which is what TM shapers are > + * expected to do. > + */ > + odp_bool_t tm_queue_shaper_supported; > + > + /** tm_node_shaper_supported indicates that the tm_nodes (at least > for > + * some hierarchical levels) support proper T < M shaping. > + */ > + odp_bool_t tm_node_shaper_supported; > + > + /** red_supported indicates that the tm_queues support some form of > + * Random Early Discard. > + */ > + odp_bool_t red_supported; > + > + /** hierarchical_red_supported indicates that this TM system > supports > + * some form of RED where the queue fullness of tm_nodes contributes > + * to the overall RED DROP/NO-DROP decision. > + */ > + odp_bool_t hierarchical_red_supported; > + > + /** weights_supported indicates that the tm_node schedulers (at > least > + * for some hierarchical levels) can have their different weights for > + * their fan-ins. > + */ > + odp_bool_t weights_supported; > + > + /** fair_queuing_supported indicates the the tm_node schedulers (at > + * least for some hierarchical levels) can implement WFQ or FQ > + * scheduling disciplines, otherwise these schedulers can only > + * implement WRR or RR algorithms, > + */ > + odp_bool_t fair_queuing_supported; > +} odp_tm_capability_t; > + > +/** The odp_tm_egress_fcn_t type defines the parameter profile of the > egress > + * function callback. Using an egress function callback is just one of > several > + * ways of getting packets out from an egress spigot. > + * > + */ > +typedef void (*odp_tm_egress_fcn_t) (odp_packet_t odp_pkt); > + > +/** The tm_egress_kind_e enumeration type is used to indicate the kind of > + * egress object ("spigot") associated with this TM system. Most of these > + * kinds are optional - with ODP_TM_EGRESS_PKT_IO being the only mandatory > + * kind. The TM_EGRESS_FN - if implemented - is useful for testing the TM > + * subsystem, and users are warned that its performance might be limited. > + */ > +typedef enum { > + ODP_TM_EGRESS_PKT_IO, > + ODP_TM_EGRESS_FN, > +} odp_tm_egress_kind_t; > + > +/** The odp_tm_egress_t type is used to describe that type of "egress > spigot" > + * associated with this TM system. It is passed to the odp_tm_create() > + * function indirectly by being part of the odp_tm_params_t record. > + */ > +typedef struct { > + odp_tm_egress_kind_t egress_kind; /**< Union discriminator */ > + > + union { > + odp_pktio_t pktio; > + odp_tm_egress_fcn_t egress_fcn; > + }; > +} odp_tm_egress_t; > + > +/** The odp_tm_params_t record type is used to hold extra parameters when > + * calling the odp_tm_create() function. > + * Since it is expected that implementations might augment this record > type > + * with platform specific additional fields - it is required that > + * odp_tm_params_init() be called on variables of this type before any of > the > + * fields are filled in. > + */ > +typedef struct { > + odp_tm_capability_t capability; /**< capability record */ > + odp_tm_egress_t egress; /**< describes the egress "spigot" */ > +} odp_tm_params_t; > + > +/** odp_tm_capability_init() must be called to initialize any > + * odp_tm_capability_t record before it is first used or assigned to. > + * > + * @param[in] capability A pointer to an odp_tm_capability_t record which > + * is to be initialized. > + */ > +void odp_tm_capability_init(odp_tm_capability_t *capability); > + > +/** odp_tm_params_init() must be called to initialize any > + * odp_tm_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_params_t record which > + * is to be initialized. > + */ > +void odp_tm_params_init(odp_tm_params_t *params); > + > +/** Create/instantiate a TM Packet Scheduling system. > + * > + * @param[in] name The name to be assigned to this TM system. Cannot > be > + * NULL, and also must be unique amongst all other TM > system > + * names. > + * @param[in] params The params to be used when creating this TM system. > + * @return Returns ODP_TM_INVALID upon failure, otherwise the > newly > + * created TM system's odp_tm_t handle is returned. > + */ > +odp_tm_t odp_tm_create(const char *name, odp_tm_params_t *params); > + > +/** Find a pre-existing TM Packet Scheduling system. This function can be > + * used either to find a TM system created previously with odp_tm_create > OR > + * get the odp_tm_t of a built-in TM system - usually based on HW. In this > + * later case the format of the name used to refer to a specific built-in > + * hardware TM system may be platform dependent, but in any case a name of > + * "HW_TM_%u" where the number starts at 1, can be used to find a built-in > + * system independently of the best capability match. If name is NULL > then > + * the existing (built-in or created by odp_tm_create) TM system that best > + * matches capability is returned. > + * > + * @param[in] name If NULL then only uses the capability parameter > to > + * find a closest match, otherwise if the name is > + * matched by an existing TM system it is returned. > + * @param[in] capability Used when the name is NULL (in which > + * case the closest match is returned) or when the > + * name is not-NULL, but doesn't match > + * any existing TM system in which case the > + * capability is used to find the FIRST > + * TM system matching exactly these limits. > + * @return If an existing TM system (built-in or previously > + * created via odp_tm_create) is found, its > + * odp_tm_t value is returned, otherwise > + * ODP_TM_INVALID is returned. > + */ > +odp_tm_t odp_tm_find(const char *name, odp_tm_capability_t *capability); > + > +/** odp_tm_capability() can be used to query the actual limits of a given > TM > + * system. This function can be used for both built-in TM systems AND TM > + * system's created via odp_tm_create(). > + * > + * @param[in] odp_tm The odp_tm_t value of the TM system to be > + * queried. > + * @param[out] capability A pointer to a odp_tm_capability_t record > + * where the actual limits used by the TM system > are > + * copied into. Note that these limits do NOT > + * have to match the capability passed in if > + * a TM system was created by odp_tm_create, > + * but of course these limits in some cases could > + * be larger. > + * @return Returns 0 upon success, < 0 upon failure (which > + * indicates that the odp_tm value did not > + * exist). > + */ > +int odp_tm_capability(odp_tm_t odp_tm, odp_tm_capability_t *capability); > + > +/** odp_tm_destroy() may be used to destroy TM systems created via > + * odp_tm_create(). It generally CANNOT be used to destroy built-in TM > + * systems. Also some platforms MAY not support destroying of TM systems > + * created via odp_tm_create() under certain conditions. For example a > given > + * platform may require that the TM system be first "drained" of all of > its > + * queued packets before it will accept a odp_tm_destroy() call. > + * > + * In general calling odp_tm_destroy() on an active TM system does not > + * guarantee anything about the disposition of any packets queued within > the > + * TM system, other than EVENTUALLY these packets will be either sent (in > ANY > + * order) or freed. > + * > + * @param[in] odp_tm The odp_tm_t value of the TM system to be destroyed > (and > + * hence destroyed (and hence freed). > + * @return 0 upon success, < 0 upon failure. > + */ > +int odp_tm_destroy(odp_tm_t odp_tm); > + > +/** Shaper profile types and functions */ > + > +/** Possible values of running the shaper algorithm. ODP_TM_SHAPER_GREEN > + * means that the traffic is within the commit specification (rate and > burst > + * size), ODP_TM_SHAPER_YELLOW means that the traffic is within the peak > + * specification (rate and burst size) and ODP_TM_SHAPER_RED means that > the > + * traffic is exceeding both its commit and peak specifications. Note > that > + * packets can also have an assigned <b> packet color</b> of > ODP_PACKET_GREEN, > + * ODP_PACKET_YELLOW or ODP_PACKET_RED which has a different meaning and > + * purpose than the shaper colors. > + */ > +typedef enum { > + ODP_TM_SHAPER_GREEN, ODP_TM_SHAPER_YELLOW, ODP_TM_SHAPER_RED > +} odp_tm_shaper_color_t; > + > +/** The odp_tm_shaper_params_t record type is used to supply the > parameters > + * associated with a shaper profile. Since it is expected that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_shaper_params_init() be > + * called on variables of this type before any of the fields are filled > in. > + */ > +typedef struct { > + /** The committed information rate for this shaper profile. The > units > + * for this integer are always in bits per second. > + */ > + uint64_t commit_bps; > + > + /** The peak information rate for this shaper profile. The units > for > + * this integer are always in bits per second. > + */ > + uint64_t peak_bps; > + > + /** The commit burst tolerance for this shaper profile. The units > for > + * this field are always bits. This value sets an upper limit for the > + * size of the commitCnt. > + */ > + uint32_t commit_burst; > + > + /** The peak burst tolerance for this shaper profile. The units > for > + * this field are always bits. This value sets an upper limit for the > + * size of the peakCnt. > + */ > + uint32_t peak_burst; > + > + /** The shaper_len_adjust is a value between -128 and 127 which is > + * directly added to the frame_len of a packet associated with this > + * profile. The frame_len would normally include the outermost > + * Ethernet header (DA, SA, ...) through to the outermost Ethernet CRC > + * inclusive. Hence this field - when non-zero - will usually be set > + * to a value approximating the "time" (in units of bytes) taken by > + * the Ethernet preamble and Inter Frame Gap. Traditionally this > + * would be the value 20 (8 + 12), but in same cases can be as low as > + * 9 (4 + 5). > + */ > + int8_t shaper_len_adjust; > + > + /** If dual_rate is TRUE it indicates the desire for the > + * implementation to use dual rate shaping for packets associated with > + * this profile. The precise semantics of dual rate shaping are > + * implementation specific, but in any case require a non-zero set of > + * both commit and peak parameters. > + */ > + odp_bool_t dual_rate; > +} odp_tm_shaper_params_t; > + > +/** odp_tm_shaper_params_init() must be called to initialize any > + * odp_tm_shaper_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_shaper_params_t record which > + * is to be initialized. > + */ > +void odp_tm_shaper_params_init(odp_tm_shaper_params_t *params); > + > +/** odp_tm_shaper_create() creates a shaper profile object, which can > + * subsequently be attached to any number (including zero) of tm_queues > + * or tm_nodes. > + * > + * @param[in] name Optional name associated with this shaper profile. > Can > + * be NULL. If non-NULL must be unique amongst the set > of > + * all other shaper profiles. > + * @param[in] params The profile parameters. See comments associated > with > + * the odp_tm_shaper_params_t for more details. > + * @return Returns ODP_TM_INVALID upon failure, or the newly > + * allocated odp_tm_shaper_t value representing this > + * profile object. > + */ > +odp_tm_shaper_t odp_tm_shaper_create(const char *name, > + odp_tm_shaper_params_t *params); > + > +/** odp_tm_shaper_params_read() "gets" the current set of values > associated > + * with the specified shaper profile object, and copies them into the > supplied > + * record. > + * > + * @param[in] shaper_profile Specifies the shaper profile object whose > + * values are to be read. > + * @param[out] params A pointer to an odp_tm_shaper_params_t > record > + * where the current shaper profile object > values > + * are copied to. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_shaper_params_read(odp_tm_shaper_t shaper_profile, > + odp_tm_shaper_params_t *params); > + > +/** odp_tm_shaper_params_update() "sets" the current set of values > associated > + * with the specified shaper profile object. In addition, this call has > the > + * effect that all tm_input's and tm_nodes that are associated (attached?) > + * with this shaper profile object will be updated with the new values. > + * > + * @param[in] shaper_profile Specifies the shaper profile object whose > + * values are to be set. > + * @param[in] params A pointer to an odp_tm_shaper_params_t > record > + * where the new shaper profile object values > + * are taken from. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_shaper_params_update(odp_tm_shaper_t shaper_profile, > + odp_tm_shaper_params_t *params); > + > +/** odp_tm_shaper_lookup() can be used to find the shaper profile object > + * created with the specified name. > + * > + * @param[in] name Name of a previously created shaper profile. Cannot > be > + * NULL. > + * @return Returns ODP_TM_INVALID upon failure, or the shaper > + * profile handle created with this name. > + */ > +odp_tm_shaper_t odp_tm_shaper_lookup(const char *name); > + > +/** Scheduler Profiles - types and functions */ > + > +/** The odp_tm_sched_mode_t type is used to control whether a tm_node > + * scheduler takes into account packet lengths (by setting the sched_mode > to > + * ODP_TM_BYTE_BASED_WEIGHTS) or instead treat packets with different > lengths > + * the same (by setting the sched_mode to ODP_TM_FRAME_BASED_WEIGHTS). > + * Normally the sched_mode will be set to ODP_TM_BYTE_BASED_WEIGHTS, > otherwise > + * the scheduler becomes a weighted round robin scheduler. > + */ > +typedef enum { > + ODP_TM_BYTE_BASED_WEIGHTS, /**< Use the packet length in > + scheduler algorithm */ > + ODP_TM_FRAME_BASED_WEIGHTS /**< Ignore the packet length */ > +} odp_tm_sched_mode_t; > + > +/** The odp_tm_sched_params_t record type is used to supply the parameters > + * associated with a scheduler profile. Since it is expected that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_sched_params_init() be > + * called on variables of this type before any of the fields are filled > in. > + */ > +typedef struct { > + /** sched_modes indicates whether weighted scheduling should be > used > + * or not - on a priority basis. > + */ > + odp_tm_sched_mode_t sched_modes[ODP_TM_MAX_PRIORITIES]; > + > + /** In the case that sched_modes for a given strict priority level > + * indicates the use of weighted scheduling, this field supplies the > + * weighting factors. The weights - when defined - are used such that > + * the (adjusted) frame lengths are divided by these 8-bit weights > + * (i.e. they are divisors and not multipliers). Consequently a > + * weight of 0 (when sched_mode is ODP_TM_BYTE_BASED_WEIGHTS) is > + * illegal. > + */ > + uint8_t sched_weights[ODP_TM_MAX_PRIORITIES]; > +} odp_tm_sched_params_t; > + > +/** odp_tm_sched_params_init() must be called to initialize any > + * odp_tm_sched_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_sched_params_t record which > + * is to be initialized. > + */ > +void odp_tm_sched_params_init(odp_tm_sched_params_t *params); > + > +/** odp_tm_sched_create() creates a scheduler profile object, which can > + * subsequently be attached to any number (including zero) of tm_nodes. > + * > + * @param[in] name Optional name associated with this scheduler > profile. > + * Can be NULL. If non-NULL must be unique amongst the > + * set of all other scheduler profiles. > + * @param[in] params The profile parameters. See comments associated > with > + * the odp_tm_sched_params_t for more details. > + * @return Returns ODP_TM_INVALID upon failure, or the newly > + * allocated odp_tm_sched_t value representing this > profile > + * object. > + */ > +odp_tm_sched_t odp_tm_sched_create(const char *name, > + odp_tm_sched_params_t *params); > + > +/** odp_tm_sched_params_read() "gets" the current set of values associated > + * with the specified scheduler profile object, and copies them into the > + * supplied record. > + * > + * @param[in] sched_profile Specifies the scheduler profile whose values > + * are to be read. > + * @param[out] params A pointer to an odp_tm_sched_params_t record > + * where the current scheduler profile object > + * values are copied to. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_sched_params_read(odp_tm_sched_t sched_profile, > + odp_tm_sched_params_t *params); > + > +/** odp_tm_sched_params_update() "sets" the current set of values > associated > + * with the specified scheduler profile object. In addition, this call > has > + * the effect that all tm_nodes that are associated (attached?) with this > + * Scheduler profile object will be updated with the new values. > + * > + * @param[in] sched_profile Specifies the Scheduler profile object whose > + * values are to be set. > + * @param[in] params A pointer to an odp_tm_sched_params_t record > + * where the new scheduler profile object > values > + * are taken from. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_sched_params_update(odp_tm_sched_t sched_profile, > + odp_tm_sched_params_t *params); > + > +/** odp_tm_sched_lookup() can be used to find the scheduler profile object > + * created with the specified name. > + * > + * @param[in] name Name of a previously created scheduler profile. > Cannot be > + * NULL. > + * @return Returns ODP_TM_INVALID upon failure, or the scheduler > + * profile handle created with this name. > + */ > +odp_tm_sched_t odp_tm_sched_lookup(const char *name); > + > +/** Queue Threshold Profiles - types and functions */ > + > +/** The odp_tm_threshold_params_t record type is used to supply the > parameters > + * associated with a queue thresholds profile. Since it is expected that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_threshold_params_init() > be > + * called on variables of this type before any of the fields are filled in > + */ > +typedef struct { > + uint64_t max_pkts; /**< max pkt cnt for this threshold profile */ > + uint64_t max_bytes; /**< max byte cnt for this threshold profile */ > + odp_bool_t enable_max_pkts; /**< TRUE if max_pkts is valid */ > + odp_bool_t enable_max_bytes; /**< TRUE if max_bytes is valid */ > +} odp_tm_threshold_params_t; > + > +/** odp_tm_threshold_params_init() must be called to initialize any > + * odp_tm_threshold_params_t record before it is first used or assigned > to. > + * > + * @param[in] params A pointer to an odp_tm_threshold_params_t record > which > + * is to be initialized. > + */ > +void odp_tm_threshold_params_init(odp_tm_threshold_params_t *params); > + > +/** odp_tm_threshold_create() creates a queue threshold profile object, > which > + * can subsequently be attached to any number (including zero) of > tm_queues or > + * tm_nodes. > + * > + * @param[in] name Optional name associated with this queue threshold > + * profile. Can be NULL. If non-NULL must be unique > + * amongst the set of all other queue threshold > profiles. > + * @param[in] params The profile parameters. See comments associated > with > + * the odp_tm_threshold_params_t for more details. > + * @return Returns ODP_TM_INVALID upon failure, or the newly > + * allocated odp_tm_threshold_t value representing this > + * profile object. > + */ > +odp_tm_threshold_t odp_tm_threshold_create(const char *name, > + odp_tm_threshold_params_t *params); > + > +/** odp_tm_thresholds_params_read() "gets" the current set of values > associated > + * with the specified queue thresholds profile object, and copies them > into the > + * supplied record. > + * > + * @param[in] threshold_profile Specifies the queue thresholds profile > + * object whose values are to be read. > + * @param[out] params A pointer to an > odp_tm_threshold_params_t > + * record where the current queue > thresholds > + * profile object values are copied to. > + * @return Returns < 0 upon failure or 0 upon > success. > + */ > +int odp_tm_thresholds_params_read(odp_tm_threshold_t threshold_profile, > + odp_tm_threshold_params_t *params); > + > +/** odp_tm_thresholds_params_update() "sets" the current set of values > + * associated with the specified queue thresholds profile object. In > addition, > + * this call has the effect that all tm_input's and tm_nodes that are > + * associated (attached?) with this queue thresholds profile object will > be > + * updated with the new values. > + * > + * @param[in] threshold_profile Specifies the queue thresholds profile > + * object whose values are to be set. > + * @param[in] params A pointer to an odp_tm_threshold_params_t > + * record where the current queue thresholds > + * profile object values are taken from. > + * @return Returns < 0 upon failure or 0 upon > success. > + */ > +int odp_tm_thresholds_params_update(odp_tm_threshold_t threshold_profile, > + odp_tm_threshold_params_t *params); > + > +/** odp_tm_thresholds_lookup() can be used to find the queue thresholds > + * profile object created with the specified name. > + * > + * @param[in] name Name of a previously created queue thresholds profile. > + * Cannot be NULL. > + * @return Returns ODP_TM_INVALID upon failure, or the queue > + * thresholds profile handle created with this name. > + */ > +odp_tm_threshold_t odp_tm_thresholds_lookup(const char *name); > + > +/** WRED Profiles - types and functions */ > + > +/** The odp_tm_wred_params_t record type is used to supply the parameters > + * associated with a Random Early Discard profile. Since it is expected > that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_wred_params_init() be > called > + * on variables of this type before any of the fields are filled in. > + */ > +typedef struct { > + /** When min_threshold is set to zero then single-slope WRED is > + * enabled, as described in the description of med_threshold. > + * Otherwise dual-slope WRED is enabled whereby the behavior depends > + * on which of the following three cases exists: > + * <ol> <li> queue > + * fullness < min_threshold. In this case the drop probability is > + * zero. > + * <li> min_threshold <= queue fullness < med_threshold. In > + * this case the drop probability increases linearly from zero until > + * it reaches med_drop_prob at a queue fullness equal to > + * med_threshold. > + * <li> med_threshold <= queue fullness. In this case > + * the drop probability increases linearly from med_drop_prob when the > + * queue fullness equals med_threshold until it reaches 100% with a > + * drop probability of max_drop_prob. </ol> > + */ > + odp_tm_percent_t min_threshold; > + > + /** The meaning of med_threshold depends upon whether single-slope > or > + * dual-slope WRED is being used or not. When min_threshold is 0 then > + * single-slope WRED is enabled in which case the med_threshold value > + * represents (as a percentage of max queue fullness) the point at > + * which the drop probability starts increasing linearly from 0 until > + * it becomes equal to max_drop_prob when the queue fullness reaches > + * 100%. See min_threshold comments for the case of dual-slope WRED. > + */ > + odp_tm_percent_t med_threshold; > + > + /** The med_drop_prob is only used when dual-slope WRED is being > used, > + * in which case med_drop_prob MUST be < max_drop_prob. See > + * min_threshold comments for more details. > + */ > + odp_tm_percent_t med_drop_prob; > + > + /** The max_drop_prob equals the drop probability when the queue > + * fullness almost equals 100%. Of course once the queue fullness is > + * >= 100% of the max queue fullness, the drop probability > + * discontinuously becomes 100%. > + */ > + odp_tm_percent_t max_drop_prob; > + > + /** When enable_wred is false, all tm_queues and tm_nodes that are > + * attached to this profile will not take part in a Random Early > + * Discard algorithm. > + */ > + odp_bool_t enable_wred; > + > + /** When use_byte_fullness is true then WRED will use queue memory > + * usage as the fullness criterion, otherwise when use_byte_fullness > + * is false, WRED will use the queue length (i.e. the number of > + * packets in the queue) as the fullness criterion. Often will be set > + * to true for WRED profiles applied to tm_queues and set to false for > + * WRED profiles applied to tm_nodes. > + */ > + odp_bool_t use_byte_fullness; > +} odp_tm_wred_params_t; > + > +/** odp_tm_wred_params_init() must be called to initialize any > + * odp_tm_wred_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_wred_params_t record which > + * is to be initialized. > + */ > +void odp_tm_wred_params_init(odp_tm_wred_params_t *params); > + > +/** odp_tm_wred_create() creates a WRED (Weighted Random Early Discard) > + * profile object, which can subsequently be attached to any number > (including > + * zero) of tm_queues or tm_nodes. > + * > + * @param[in] name Optional name associated with this WRED profile. > Can > + * be NULL. If non-NULL must be unique amongst the set > of > + * all other WRED profiles. > + * @param[in] params The profile parameters. See comments associated > with the > + * odp_tm_wred_params_t for more details. > + * @return Returns ODP_TM_INVALID upon failure, or the newly > + * allocated odp_tm_wred_t value representing this > profile > + * object. > + */ > +odp_tm_wred_t odp_tm_wred_create(const char *name, > + odp_tm_wred_params_t *params); > + > +/** odp_tm_wred_params_read() "gets" the current set of values associated > + * with the specified WRED profile object, and copies them into the > supplied > + * record. > + * > + * @param[in] wred_profile Specifies the WRED profile object whose > + * values are to be read. > + * @param[out] params A pointer to an odp_tm_wred_params_t record > + * where the current WRED profile object values > + * are copied to. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_wred_params_read(odp_tm_wred_t wred_profile, > + odp_tm_wred_params_t *params); > + > +/** odp_tm_wred_params_update() "sets" the current set of values > associated > + * with the specified WRED profile object. In addition, this call has the > + * effect that all tm_input's and tm_nodes that are associated (attached?) > + * with this WRED profile object will be updated with the new values. > + * > + * @param[in] wred_profile Specifies the WRED profile object whose > + * values are to be set. > + * @param[in] params A pointer to an odp_tm_wred_params_t record > + * where the new WRED profile object values > + * are taken from. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_wred_params_update(odp_tm_wred_t wred_profile, > + odp_tm_wred_params_t *params); > + > +/** odp_tm_wred_lookup() can be used to find the WRED profile object > created > + * with the specified name. > + * > + * @param[in] name Name of a previously created WRED profile. Cannot be > + * NULL. > + * @return Returns ODP_TM_INVALID upon failure, or the WRED > + * profile handle created with this name. > + */ > +odp_tm_wred_t odp_tm_wred_lookup(const char *name); > + > +/** The odp_tm_node_params_t record type is used to hold extra parameters > when > + * calling the odp_tm_node_create() function. Many of these fields are > + * optional EXCEPT for max_fanin and level. Also since it is expected > that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_node_params_init() be > called > + * on variables of this type before any of the fields are filled in. > + */ > +typedef struct { > + /** The max_fan_in sets tha maximum number of src tm_queues and > + * producer tm_nodes that can be simultaneously be connected to this > + * tm_node as their destination. > + */ > + uint32_t max_fanin; > + > + /**> @todo uint8_t num_priorities; ? */ > + > + /** The shaper profile to be associated with this tm_node. Can be > + * ODP_TM_INVALID and can also be set and changed post-creation via > + * odp_tm_node_shaper_config(); > + */ > + odp_tm_shaper_t shaper_profile; > + > + /** The threshold profile to be used in setting the max queue > fullness > + * for WRED and/or tail drop? Can be ODP_TM_INVALID and can also be > + * set and changed post-creation via odp_tm_node_threshold_config(). > + */ > + odp_tm_threshold_t threshold_profile; > + > + /** The WRED profile(s) to be associated with this tm_node. Any or > + * all array elements can be ODP_TM_INVALID and can also be set and > + * changed post-creation via odp_tm_node_wred_config(). > + */ > + odp_tm_wred_t wred_profile[ODP_NUM_PACKET_COLORS]; > + > + /** The level (or tm_node stage) sets the level for this tm_node It > + * must be in range 0..max_levels-1. Note that the tm_node topology > + * is constrained such that only tm_node outputs with numerically > + * greater levels may be connected to the fan-in of tm_node's with > + * numerically smaller levels. > + */ > + uint8_t level; > +} odp_tm_node_params_t; > + > +/** odp_tm_node_params_init() must be called to initialize any > + * odp_tm_node_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_node_params_t record which > + * is to be initialized. > + */ > +void odp_tm_node_params_init(odp_tm_node_params_t *params); > + > +/** Create an tm_node with a specific set of implemented strict priority > + * levels as given by the priorities array parameter. The set of priority > + * levels does not have to "contiguous", but the "priorities" values for > all > + * indexes > max_priority MUST be FALSE. Note that the set of implemented > + * strict priority levels for an tm_node cannot be changed after tm_node > + * creation. The level parameter MUST be in the range 0..max_level - 1. > + * > + * @param[in] odp_tm Odp_tm is used to identify the TM system into which > this > + * odp_tm_node object is created. > + * @param[in] name Optional name that can be used later later to find > this > + * same odp_tm_node_t. Can be NULL, otherwise must be > + * unique across all odp_tm_node objects. > + * @param[in] params A pointer to a record holding (an extensible) set of > + * properties/attributes of this tm_node. > + * @return Returns ODP_TM_INVALID upon failure, otherwise > returns > + * a valid odp_tm_node_t handleif successful. > + */ > +odp_tm_node_t odp_tm_node_create(odp_tm_t odp_tm, const char *name, > + odp_tm_node_params_t *params); > + > +/** The odp_tm_node_shaper_config() function is used to dynamically set or > + * change the shaper profile associated with this tm_node. > + * > + * @param[in] tm_node Specifies the tm_node to be changed. > + * @param[in] shaper_profile Specifies the shaper profile that should > + * now be used for the shaper entity within the > + * given tm_node. Note that it is legal to > specify > + * ODP_TM_INVALID indicating that this tm_node > + * no longer implements a shaper function. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_node_shaper_config(odp_tm_node_t tm_node, > + odp_tm_shaper_t shaper_profile); > + > +/** The odp_tm_node_sched_config() function is used to dynamically set or > + * change the scheduler profile associated with a tm_node. > + * > + * @param[in] tm_node Specifies the tm_node to be changed. > + * @param[in] tm_fan_in_node Specifies which of the specified tm_node's > + * fan-in's weights etc are to be changed. The > + * fan-in is indentified by the > "producer"/parent > + * tm_node actually connected to this fan-in. > + * @param[in] sched_profile Specifies the scheduler profile that should > + * now be used for the WFQ/RR entity within the > + * given tm_node. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_node_sched_config(odp_tm_node_t tm_node, > + odp_tm_node_t tm_fan_in_node, > + odp_tm_sched_t sched_profile); > + > +/** The odp_tm_node_threshold_config() function is used to dynamically set > or > + * change the queue threshold profile associated with this tm_node. > + * > + * @param[in] tm_node Specifies the tm_node to be changed. > + * @param[in] thresholds_profile Specifies the queue threshold profile > that > + * should now be used for the given > tm_node. > + * @return Returns 0 upon success and < 0 upon > failure. > + */ > +int odp_tm_node_threshold_config(odp_tm_node_t tm_node, > + odp_tm_threshold_t thresholds_profile); > + > +/** The odp_tm_node_wred_config() function is used to dynamically set or > + * change the WRED profile associated with this tm_node or > tm_node/pkt_color > + * combination. > + * > + * @param[in] tm_node Specifies the tm_node to be changed. > + * @param[in] pkt_color Specifies the pkt_color that this profile is > to be > + * used with. Can also be the special value > + * ALL_PKT_COLORS. > + * @param[in] wred_profile Specifies the WRED profile that should now be > used > + * by this tm_queue, when processing pkts of this > + * pkt_color. It can be the value ODP_TM_INVALID > + * indicating that this tm_queue/pkt_color > combination > + * no longer implements WRED. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_node_wred_config(odp_tm_node_t tm_node, > + odp_packet_color_t pkt_color, > + odp_tm_wred_t wred_profile); > + > +/** odp_tm_node_lookup() can be used to find the tm_node object created > with > + * the specified name. > + * > + * @param[in] odp_tm Odp_tm is used to identify the TM system into which > this > + * odp_tm_node object is created. > + * @param[in] name Name of a previously created tm_node. Cannot be > + * NULL. > + * @return Returns ODP_TM_INVALID upon failure, or the tm_node > + * handle created with this name. > + */ > +odp_tm_node_t odp_tm_node_lookup(odp_tm_t odp_tm, const char *name); > + > +/** The odp_tm_queue_params_t record type is used to hold extra parameters > + * when calling the odp_tm_queue_create() function. Many of these fields > are > + * optional EXCEPT for priority. Also since it is expected that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_queue_params_init() be > + * called on variables of this type before any of the fields are filled > in. > + */ > +typedef struct { > + /** The shaper profile to be associated with this tm_queue. Can be > + * ODP_TM_INVALID and can also be set and changed post-creation via > + * odp_tm_queue_shaper_config(); > + */ > + odp_tm_shaper_t shaper_profile; > + > + /** The threshold profile to be used in setting the max queue > fullness > + * for WRED and/or tail drop? Can be ODP_TM_INVALID and can also be > + * set and changed post-creation via odp_tm_queue_threshold_config(). > + */ > + odp_tm_threshold_t threshold_profile; > + > + /** The WRED profile(s) to be associated with this tm_queue. Any > or > + * all array elements can be ODP_TM_INVALID and can also be set and > + * changed post-creation via odp_tm_queue_wred_config(). > + */ > + odp_tm_wred_t wred_profile[ODP_NUM_PACKET_COLORS]; > + > + /** The strict priority level assigned to packets in this tm_queue > - > + * in other words all packets associated with a given tm_queue MUST > + * have the same single strict priority level and this level must be > + * in the range 0..max_priority. > + */ > + uint8_t priority; > +} odp_tm_queue_params_t; > + > +/** odp_tm_queue_params_init() must be called to initialize any > + * odp_tm_queue_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_queue_params_t record which > + * is to be initialized. > + */ > +void odp_tm_queue_params_init(odp_tm_queue_params_t *params); > + > +/** Create an tm_queue object. One can specify the maximum queue limits > + * either as a maximum number of packets in the queue OR as a maximum > number > + * of bytes in the queue, or if both are specified, then whichever limit > is > + * hit first. Note that in the case of specifying the maximum queue > memory > + * size as bytes, the system is free to instead convert this byte value > into a > + * number of buffers and instead limit the queue memory usage by buffer > counts > + * versus strictly using byte counts. > + * > + * @param[in] odp_tm Odp_tm is used to identify the TM system into which > this > + * odp_tm_queue object is created. > + * @param[in] params A pointer to a record holding (an extensible) set of > + * properties/attributes of this tm_queue. > + * @return Returns ODP_TM_INVALID upon failure, otherwise a > valid > + * odp_tm_queue_t handle. > + */ > +odp_tm_queue_t odp_tm_queue_create(odp_tm_t odp_tm, > + odp_tm_queue_params_t *params); > + > +/** The odp_tm_queue_shaper_config() function is used to dynamically set > + * or change the shaper profile associated with this tm_queue. > + * > + * @param[in] tm_queue Specifies the tm_queue to be changed. > + * @param[in] shaper_profile Specifies the shaper profile that should now > be > + * used for shaping the tm_queue's packet > stream. > + * Note that it is legal to specify > ODP_TM_INVALID > + * indicating that this tm_queue no longer > + * implements a shaper function. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_queue_shaper_config(odp_tm_queue_t tm_queue, > + odp_tm_shaper_t shaper_profile); > + > +/** The odp_tm_queue_sched_config() function is used to dynamically set or > + * change the scheduler profile associated with a tm_node. Note that > despite > + * the name, this function affects a tm_node scheduler - specifically the > + * scheduler fan-in when such fan-in comes from an tm_queue. > + * > + * @param[in] tm_node Specifies the tm_node to be changed. > + * @param[in] tm_fan_in_queue Specifies which of the specified tm_node's > + * fan-in's weights etc are to be changed. The > + * fan-in is indentified by the > "producer"/parent > + * tm_queue actually connected to this fan-in. > + * @param[in] sched_profile Specifies the scheduler profile that should > + * now be used for the WFQ/RR entity within the > + * given tm_node. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_queue_sched_config(odp_tm_node_t tm_node, > + odp_tm_queue_t tm_fan_in_queue, > + odp_tm_sched_t sched_profile); > + > +/** The odp_tm_queue_threshold_config() function is used to dynamically > set or > + * change the queue threshold profile associated with this tm_queue. > + * > + * @param[in] tm_queue Specifies the tm_queue to be changed. > + * @param[in] thresholds_profile Specifies the queue threshold profile > that > + * should now be used for the given > tm_queue. > + * @return Returns 0 upon success and < 0 upon > failure. > + */ > +int odp_tm_queue_threshold_config(odp_tm_queue_t tm_queue, > + odp_tm_threshold_t thresholds_profile); > + > +/** odp_tm_queue_wred_config() function is used to dynamically set or > change > + * the WRED profile associated with this tm_queue or tm_queue/pkt_color > + * combination. > + * > + * @param[in] tm_queue Specifies the tm_queue to be changed. > + * @param[in] pkt_color Specifies the pkt_color that this profile is > to be > + * used with. Can also be the special value > + * ALL_PKT_COLORS. > + * @param[in] wred_profile Specifies the WRED profile that should now be > used > + * by this tm_queue, when processing pkts of this > + * pkt_color. It can be the value ODP_TM_INVALID > + * indicating that this tm_queue/pkt_color > combination > + * no longer implements WRED. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_queue_wred_config(odp_tm_queue_t tm_queue, > + odp_packet_color_t pkt_color, > + odp_tm_wred_t wred_profile); > + > +/** Topology setting functions */ > + > +/** Connects the "output" of the src_tm_node to be a "producer" of the > given > + * dst_tm_node. Note that an ODP_TM_ROOT handle passed in for the > + * dst_tm_node implies connection to the egress/root object of this TM > system. > + * > + * @param[in] src_tm_node odp_tm_node_t handle of the tm_node whose > output is > + * to be connected to the fan-in of the next > tm_node > + * as represented by the dst_tm_node. > + * @param[in] dst_tm_node odp_tm_node_t handle of the tm_node object that > will > + * receive all of the pkt_descs from the src > tm_node > + * output. If ODP_TM_ROOT, then attachment is to > + * the root egress object/spigot. > + * @return 0 upon success, < 0 on failure. > + */ > +int odp_tm_node_connect(odp_tm_node_t src_tm_node, odp_tm_node_t > dst_tm_node); > + > +/** The odp_queue_connect() function connects the indicated tm_queue to a > + * parent tm_node or to the egress/root node. The tm_queue will then > become > + * one of the dst node's fan-in set. > + * > + * @param[in] tm_queue Specifies the tm_queue. > + * @param[in] dst_tm_node odp_tm_node_t handle of the tm_node object that > will > + * receive all of the pkt_descs from the src > tm_node > + * output. If ODP_TM_ROOT, then attachment is to > + * the root egress object/spigot. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_queue_connect(odp_tm_queue_t tm_queue, odp_tm_node_t > dst_tm_node); > + > +/** Input API */ > + > +/** The odp_tm_enq() function is used to add packets to a given TM system. > + * Note that the System Metadata associated with the pkt needed by the TM > + * system is (a) a drop_eligible bit, (b) a two bit "pkt_color", (c) a 16- > bit > + * pkt_len, and MAYBE? (d) a signed 8-bit shaper_len_adjust. > + * > + * If there is a non-zero shaper_len_adjust, then it is added to the > pkt_len > + * after any non-zero shaper_len_adjust that is part of the shaper > profile. > + * > + * The pkt_color bits are a result of some earlier > Metering/Marking/Policing > + * processing (typically ingress based), and should not be confused with > the > + * shaper_color produced from the TM shaper entities within the tm_inputs > and > + * tm_nodes. > + * > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the TM > system). > + * @param[in] pkt Handle to a packet. > + * @return Returns 0 upon success, < 0 upon failure. One of > the > + * more common failure reasons is WRED dropage. > + */ > +int odp_tm_enq(odp_tm_queue_t tm_queue, odp_packet_t pkt); > + > +/** The odp_tm_enq_with_cnt() function behaves identically to > odp_tm_enq(), > + * except that it also returns (an approximation to?) the current tm_queue > + * packet queue count. > + * > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the TM > system). > + * @param[in] pkt Handle to a packet. > + * @return Returns the number of packets previously enqueued > on > + * this tm_queue upon success, < 0 upon failure. > + */ > +int odp_tm_enq_with_cnt(odp_tm_queue_t tm_queue, odp_packet_t pkt); > + > +/** Dynamic state query functions */ > + > +/** The following bit mask constants are used to refine the queue query > + * functions defined below. > + */ > +#define ODP_TM_QUERY_PKT_CNT 0x01 /**< The total_pkt_cnt value */ > +#define ODP_TM_QUERY_BYTE_CNT 0x02 /**< The total_byte_cnt value */ > +#define ODP_TM_QUERY_THRESHOLDS 0x04 /**< The thresholds??? */ > + > +/** The odp_tm_queue_info_t record type is used to return the various > counts > + * as requested by functions like odp_tm_queue_query() and > + * odp_tm_total_query(). > + */ > +typedef struct { > + /** The total_pkt_cnt field is the total number of packets > currently > + * stored/associated with the requested set of tm_queues. Note that > + * because the packet queues are potentially being manipulated by > + * multiple cpu's, the values here are only accurate when the tm > + * system is "stopped" (i.e. the egress spigot is stopped and no > + * odp_tm_enq calls are taking place). Implementations are free to > + * batch update these counters - up to a dozen or so packets. > + */ > + uint64_t total_pkt_cnt; > + > + /** If the requested set of tm_queues has an odp_tm_threshold_t > + * profile associated with it, then this is the max_pkt_cnt set in the > + * profile params. Returning this field is a convenience to the ODP > + * programmer, enabling them to quickly see how the total_pkt_cnt > + * compares to the maximum packet count threshold. Note that there is > + * no requirement that total_pkt_cnt be <= max_pkt_cnt. > + */ > + uint64_t max_pkt_cnt; > + > + /** The total_byte_cnt can either be the actual number of bytes > used > + * or an approximation of the number of bytes used based upon the > + * number of fixed sized buffers used multiplied by the buffer size. > + * In both cases the total_byte_cnt should correspond to the same set > + * of packets that were counted above. For instance, if the > + * total_pkt_cnt is updated in a batch, then the total_byte_cnt should > + * also be updated in the same batch. The approx_byte_cnt field below > + * indicates whether the total_byte_cnt is buffer count based or not. > + * In the case that the number of bytes used by a packet is rounded up > + * to a 2, 4, 8, or 16 byte boundary, it is recommended that > + * approx_byte_cnt be false. It is implementation dependent whether > + * the byte count of a packet includes the CRC, but it is recommended > + * that it not include headroom, preamble or IPG. Of course when the > + * buffer counting method is used, it is expected that any headroom in > + * the first buffer is implicitly included. Finally in the case of > + * variable length pkt based buffering, instead of taking the > + * total_pkt_cnt and multiplying it by the maximum ethernet packet > + * size, it is recommended that byte_cnt_valid be FALSE - even when > + * query_flags includes ODP_TM_QUERY_BYTE_CNT. > + */ > + uint64_t total_byte_cnt; > + > + /** If the requested set of tm_queues has an odp_tm_threshold_t > + * profile associated with it, then this is the max_byte_cnt set in > + * the profile params. Returning this field is a convenience to the > + * ODP programmer, enabling them to quickly see how the total_byte_cnt > + * compares to the maximum byte count threshold. Note that there is > + * no requirement that total_byte_cnt be <= max_byte_cnt. > + */ > + uint64_t max_byte_cnt; > + > + /** The following boolean values indicate which of the counts above > + * are valid. Invalid count values must be 0. > + */ > + odp_bool_t total_pkt_cnt_valid; /**< TRUE if total_pkt_cnt is valid > */ > + odp_bool_t max_pkt_cnt_valid; /**< TRUE if max_pkt_cnt is valid */ > + odp_bool_t total_byte_cnt_valid; /**< TRUE if total_byte_cnt is valid > */ > + odp_bool_t max_byte_cnt_valid; /**< TRUE if max_byte_cnt is valid > */ > + > + /** The approx_byte_cnt is TRUE if the total_byte_cnt field is > valid > + * AND if the buffer counting method is used. > + */ > + odp_bool_t approx_byte_cnt; > +} odp_tm_queue_info_t; > + > +/** The odp_tm_queue_query() function can be used to check a single > tm_queue's > + * queue utilization. The query_flags indicate whether or not packet > counts, > + * byte counts or both are being requested. It is an error to request > + * neither. The implementation may still return both sets of counts > + * regardless of query_flags if the cost of returning all the counts is > + * comparable to the cost of checking the query_flags. > + * > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the > + * TM system). > + * @param[out] query_flags A set of flag bits indicating which counters > are > + * being requested to be returned in the info > record. > + * @param[out] info Pointer to an odp_tm_queue_info_t record where > the > + * requested queue info is returned. > + * @return Returns 0 upon success, < 0 upon failure. > + */ > +int odp_tm_queue_query(odp_tm_queue_t tm_queue, > + uint32_t query_flags, > + odp_tm_queue_info_t *info); > + > +/** The odp_tm_priority_query() function can be used to check the queue > + * utilization of all tm_queue's with the given priority. The query_flags > + * indicate whether or not packet counts, byte counts or both are being > + * requested. It is an error to request neither. The implementation may > + * still return both sets of counts regardless of query_flags if the cost > of > + * returning all the counts is comparable to the cost of checking the > + * query_flags. > + * > + * @param[in] odp_tm Specifies the TM system. > + * @param[in] priority Supplies the strict priority level used to > specify > + * which tm_queues are included in the info > values. > + * @param[out] query_flags A set of flag bits indicating which counters > are > + * being requested to be returned in the info > record. > + * @param[out] info Pointer to an odp_tm_queue_info_t record where > the > + * requested queue info is returned. > + * @return Returns 0 upon success, < 0 upon failure. > + */ > +int odp_tm_priority_query(odp_tm_t odp_tm, uint8_t priority, > + uint32_t query_flags, odp_tm_queue_info_t *info); > + > +/** The odp_tm_total_query() function can be used to check the queue > + * utilization of all tm_queue's in a single TM system. The query_flags > + * indicate whether or not packet counts, byte counts or both are being > + * requested. It is an error to request neither. The implementation may > + * still return both sets of counts regardless of query_flags if the cost > of > + * returning all the counts is comparable to the cost of checking the > + * query_flags. > + * > + * @param[in] odp_tm Specifies the TM system. > + * @param[out] query_flags A set of flag bits indicating which counters > are > + * being requested to be returned in the info > record. > + * @param[out] info Pointer to an odp_tm_queue_info_t record where > the > + * requested queue info is returned. > + * @return Returns 0 upon success, < 0 upon failure. > + */ > +int odp_tm_total_query(odp_tm_t odp_tm, uint32_t query_flags, > + odp_tm_queue_info_t *info); > + > +/** The odp_tm_priority_threshold_config() function is only used to > associate > + * a maximum packet count and/or a maximum byte count with a strict > priority > + * level - for the benefit of the odp_tm_priority_query() function. It > has no > + * semantic effects other than returning these queue threshold values in > the > + * odp_tm_queue_info_t record. > + * > + * @param[in] odp_tm Specifies the TM system. > + * @param[in] priority Supplies the strict priority level that > + * the threshold profile params are > associated > + * with. > + * @param[in] thresholds_profile Specifies the queue threshold profile > that > + * should now be associated with the > supplied > + * strict priority level. > + * @return Returns 0 upon success and < 0 upon > failure. > + */ > +int odp_tm_priority_threshold_config(odp_tm_t odp_tm, uint8_t priority, > + odp_tm_threshold_t thresholds_profile); > + > +/** The odp_tm_total_threshold_config() function is only used to associate > a > + * maximum packet count and/or a maximum byte count with a TM system - for > the > + * benefit of the odp_tm_total_query() function. It has no semantic > effects > + * other than returning these queue threshold values in the > + * odp_tm_queue_info_t record. > + * > + * @param[in] odp_tm Specifies the TM system. > + * @param[in] thresholds_profile Specifies the queue threshold profile > that > + * should now be used for the entire TM > + * system. > + * @return Returns 0 upon success and < 0 upon > failure. > + */ > +int odp_tm_total_threshold_config(odp_tm_t odp_tm, > + odp_tm_threshold_t thresholds_profile); > + > +/** Misc functions */ > + > +/** The odp_tm_periodic_update function is a placeholder for any external > + * source of periodic events. In some cases the TM system may already > have an > + * internal built-in source of periodic events - in which case calling > this > + * function has no effect. > + */ > +void odp_tm_periodic_update(void); > + > +/** The odp_tm_is_idle function is used to determine if the specified ODP > + * traffic management system still has "work" to do (i.e. has at least one > + * non-empty tm_queue and perhaps some outstanding timers etc). This > function > + * can be used by test programs and ODP applications that wish to know > when > + * TM system has completed its work - presumably after they have stopped > + * sending in new pkts. Note that this function should not be called > often > + * since for some implementations this call could take a fairly long time > + * to execute! > + * > + * @param[in] odp_tm Specifies the TM system. > + * @return Returns 1 if the TM system is idle and 0 otherwise. > + */ > +odp_bool_t odp_tm_is_idle(odp_tm_t odp_tm); > + > +/** The odp_tm_stats_print function is used to write implementation- > defined > + * information about the specified TM system to the ODP log. The intended > use > + * is for debugging. > + * > + * @param[in] odp_tm Specifies the TM system. > + */ > +void odp_tm_stats_print(odp_tm_t odp_tm); > + > +/** > + * @} > + */ > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-generic/include/odp/plat/packet_types.h > b/platform/linux-generic/include/odp/plat/packet_types.h > index 45cb801..c3be633 100644 > --- a/platform/linux-generic/include/odp/plat/packet_types.h > +++ b/platform/linux-generic/include/odp/plat/packet_types.h > @@ -36,6 +36,17 @@ typedef ODP_HANDLE_T(odp_packet_seg_t); > > #define ODP_PACKET_SEG_INVALID _odp_cast_scalar(odp_packet_seg_t, > 0xffffffff) > > +/** odp_packet_color_t assigns names to the various pkt "colors" */ > +typedef enum { > + ODP_PACKET_GREEN = 0, > + ODP_PACKET_YELLOW = 1, > + ODP_PACKET_RED = 2, > + ODP_PACKET_ALL_COLORS = 3, > +} odp_packet_color_t; > + > +/** Sets the maximum number of pkt "colors" */ > +#define ODP_NUM_PACKET_COLORS 3 > + > /** Get printable format of odp_packet_t */ > static inline uint64_t odp_packet_to_u64(odp_packet_t hdl) > { > diff --git a/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > b/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > new file mode 100644 > index 0000000..52df64b > --- /dev/null > +++ b/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > @@ -0,0 +1,185 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/** > + * @file > + * > + * ODP traffic mngr > + */ > + > +#ifndef ODP_TRAFFIC_MNGR_TYPES_H_ > +#define ODP_TRAFFIC_MNGR_TYPES_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include <odp/std_types.h> > +#include <odp/plat/strong_types.h> > + > +/** @addtogroup odp_traffic_mngr > + * Macros and operations on a TM system. > + * @{ > + */ > + > +/** The ODP_TM_MAX_NUM_SYSTEMS constant specifies the maximum number of TM > + * systems that may be created. On some platforms this might be much more > + * limited to as little as one hardware TM system. > + */ > +#define ODP_TM_MAX_NUM_SYSTEMS 64 > + > +/** The ODP_TM_MAX_PRIORITIES constant specifies the largest range of > + * priorities that any TM system can support. All strict priority values > MUST > + * in the range 0..ODP_TM_MAX_PRIORITIES-1. > + */ > +#define ODP_TM_MAX_PRIORITIES 16 > + > +/** The ODP_TM MAX_LEVELS constant specifies the largest range of > + * tm_node levels that any TM system can support. Hence all tm_node level > + * values MUST be in the range 0..ODP_TM_MAX_LEVELS-1. Smaller tm_node > + * levels are associated with tm_nodes closer to the TM system egress. > + */ > +#define ODP_TM_MAX_LEVELS 8 > + > +/** > + * The smallest SCHED weight is 1 (i.e. 0 is not a legal WFQ/WRR value). > + */ > +#define ODP_TM_MIN_SCHED_WEIGHT 1 > + > +/** The ODP_TM_MAX_SCHED_WEIGHT constant is the largest weight any TM > system > + * can support (at least from a configuration standpoint). A given TM > system > + * could have a smaller value. > + */ > +#define ODP_TM_MAX_SCHED_WEIGHT 255 > + > +/** The ODP_TM_MAX_TM_QUEUES constant is the largest number of tm_queues > + * that can handled by any one TM system. > + */ > +#define ODP_TM_MAX_TM_QUEUES (16 * 1024 * 1024) > + > +/** The ODP_TM_MAX_NUM_OUTPUTS constant is the largest number of outputs > that > + * can be configured for any one TM system. > + */ > +#define ODP_TM_MAX_NUM_OUTPUTS 256 > + > +/** The ODP_TM_MAX_NUM_TM_NODES constant is the largest number of tm_nodes > that > + * can be in existence for any one TM system. > + */ > +#define ODP_TM_MAX_NUM_TM_NODES (1024 * 1024) > + > +/** The ODP_TM_MAX_TM_NODE_FANIN constant is the largest number of fan-in > + * "inputs" that can be simultaneously connected to a single tm_node. > + * *TBD* Does this need to be as large as ODP_TM_MAX_TM_QUEUES? *TBD* > + */ > +#define ODP_TM_MAX_TM_NODE_FANIN (1024 * 1024) > + > +/** The ODP_TM_MIN_SHAPER_BW constant is the smallest amount of bandwidth > that > + * can a shaper's peak or commit rate can be set to. It is in units of > + * 1000 bytes/second so that it and the ODP_TM_MAX_SHAPER_BW can both fit > in > + * 32 bits. > + */ > +#define ODP_TM_MIN_SHAPER_BW 1 > + > +/** The ODP_TM_MAX_SHAPER_BW constant is the largest amound of bandwidth > that > + * any shaper's peak or commit rate can be set to. It is in units of > + * 1000 bytes/second so that it and the ODP_TM_MIN_SHAPER_BW can both fit > in > + * 32 bits. > + */ > +#define ODP_TM_MAX_SHAPER_BW 12500000 > + > +/** The ODP_NUM_SHAPER_COLORS constant just counts the number of > enumeration > + * values defined in the odp_tm_shaper_color_t type. > + */ > +#define ODP_NUM_SHAPER_COLORS 3 > + > +/** The INVALID_PRIORITY constant is used when one needs to indicate an > + * invalid priority value. > + */ > +#define ODP_TM_INVALID_PRIORITY 255 > + > +/** The odp_tm_percent_t type is used when specifying fields that are > + * percentages. It is a fixed point integer whose units are 1/100 of a > + * percent. Hence 100% is represented as the integer value 10000. Note > + * that because it is often used as a ratio of the current queue value and > + * maximum queue threshold, it can be > 100%, but in any event will never > + * be larger than 500% (i.e. it MUST be capped at 50000). > + */ > +typedef uint16_t odp_tm_percent_t; > + > +/** The odp_tm_handle_t type is a generic type that can stand for any of > the > + * other ODP_TM handle types. > + */ > +typedef uint64_t odp_tm_handle_t; > + > +/** Each odp_tm_t value represents a specific TM system. Almost all > + * functions in this API require a odp_tm_t value - either directly > + * as a function parameter or indirectly by having another ODP TM handle > value > + * as a function parameter. > + */ > +typedef odp_tm_handle_t odp_tm_t; > + > +/** Each odp_tm_queue_t value is an opaque ODP handle representing a > specific > + * tm_queue within a specific TM system. > + */ > +typedef odp_tm_handle_t odp_tm_queue_t; > + > +/** Each odp_tm_node_t value is an opaque ODP handle representing a > specific > + * tm_node within a specific TM system. > + */ > +typedef odp_tm_handle_t odp_tm_node_t; > + > +/** Each odp_tm_shaper_t value is an opaque ODP handle representing a > specific > + * shaper profile usable across all TM systems described by this API. A > given > + * shaper profile can then be attached to any tm_queue or tm_node. > + */ > +typedef odp_tm_handle_t odp_tm_shaper_t; > + > +/** Each odp_tm_sched_t value is an opaque ODP handle representing a > specific > + * tm_node scheduler profile usable across all TM systems described by > this > + * API. A given tm_node scheduler profile can then be attached to any > tm_node. > + */ > +typedef odp_tm_handle_t odp_tm_sched_t; > + > +/** Each odp_tm_threshold_t value is an opaque ODP handle representing a > + * specific queue threshold profile usable across all TM systems described > by > + * this API. A given queue threshold profile can then be attached to any > + * tm_queue or tm_node. > + */ > +typedef odp_tm_handle_t odp_tm_threshold_t; > + > +/** Each odp_tm_wred_t value is an opaque ODP handle representing a > specific > + * WRED profile usable across all TM systems described by this API. A > given > + * WRED profile can then be attached to any tm_queue or tm_node. > + */ > +typedef odp_tm_handle_t odp_tm_wred_t; > + > +/** The ODP_TM_INVALID constant can be used with any ODP TM handle type > and > + * indicates that this value does NOT represent a valid TM object. > + */ > +#define ODP_TM_INVALID 0 > + > +/** > + * @def ODP_TM_ROOT > + * Constant that is used to refer to the egress/root node of the TM > subsystem's > + * tree/hierarchy of nodes. > + */ > +#define ODP_TM_ROOT 0 > + > +/** Get printable format of odp_queue_t */ > +static inline uint64_t odp_tm_handle_to_u64(odp_tm_handle_t hdl) > +{ > + return hdl; > +} > + > +/** > + * @} > + */ > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-generic/include/odp/traffic_mngr.h > b/platform/linux-generic/include/odp/traffic_mngr.h > new file mode 100644 > index 0000000..3aa6267 > --- /dev/null > +++ b/platform/linux-generic/include/odp/traffic_mngr.h > @@ -0,0 +1,35 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/** > + * @file > + * > + * ODP Traffic manager > + */ > + > +#ifndef ODP_PLAT_TRAFFIC_MNGR_H_ > +#define ODP_PLAT_TRAFFIC_MNGR_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/** @ingroup odp_traffic_mngr > + * @{ > + */ > + > +/** > + * @} > + */ > + > +#include <odp/plat/traffic_mngr_types.h> > +#include <odp/api/traffic_mngr.h> > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-generic/include/odp_packet_internal.h > b/platform/linux-generic/include/odp_packet_internal.h > index ba2cd7e..d3eaad0 100644 > --- a/platform/linux-generic/include/odp_packet_internal.h > +++ b/platform/linux-generic/include/odp_packet_internal.h > @@ -61,6 +61,9 @@ typedef union { > uint32_t tcpopt:1; /**< TCP options present */ > uint32_t sctp:1; /**< SCTP */ > uint32_t icmp:1; /**< ICMP */ > + > + uint32_t color:2; /**< Packet color for traffic mgmt */ > + uint32_t nodrop:1; /**< Drop eligibility status */ > }; > } input_flags_t; > > @@ -102,6 +105,8 @@ typedef union { > uint32_t l3_chksum:1; /**< L3 chksum override */ > uint32_t l4_chksum_set:1; /**< L3 chksum bit is valid */ > uint32_t l4_chksum:1; /**< L4 chksum override */ > + > + int8_t shaper_len_adj; /**< adjustment for traffic mgr */ > }; > } output_flags_t; > > -- > 2.1.4 > > _______________________________________________ > lng-odp mailing list > lng-odp@lists.linaro.org > https://lists.linaro.org/mailman/listinfo/lng-odp
They seem to show up just fine under the enumerations of the packet section. What issues do you see? On Fri, Oct 23, 2015 at 3:12 AM, Savolainen, Petri (Nokia - FI/Espoo) < petri.savolainen@nokia.com> wrote: > Reviewed-by: Petri Savolainen <petri.savolainen@nokia.com> > > > Bill, did you run 'make doxygen-html'? > > Not sure if @def ODP_PACKET_GREEN works when it's actually an enum. Anyway, > it's in the correct file now. > > -Petri > > > > > -----Original Message----- > > From: lng-odp [mailto:lng-odp-bounces@lists.linaro.org] On Behalf Of EXT > > Bill Fischofer > > Sent: Thursday, October 22, 2015 11:44 PM > > To: lng-odp@lists.linaro.org > > Cc: Barry Spinney > > Subject: [lng-odp] [API-NEXT PATCHv6 1/4] api: tm: add tm API definitions > > > > From: Barry Spinney <spinney@ezchip.com> > > > > This introduces an API for configuring and using Traffic Management > > systems. > > > > The purpose of this API is as a general packet scheduling system that > > accepts packets from input queues and applies strict priority > > scheduling, weighted fair queuing scheduling and/or bandwidth controls > > to decide which input packet should be chosen as the next output > > packet and when this output packet can be sent onwards. > > > > Signed-off-by: Barry Spinney <spinney@ezchip.com> > > Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org> > > --- > > include/odp.h | 1 + > > include/odp/api/packet.h | 69 + > > include/odp/api/traffic_mngr.h | 1611 > > ++++++++++++++++++++ > > .../linux-generic/include/odp/plat/packet_types.h | 11 + > > .../include/odp/plat/traffic_mngr_types.h | 185 +++ > > platform/linux-generic/include/odp/traffic_mngr.h | 35 + > > .../linux-generic/include/odp_packet_internal.h | 5 + > > 7 files changed, 1917 insertions(+) > > create mode 100644 include/odp/api/traffic_mngr.h > > create mode 100644 platform/linux- > > generic/include/odp/plat/traffic_mngr_types.h > > create mode 100644 platform/linux-generic/include/odp/traffic_mngr.h > > > > diff --git a/include/odp.h b/include/odp.h > > index 825c7e1..f6a6ea9 100644 > > --- a/include/odp.h > > +++ b/include/odp.h > > @@ -56,6 +56,7 @@ extern "C" { > > #include <odp/thrmask.h> > > #include <odp/spinlock_recursive.h> > > #include <odp/rwlock_recursive.h> > > +#include <odp/traffic_mngr.h> > > > > #ifdef __cplusplus > > } > > diff --git a/include/odp/api/packet.h b/include/odp/api/packet.h > > index 5d46b7b..0680b3f 100644 > > --- a/include/odp/api/packet.h > > +++ b/include/odp/api/packet.h > > @@ -48,6 +48,26 @@ extern "C" { > > * Invalid packet segment > > */ > > > > + /** > > + * @typedef odp_packet_color_t > > + * Color of packet for shaper/drop processing > > + */ > > + > > + /** > > + * @def ODP_PACKET_GREEN > > + * Packet is green > > + */ > > + > > + /** > > + * @def ODP_PACKET_YELLOW > > + * Packet is yellow > > + */ > > + > > + /** > > + * @def ODP_PACKET_RED > > + * Packet is red > > + */ > > + > > /* > > * > > * Alloc and free > > @@ -700,6 +720,55 @@ odp_packet_seg_t odp_packet_last_seg(odp_packet_t > > pkt); > > */ > > odp_packet_seg_t odp_packet_next_seg(odp_packet_t pkt, odp_packet_seg_t > > seg); > > > > +/** > > + * Get packet color > > + * > > + * @param pkt Packet handle > > + * @return packet color > > + */ > > +odp_packet_color_t odp_packet_color(odp_packet_t pkt); > > + > > +/** > > + * Set packet color > > + * > > + * @param pkt Packet handle > > + * @param color Color to set > > + */ > > +void odp_packet_color_set(odp_packet_t pkt, odp_packet_color_t color); > > + > > +/** > > + * Get drop eligible status > > + * > > + * @param pkt Packet handle > > + * @return Packet drop eligibility status > > + * @retval 0 Packet is not drop eligible > > + * @retval 1 Packet is drop > > + */ > > +odp_bool_t odp_packet_drop_eligible(odp_packet_t pkt); > > + > > +/** > > + * Set drop eligible status > > + * > > + * @param pkt Packet handle > > + * @param status Drop eligibility status > > + */ > > +void odp_packet_drop_eligible_set(odp_packet_t pkt, odp_bool_t status); > > + > > +/** > > + * Get shaper length adjustment > > + * > > + * @param pkt Packet handle > > + * @return Shaper adjustment (-128..127) > > + */ > > +int8_t odp_packet_shaper_len_adjust(odp_packet_t pkt); > > + > > +/** > > + * Set shaper length adjustment > > + * > > + * @param pkt Packet handle > > + * @param adj Signed adjustment value > > + */ > > +void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, int8_t adj); > > > > /* > > * > > diff --git a/include/odp/api/traffic_mngr.h > > b/include/odp/api/traffic_mngr.h > > new file mode 100644 > > index 0000000..2459a8b > > --- /dev/null > > +++ b/include/odp/api/traffic_mngr.h > > @@ -0,0 +1,1611 @@ > > +/** Copyright (c) 2015, Linaro Limited > > + * All rights reserved. > > + * > > + * SPDX-License-Identifier: BSD-3-Clause > > + */ > > + > > +#ifndef ODP_TRAFFIC_MNGR_H_ > > +#define ODP_TRAFFIC_MNGR_H_ > > + > > +#ifdef __cplusplus > > +extern "C" { > > +#endif > > + > > +#include <odp/std_types.h> > > +#include <odp/packet_io.h> > > + > > +/** > > + * @file > > + * > > + */ > > + > > +/** @defgroup odp_traffic_mngr ODP TRAFFIC MNGR > > + * @{ > > + * > > + * An API for configuring and using Traffic Management systems > > + * > > + * This file forms a simple interface for creating, configuring and > using > > + * Traffic Management (TM) subsystems. By TM subsystem it is meant a > > general > > + * packet scheduling system that accepts packets from input queues and > > applies > > + * strict priority scheduling, weighted fair queueing scheduling and/or > > + * bandwidth controls to decide which input packet should be chosen as > the > > + * next output packet and when this output packet can be sent onwards. > > + * > > + * A given platform supporting this TM API could support one or more > pure > > + * hardware based packet scheduling systems, one or more pure software > > + * based systems or one or more hybrid systems - where because of > > + * hardware constraints some of the packet scheduling is done in > hardware > > + * and some is done in software. In addition, there may also be > > additional > > + * API's beyond those described here for (a) controlling advanced > > capabilities > > + * supported by specific hardware, software or hybrid subsystems or (b) > > + * dealing with constraints and limitations of specific implementations. > > + * The intention here is to be the simplest API that covers the vast > > majority > > + * of packet scheduling requirements. > > + * > > + * Often a TM subsystem's output(s) will be directly connected > > + * to a device's physical (or virtual) output interfaces/links, in which > > case > > + * sometimes such a system will be called an Egress Packet Scheduler or > an > > + * Output Link Shaper, etc.. While the TM subsystems configured by this > > API > > + * can be used in such a way, this API equally well supports the ability > > to > > + * have the TM subsystem's outputs connect to other TM subsystem input > > queues > > + * or general software queues or even some combination of these three > > cases. > > + * > > + * <H2>TM Algorithms</H2> > > + * > > + * The packet scheduling/dropping techniques that can be applied to > input > > + * traffic include any mixture of the following: > > + * <ol> > > + * <li> Strict Priority scheduling. > > + * <li> Weighted Fair Queueing scheduling (WFQ). > > + * <li> Bandwidth Shaping. > > + * <li> Weighted Random Early Discard (WRED). > > + * </ol> > > + * Note that Bandwidth Shaping is the only feature that can cause > packets > > + * to be "delayed", and Weighted Random Early Discard is the only > feature > > + * (other than input queues becoming full) that can cause packets to be > > + * dropped. > > + * > > + * <H3>Strict Priority Scheduling</H3> > > + * Strict Priority Scheduling (or just priority for short), is a > technique > > + * where input queues and the packets from them, are assigned a priority > > + * value in the range 0 .. ODP_TM_MAX_PRIORITIES - 1. At all times > > packets > > + * the the smallest priority value will be chosen ahead of packets with > a > > + * numerically larger priority value. This is called strict priority > > + * scheduling because the algorithm strictly enforces the scheduling of > > + * higher priority packets over lower priority packets. > > + * > > + * <H3>Bandwidth Shaping</H3> > > + * Bandwidth Shaping (or often just Shaping) is the term used here for > the > > + * idea of controlling packet rates using single rate and/or dual rate > > token > > + * bucket algorithms. For single rate shaping a rate (the commit rate) > > and > > + * a "burst size" (the maximum commit count) are configured. Then an > > + * internal signed integer counter called the commitCnt is maintained > such > > + * that if the commitCnt is positive then packets are eligible to be > sent. > > + * When such a packet is actually sent then its commitCnt is decremented > > + * (usually by its length, but one could decrement by 1 for each packet > > + * instead). The commitCnt is then incremented periodically based upon > > the > > + * configured rate, so that this technique causes the traffic to be > > limited > > + * to the commit rate over the long term, while allowing some ability to > > + * exceed this rate for a very short time (based on the burst size) in > > order > > + * to catch up if the traffic input temporarily drops below the commit > > rate. > > + * > > + * Dual Rate Shaping is designed to allow certain traffic flows to > fairly > > + * send more than their assigned commit rate when the scheduler has > > excess > > + * capacity. The idea being that it may be better to allow some types > of > > + * traffic to send more than their committed bandwidth rather than > letting > > + * the TM outputs be idle. The configuration of Dual Rate Shaping > > requires > > + * additionally a peak rate and a peak burst size. The peak rate must > be > > + * greater than the related comls mit rate, but the burst sizes have no > > similar > > + * constraint. Also for every input priority that has Dual Rate shaping > > + * enabled, there needs to be an additional equal or lower priority > (equal > > or > > + * higher numeric priority value) assigned. Then if the traffic exceeds > > its > > + * commit rate but not its peak rate, the "excess" traffic will be sent > at > > the > > + * lower priority level - which by the strict priority algorithm should > > + * cause no degradation of the higher priority traffic, while allowing > for > > + * less idle outputs. > > + * > > + * <H3>Weighted Fair Queuing</H3> > > + * Weighted Fair Queuing (WFQ) is used to arbitrate amongst multiple > input > > + * packets with the same priority. Each input can be assigned a weight > in > > the > > + * range MIN_WFQ_WEIGHT..MAX_WFQ_WEIGHT (nominally 1..255) that affects > > the way > > + * the algorithm chooses the next packet. If all of the weights are > equal > > AND > > + * all of the input packets are the same length then the algorithm is > > + * equivalent to a round robin scheduling. If all of the weights are > > equal > > + * but the packets have different lengths then the WFQ algorithm will > > attempt > > + * to choose the packet such that inputs each get a fair share of the > > + * bandwidth - in other words it implements a weighted round robin > > algorithm > > + * where the weighting is based on frame length. > > + * > > + * When the input weights are not all equal and the input packet lengths > > vary > > + * then the WFQ algorithm will schedule packets such that the packet > with > > + * the lowest "Virtual Finish Time" is chosen first. An input packet's > > + * Virtual Finish Time is roughly calculated based on the WFQ object's > > base > > + * Virtual Finish Time when the packet becomes the first packet in its > > queue > > + * plus its frame length divided by its weight. > > + * @code > > + * virtualFinishTime = wfqVirtualTimeBase + (pktLength / wfqWeight) > > + * @endcode > > + * In a system running at full capacity with no bandwidth limits - over > > the > > + * long term - each input fan-in's average transmit rate will be the > same > > + * fraction of the output bandwidth as the fraction of its weight > divided > > by > > + * the sum of all of the WFQ fan-in weights. Hence larger WFQ weights > > result > > + * in better "service" for a given fan-in. > > + * @code > > + * totalWfqWeight = 0; > > + * for (each fan-in entity - fanIn - feeding this WFQ scheduler) > > + * totalWfqWeight += fanIn->sfqWeight; > > + * > > + * fanIn->avgTransmitRate = avgOutputRate * fanIn->sfqWeight / > > totalWfqWeight; > > + * @endcode > > + * > > + * <H3>Weighted Random Early Discard</H3> > > + * The Weighted Random Early Discard (WRED) algorithm deals with the > > situation > > + * where an input packet rate exceeds some output rate (including > > + * the case where Bandwidth Shaping limits some output rates). Without > > WRED > > + * enabled and configured, the TM system will just implement a tail > > dropping > > + * scheme whereby whichever packet is unlucky enough to arrive when an > TM > > + * input queue is full will be discarded regardless of priority or any > > other > > + * consideration. > > + * WRED allows one to configure the system to use a better/fairer > > algorithm > > + * than simple tail dropping. It works by measuring the "fullness" of > > + * various packet queues and converting this percentage into a > probability > > + * of random packet dropping with the help of some configurable > > parameters. > > + * Then a random number is picked and together with the drop > probability, > > + * a decision is made to accept the packet or drop it. > > + * A basic parameterization of WRED requires three parameters: > > + * <ol> > > + * <li> the maximum queue level (which could be either a maximum number > of > > + * packets or a maximum amount of memory (i.e. bytes/buffers) > used), > > + * <li> a starting threshold - which is a number in the range 0..100 > > + * representing a percentage of the maximum queue level at which > the > > + * drop probability becomes non-zero, > > + * <li> a drop probability - which is a number in the range 0..100 > > + * representing a probability (0 means no drop and 100 means > > + * certain drop) - which is used when the queue is near 100% full. > > + * </ol> > > + * > > + * Note that all packet drops for a TM system only occur when a new > packet > > + * arrives at a given TM system input queue. At that time either the > WRED > > + * algorithm, if enabled for this input queue, or the "input queue full" > > + * tail drop algorithm will make a drop/no drop decision. After this > > point, > > + * any packets not dropped, will at some point be sent out a TM output - > > + * assuming that the topology is fully connected and enabled. > > + * > > + * <H2>Hierarchical Scheduling and tm_nodes</H2> > > + * This API supports the ability to do Hierarchical Scheduling whereby > the > > + * final scheduling decision is controlled by equal priority schedulers, > > + * strict priority multiplexers, bandwidth shapers - at multiple levels > - > > all > > + * forming a tree rooted at a single egress object. In other words, all > > + * tm_queues and tm_nodes have the property that their logical "output" > > feeds > > + * into one fan-in of a subsequent tm_node or egresss object - forming a > > proper > > + * tree. See the following link - > > + * <A HREF="diagram1.svg">Example Tm_node</A> - for an example. > > + * > > + * Multi-level/hierarchical scheduling adds both great control and > > significant > > + * complexity. Logically, despite the implication of the tm_node tree > > + * diagrams, there are no queues between the levels of hierarchy. > Instead > > all > > + * packets are held in their input queue, until such time that the > > totality of > > + * all of the tm_nodes in the single path from input queue to output > > object > > + * agrees that this packet should be the next to be chosen to leave the > TM > > + * system through the output object "portal". Hence what flows from > level > > to > > + * level is the "local choice" of what packet/tm_queue should next be > > + * serviced. > > + * > > + * <H3>tm_nodes</H3> > > + * Tm_nodes are the main "entity"/object that a TM system is composed > of. > > + * Each tm_node is a mini-TM subsystem of its own, but the > interconnection > > + * and interplay of a multi-level "tree" of tm_nodes can allow the user > > + * to specify some very sophisticated behaviours. > > + * Each tm_node can contain a set of scheduler (one per strict priority > > level), > > + * a strict priority multiplexer, a bandwidth shaper and a WRED > component > > - or > > + * a subset of these. > > + * > > + * In its full generality an tm_node consists of a set of "fan-in" > > connections > > + * to preceding tm_queues or tm_nodes. The fan-in for a single tm_node > > + * can range from 1 to many many thousands. This fan-in is divided > first > > + * into a WFQ scheduler per priority level. So if 4 priority levels are > > + * implemented by this tm_node, there would be 4 WFQ schedulers - each > > with > > + * its own unique fan-in. After the WFQ schedulers a priority chooser > > comes > > + * next - where it will always choose the highest priority WFQ output > > + * available. The output of the priority chooser then feeds a bandwidth > > + * shaper function which then finally uses the shaper's propagation > table > > + * to determine its output packet and its priority. This output could > > + * then be remapped via a priority map profile and then becomes one of > the > > + * input fan-in to perhaps another level of tm_nodes, and so on. > > + * > > + * During this process it is important to remember that the bandwidth > > shaping > > + * function never causes packets to be dropped. Instead all packet > drops > > + * occur because of tm_queue fullness or be running the WRED algorithm > > + * at the time a new packet attempts to be appended to the end of some > > + * input queue. > > + * > > + * The WRED profile associated with an tm_node considers the entire set > of > > + * tm_queues feeding directly or indirectly into it as its measure of > > + * queue fullness. > > + * > > + * <H3>tm_queues</H3> > > + * tm_queues are the second major type of "entity"/object that a TM > > + * system is composed of. All packets MUST first enter the TM system > via > > + * some tm_queue. Then logically, the head packets of all of the > > tm_queues > > + * are examined simultaneously by the entire TM system, and ONE tm_queue > > is > > + * chosen send its head packet out of the TM system's egress. > Abstractly > > + * packets stay in the tm_queue until they are chosen at which time they > > are > > + * instantly transferred from tm_queue to/through the corresponding TM > > egress. > > + * It is also important to note that packets in the same tm_queue MUST > > always > > + * stay in order. In other words, the second packet in an tm_queue must > > never > > + * leave the TM system through a TM egress spigot before the first > packet > > has > > + * left the system. So tm_queue packet order must always be maintained. > > + * > > + * <H3>TM egress</H3> > > + * Note that TM egress objects are NOT referred to as queues, because in > > + * many/most cases they don't have multi-packet structure but instead > are > > + * viewed as a port/spigot through which the TM system schedules and > > finally > > + * transfers input packets through. > > + * > > + * <H2>Ideal versus Actual Behavior</H2> > > + * It is important to recognize the difference between the "abstract" > > + * mathematical model of the prescribed behavior and real > implementations. > > + * The model describes the Ideal, but theoretically desired behavior, > but > > such > > + * an Ideal is generally not practical to implement. Instead, one > > understands > > + * that virtually all Real TM systems attempt to approximate the Ideal > > behavior > > + * as given by the TM configuration as best as they can - while still > > + * attaining high packet processing performance. The idea is that > instead > > of > > + * trying too hard to be "perfect" at the granularity of say > microseconds, > > it > > + * may be better to instead try to match the long term Ideal behavior > over > > a > > + * much more reasonable period of time like a millisecond. It is > > generally > > + * better to have a stable implementation that when averaged over a > period > > of > > + * several milliseconds matches the Ideal behavior very closely than to > > have > > + * an implementation that is perhaps more accurate over a period of > > + * microseconds, but whose millisecond averaged behavior drifts away > from > > the > > + * Ideal case. > > + * > > + * <H2>Other TM Concepts</H2> > > + * > > + * <H3>Profiles</H3> > > + * This specification often packages related TM system parameters into > > + * records/objects called profiles. These profiles can then be > associated > > with > > + * various entities like tm_nodes and tm_queue's. This way the amount > of > > + * storage associated with setting related parameters can be reduced and > > + * in addition it is common to re-use the same set of parameter set over > > + * and over again, and also to be able to change the parameter set once > > + * and have it affect lots of entities with which it is associated > > with/applied > > + * to. > > + * > > + * <H3>Absolute Limits versus odp_tm_capability_t</H3> > > + * This header file defines some constants representing the absolute > > maximum > > + * settings for any TM system, though in most cases a TM system can (and > > + * should) be created/instantiated with smaller values, since lower > values > > + * will often result in faster operation and/or less memory used. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_NUM_SYSTEMS > > + * The maximum number of TM systems that may be created. On some > > platforms > > + * this might be much more limited to as little as one hardware TM > system. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_PRIORITIES > > + * The largest range of priorities that any TM system can support. All > > strict > > + * priority values MUST in the range 0..ODP_TM_MAX_PRIORITIES-1. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_LEVELS > > + * The largest range of tm_node levels that any TM system can support. > > Hence > > + * all tm_node level values MUST be in the range 0..ODP_TM_MAX_LEVELS-1. > > + * Smaller tm_node levels are associated with tm_nodes closer to the TM > > system > > + * egress. > > + */ > > + > > +/** > > + * @def ODP_TM_MIN_SCHED_WEIGHT > > + * The smallest SCHED weight is 1 (i.e. 0 is not a legal WFQ/WRR value). > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_SCHED_WEIGHT > > + * The largest weight any TM system can support (at least from a > > configuration > > + * standpoint). A given TM system could have a smaller value. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_TM_QUEUES > > + * The largest number of tm_queues that can handled by any one TM > system. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_NUM_OUTPUTS > > + * The largest number of outputs that can be configured for any one TM > > system. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_NUM_TM_NODES > > + * The largest number of tm_nodes that can be in existence for any one > TM > > + * system. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_TM_NODE_FANIN > > + * The largest number of fan-in "inputs" that can be simultaneously > > connected > > + * to a single tm_node. > > + * @todo Does this need to be as large as ODP_TM_MAX_TM_QUEUES? > > + */ > > + > > +/** > > + * @def ODP_TM_MIN_SHAPER_BW > > + * The largest amound of bandwidth that any shaper's peak or commit rate > > can > > + * be set to. It is in units of 1000 bytes/second. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_SHAPER_BW > > + * The largest amound of bandwidth that any shaper's peak or commit rate > > can > > + * be set to. It is in units of 1000 bytes/second. > > + */ > > + > > +/** > > + * @def ODP_NUM_SHAPER_COLORS > > + * The number of enumeration values defined in the odp_tm_shaper_color_t > > type. > > + */ > > + > > +/** > > + * @def ODP_TM_INVALID_PRIORITY > > + * Used to indicate an invalid priority value. > > + */ > > + > > +/** > > + * @typedef odp_tm_percent_t > > + * Is used when specifying fields that are percentages. It is a fixed > > point > > + * integer whose units are 1/100 of a percent. Hence 100% is > represented > > as > > + * the integer value 10000. Note that because it is often used as a > ratio > > of > > + * the current queue value and maximum queue threshold, it can be > > 100%, > > but > > + * in any event will never be larger than 500% (i.e. it MUST be capped > at > > + * 50000). > > + */ > > + > > +/** > > + * @typedef odp_tm_t > > + * Each odp_tm_t value represents a specific TM system. Almost all > > functions > > + * in this API require a odp_tm_t value - either directly as a function > > + * parameter or indirectly by having another ODP TM handle value as a > > function > > + * parameter. > > + */ > > + > > +/** > > + * @typedef odp_tm_queue_t > > + * Each odp_tm_queue_t value is an opaque ODP handle representing a > > specific > > + * tm_queue within a specific TM system. > > + */ > > + > > +/** > > + * @typedef odp_tm_node_t > > + * Each odp_tm_queue_t value is an opaque ODP handle representing a > > specific > > + * tm node within a specific TM system. > > + */ > > + > > +/** > > + * @typedef odp_tm_shaper_t > > + * Each odp_tm_shaper_t value is an opaque ODP handle representing a > > specific > > + * shaper profile usable across all TM systems described by this API. A > > given > > + * shaper profile can then be attached to any tm_queue or tm_node. > > + */ > > + > > +/** > > + * @typedef odp_tm_sched_t > > + * Each odp_tm_sched_t value is an opaque ODP handle representing a > > specific > > + * tm_node scheduler profile usable across all TM systems described by > > this > > + * API. A given tm_node scheduler profile can then be attached to any > > + * tm_node. > > + */ > > + > > +/** > > + * @typedef odp_tm_threshold_t > > + * Each odp_tm_threshold_t value is an opaque ODP handle representing a > > + * specific queue threshold profile usable across all TM systems > described > > by > > + * this API. A given queue threshold profile can then be attached to > any > > + * tm_queue or tm_node. > > + */ > > + > > +/** > > + * @typedef odp_tm_wred_t > > + * Each odp_tm_wred_t value is an opaque ODP handle representing a > > specific > > + * WRED profile usable across all TM systems described by this API. A > > given > > + * WRED profile can then be attached to any tm_queue or tm_node. > > + */ > > + > > +/** > > + * @def ODP_TM_INVALID > > + * Constant that can be used with any ODP TM handle type and indicates > > that > > + * this value does NOT represent a valid TM object. > > + */ > > + > > +/** > > + * @def ODP_TM_ROOT > > + * Constant that is used to refer to the egress/root node of the TM > > subsystem's > > + * tree/hierarchy of nodes. > > + */ > > + > > +/** The odp_tm_capability_t type is used to describe the feature set and > > limits > > + * of a TM system. It is passed to the odp_tm_create() function > > indirectly > > + * by being part of the odp_tm_params_t record. > > + */ > > +typedef struct { > > + /** max_tm_queues specifies the maximum number of tm_queues that > > can > > + * be in existence for this TM System. > > + */ > > + uint32_t max_tm_queues; > > + > > + /** max_fanin_per_level specifies the maximum number of fan_in > link > > + * to any given scheduler (whether weighted or using fair queueing > or > > + * round robin) belonging to tm_nodes at the given level. > > + */ > > + uint32_t max_fanin_per_level[ODP_TM_MAX_LEVELS]; > > + > > + /** max_priority specifies the maximum number of strict priority > > + * levels used by any tm_queue or tm_node. Note that any given > > + * tm_queue or tm_node can use a subset of these levels. > max_priority > > + * must be in the range 0..ODP_TM_MAX_PRIORITIES - 1. Note that > lower > > + * numeric values represent higher (more important or time critical) > > + * priorities. > > + */ > > + uint8_t max_priority; > > + > > + /** max_levels specifies that maximum number of levels of > > hierarchical > > + * scheduling allowed by this TM System. This is a count of the > > + * tm_node stages and does not include tm_queues or tm_egress > objects. > > + * Hence any given tm_node will have associated tm_node_level in the > > + * range 0 to max_levels - 1, where tm_node's at level 0 output's > only > > + * go to egress objects and tm_nodes whose level is max_levels - 1 > > + * have their fan_in only from tm_queues. > > + */ > > + uint8_t max_levels; > > + > > + /** tm_queue_shaper_supported indicates that the tm_queues > support > > + * proper TM shaping. Note that TM Shaping is NOT the same thing as > > + * Ingress Metering/Policing as specified by RFC 2697 (A Single Rate > > + * Three Color Marker) or RFC 2698 (A Two Rate Three Color Marker). > > + * These RFC's can be used for a Diffserv traffic conditioner, or > > + * other ingress policing. They make no mention of and have no > > + * algorithms for delaying packets - which is what TM shapers are > > + * expected to do. > > + */ > > + odp_bool_t tm_queue_shaper_supported; > > + > > + /** tm_node_shaper_supported indicates that the tm_nodes (at > least > > for > > + * some hierarchical levels) support proper T < M shaping. > > + */ > > + odp_bool_t tm_node_shaper_supported; > > + > > + /** red_supported indicates that the tm_queues support some form > of > > + * Random Early Discard. > > + */ > > + odp_bool_t red_supported; > > + > > + /** hierarchical_red_supported indicates that this TM system > > supports > > + * some form of RED where the queue fullness of tm_nodes contributes > > + * to the overall RED DROP/NO-DROP decision. > > + */ > > + odp_bool_t hierarchical_red_supported; > > + > > + /** weights_supported indicates that the tm_node schedulers (at > > least > > + * for some hierarchical levels) can have their different weights > for > > + * their fan-ins. > > + */ > > + odp_bool_t weights_supported; > > + > > + /** fair_queuing_supported indicates the the tm_node schedulers > (at > > + * least for some hierarchical levels) can implement WFQ or FQ > > + * scheduling disciplines, otherwise these schedulers can only > > + * implement WRR or RR algorithms, > > + */ > > + odp_bool_t fair_queuing_supported; > > +} odp_tm_capability_t; > > + > > +/** The odp_tm_egress_fcn_t type defines the parameter profile of the > > egress > > + * function callback. Using an egress function callback is just one of > > several > > + * ways of getting packets out from an egress spigot. > > + * > > + */ > > +typedef void (*odp_tm_egress_fcn_t) (odp_packet_t odp_pkt); > > + > > +/** The tm_egress_kind_e enumeration type is used to indicate the kind > of > > + * egress object ("spigot") associated with this TM system. Most of > these > > + * kinds are optional - with ODP_TM_EGRESS_PKT_IO being the only > mandatory > > + * kind. The TM_EGRESS_FN - if implemented - is useful for testing the > TM > > + * subsystem, and users are warned that its performance might be > limited. > > + */ > > +typedef enum { > > + ODP_TM_EGRESS_PKT_IO, > > + ODP_TM_EGRESS_FN, > > +} odp_tm_egress_kind_t; > > + > > +/** The odp_tm_egress_t type is used to describe that type of "egress > > spigot" > > + * associated with this TM system. It is passed to the odp_tm_create() > > + * function indirectly by being part of the odp_tm_params_t record. > > + */ > > +typedef struct { > > + odp_tm_egress_kind_t egress_kind; /**< Union discriminator */ > > + > > + union { > > + odp_pktio_t pktio; > > + odp_tm_egress_fcn_t egress_fcn; > > + }; > > +} odp_tm_egress_t; > > + > > +/** The odp_tm_params_t record type is used to hold extra parameters > when > > + * calling the odp_tm_create() function. > > + * Since it is expected that implementations might augment this record > > type > > + * with platform specific additional fields - it is required that > > + * odp_tm_params_init() be called on variables of this type before any > of > > the > > + * fields are filled in. > > + */ > > +typedef struct { > > + odp_tm_capability_t capability; /**< capability record */ > > + odp_tm_egress_t egress; /**< describes the egress "spigot" */ > > +} odp_tm_params_t; > > + > > +/** odp_tm_capability_init() must be called to initialize any > > + * odp_tm_capability_t record before it is first used or assigned to. > > + * > > + * @param[in] capability A pointer to an odp_tm_capability_t record > which > > + * is to be initialized. > > + */ > > +void odp_tm_capability_init(odp_tm_capability_t *capability); > > + > > +/** odp_tm_params_init() must be called to initialize any > > + * odp_tm_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_params_t record which > > + * is to be initialized. > > + */ > > +void odp_tm_params_init(odp_tm_params_t *params); > > + > > +/** Create/instantiate a TM Packet Scheduling system. > > + * > > + * @param[in] name The name to be assigned to this TM system. Cannot > > be > > + * NULL, and also must be unique amongst all other TM > > system > > + * names. > > + * @param[in] params The params to be used when creating this TM > system. > > + * @return Returns ODP_TM_INVALID upon failure, otherwise the > > newly > > + * created TM system's odp_tm_t handle is returned. > > + */ > > +odp_tm_t odp_tm_create(const char *name, odp_tm_params_t *params); > > + > > +/** Find a pre-existing TM Packet Scheduling system. This function can > be > > + * used either to find a TM system created previously with odp_tm_create > > OR > > + * get the odp_tm_t of a built-in TM system - usually based on HW. In > this > > + * later case the format of the name used to refer to a specific > built-in > > + * hardware TM system may be platform dependent, but in any case a name > of > > + * "HW_TM_%u" where the number starts at 1, can be used to find a > built-in > > + * system independently of the best capability match. If name is NULL > > then > > + * the existing (built-in or created by odp_tm_create) TM system that > best > > + * matches capability is returned. > > + * > > + * @param[in] name If NULL then only uses the capability > parameter > > to > > + * find a closest match, otherwise if the name is > > + * matched by an existing TM system it is > returned. > > + * @param[in] capability Used when the name is NULL (in which > > + * case the closest match is returned) or when > the > > + * name is not-NULL, but doesn't match > > + * any existing TM system in which case the > > + * capability is used to find the FIRST > > + * TM system matching exactly these limits. > > + * @return If an existing TM system (built-in or > previously > > + * created via odp_tm_create) is found, its > > + * odp_tm_t value is returned, otherwise > > + * ODP_TM_INVALID is returned. > > + */ > > +odp_tm_t odp_tm_find(const char *name, odp_tm_capability_t *capability); > > + > > +/** odp_tm_capability() can be used to query the actual limits of a > given > > TM > > + * system. This function can be used for both built-in TM systems AND > TM > > + * system's created via odp_tm_create(). > > + * > > + * @param[in] odp_tm The odp_tm_t value of the TM system to be > > + * queried. > > + * @param[out] capability A pointer to a odp_tm_capability_t record > > + * where the actual limits used by the TM system > > are > > + * copied into. Note that these limits do NOT > > + * have to match the capability passed in if > > + * a TM system was created by odp_tm_create, > > + * but of course these limits in some cases > could > > + * be larger. > > + * @return Returns 0 upon success, < 0 upon failure > (which > > + * indicates that the odp_tm value did not > > + * exist). > > + */ > > +int odp_tm_capability(odp_tm_t odp_tm, odp_tm_capability_t *capability); > > + > > +/** odp_tm_destroy() may be used to destroy TM systems created via > > + * odp_tm_create(). It generally CANNOT be used to destroy built-in TM > > + * systems. Also some platforms MAY not support destroying of TM > systems > > + * created via odp_tm_create() under certain conditions. For example a > > given > > + * platform may require that the TM system be first "drained" of all of > > its > > + * queued packets before it will accept a odp_tm_destroy() call. > > + * > > + * In general calling odp_tm_destroy() on an active TM system does not > > + * guarantee anything about the disposition of any packets queued within > > the > > + * TM system, other than EVENTUALLY these packets will be either sent > (in > > ANY > > + * order) or freed. > > + * > > + * @param[in] odp_tm The odp_tm_t value of the TM system to be > destroyed > > (and > > + * hence destroyed (and hence freed). > > + * @return 0 upon success, < 0 upon failure. > > + */ > > +int odp_tm_destroy(odp_tm_t odp_tm); > > + > > +/** Shaper profile types and functions */ > > + > > +/** Possible values of running the shaper algorithm. > ODP_TM_SHAPER_GREEN > > + * means that the traffic is within the commit specification (rate and > > burst > > + * size), ODP_TM_SHAPER_YELLOW means that the traffic is within the peak > > + * specification (rate and burst size) and ODP_TM_SHAPER_RED means that > > the > > + * traffic is exceeding both its commit and peak specifications. Note > > that > > + * packets can also have an assigned <b> packet color</b> of > > ODP_PACKET_GREEN, > > + * ODP_PACKET_YELLOW or ODP_PACKET_RED which has a different meaning and > > + * purpose than the shaper colors. > > + */ > > +typedef enum { > > + ODP_TM_SHAPER_GREEN, ODP_TM_SHAPER_YELLOW, ODP_TM_SHAPER_RED > > +} odp_tm_shaper_color_t; > > + > > +/** The odp_tm_shaper_params_t record type is used to supply the > > parameters > > + * associated with a shaper profile. Since it is expected that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that odp_tm_shaper_params_init() > be > > + * called on variables of this type before any of the fields are filled > > in. > > + */ > > +typedef struct { > > + /** The committed information rate for this shaper profile. The > > units > > + * for this integer are always in bits per second. > > + */ > > + uint64_t commit_bps; > > + > > + /** The peak information rate for this shaper profile. The units > > for > > + * this integer are always in bits per second. > > + */ > > + uint64_t peak_bps; > > + > > + /** The commit burst tolerance for this shaper profile. The > units > > for > > + * this field are always bits. This value sets an upper limit for > the > > + * size of the commitCnt. > > + */ > > + uint32_t commit_burst; > > + > > + /** The peak burst tolerance for this shaper profile. The units > > for > > + * this field are always bits. This value sets an upper limit for > the > > + * size of the peakCnt. > > + */ > > + uint32_t peak_burst; > > + > > + /** The shaper_len_adjust is a value between -128 and 127 which > is > > + * directly added to the frame_len of a packet associated with this > > + * profile. The frame_len would normally include the outermost > > + * Ethernet header (DA, SA, ...) through to the outermost Ethernet > CRC > > + * inclusive. Hence this field - when non-zero - will usually be > set > > + * to a value approximating the "time" (in units of bytes) taken by > > + * the Ethernet preamble and Inter Frame Gap. Traditionally this > > + * would be the value 20 (8 + 12), but in same cases can be as low > as > > + * 9 (4 + 5). > > + */ > > + int8_t shaper_len_adjust; > > + > > + /** If dual_rate is TRUE it indicates the desire for the > > + * implementation to use dual rate shaping for packets associated > with > > + * this profile. The precise semantics of dual rate shaping are > > + * implementation specific, but in any case require a non-zero set > of > > + * both commit and peak parameters. > > + */ > > + odp_bool_t dual_rate; > > +} odp_tm_shaper_params_t; > > + > > +/** odp_tm_shaper_params_init() must be called to initialize any > > + * odp_tm_shaper_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_shaper_params_t record > which > > + * is to be initialized. > > + */ > > +void odp_tm_shaper_params_init(odp_tm_shaper_params_t *params); > > + > > +/** odp_tm_shaper_create() creates a shaper profile object, which can > > + * subsequently be attached to any number (including zero) of tm_queues > > + * or tm_nodes. > > + * > > + * @param[in] name Optional name associated with this shaper profile. > > Can > > + * be NULL. If non-NULL must be unique amongst the > set > > of > > + * all other shaper profiles. > > + * @param[in] params The profile parameters. See comments associated > > with > > + * the odp_tm_shaper_params_t for more details. > > + * @return Returns ODP_TM_INVALID upon failure, or the newly > > + * allocated odp_tm_shaper_t value representing this > > + * profile object. > > + */ > > +odp_tm_shaper_t odp_tm_shaper_create(const char *name, > > + odp_tm_shaper_params_t *params); > > + > > +/** odp_tm_shaper_params_read() "gets" the current set of values > > associated > > + * with the specified shaper profile object, and copies them into the > > supplied > > + * record. > > + * > > + * @param[in] shaper_profile Specifies the shaper profile object whose > > + * values are to be read. > > + * @param[out] params A pointer to an odp_tm_shaper_params_t > > record > > + * where the current shaper profile object > > values > > + * are copied to. > > + * @return Returns < 0 upon failure or 0 upon > success. > > + */ > > +int odp_tm_shaper_params_read(odp_tm_shaper_t shaper_profile, > > + odp_tm_shaper_params_t *params); > > + > > +/** odp_tm_shaper_params_update() "sets" the current set of values > > associated > > + * with the specified shaper profile object. In addition, this call has > > the > > + * effect that all tm_input's and tm_nodes that are associated > (attached?) > > + * with this shaper profile object will be updated with the new values. > > + * > > + * @param[in] shaper_profile Specifies the shaper profile object whose > > + * values are to be set. > > + * @param[in] params A pointer to an odp_tm_shaper_params_t > > record > > + * where the new shaper profile object values > > + * are taken from. > > + * @return Returns < 0 upon failure or 0 upon > success. > > + */ > > +int odp_tm_shaper_params_update(odp_tm_shaper_t shaper_profile, > > + odp_tm_shaper_params_t *params); > > + > > +/** odp_tm_shaper_lookup() can be used to find the shaper profile object > > + * created with the specified name. > > + * > > + * @param[in] name Name of a previously created shaper profile. Cannot > > be > > + * NULL. > > + * @return Returns ODP_TM_INVALID upon failure, or the shaper > > + * profile handle created with this name. > > + */ > > +odp_tm_shaper_t odp_tm_shaper_lookup(const char *name); > > + > > +/** Scheduler Profiles - types and functions */ > > + > > +/** The odp_tm_sched_mode_t type is used to control whether a tm_node > > + * scheduler takes into account packet lengths (by setting the > sched_mode > > to > > + * ODP_TM_BYTE_BASED_WEIGHTS) or instead treat packets with different > > lengths > > + * the same (by setting the sched_mode to ODP_TM_FRAME_BASED_WEIGHTS). > > + * Normally the sched_mode will be set to ODP_TM_BYTE_BASED_WEIGHTS, > > otherwise > > + * the scheduler becomes a weighted round robin scheduler. > > + */ > > +typedef enum { > > + ODP_TM_BYTE_BASED_WEIGHTS, /**< Use the packet length in > > + scheduler algorithm */ > > + ODP_TM_FRAME_BASED_WEIGHTS /**< Ignore the packet length */ > > +} odp_tm_sched_mode_t; > > + > > +/** The odp_tm_sched_params_t record type is used to supply the > parameters > > + * associated with a scheduler profile. Since it is expected that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that odp_tm_sched_params_init() be > > + * called on variables of this type before any of the fields are filled > > in. > > + */ > > +typedef struct { > > + /** sched_modes indicates whether weighted scheduling should be > > used > > + * or not - on a priority basis. > > + */ > > + odp_tm_sched_mode_t sched_modes[ODP_TM_MAX_PRIORITIES]; > > + > > + /** In the case that sched_modes for a given strict priority > level > > + * indicates the use of weighted scheduling, this field supplies the > > + * weighting factors. The weights - when defined - are used such > that > > + * the (adjusted) frame lengths are divided by these 8-bit weights > > + * (i.e. they are divisors and not multipliers). Consequently a > > + * weight of 0 (when sched_mode is ODP_TM_BYTE_BASED_WEIGHTS) is > > + * illegal. > > + */ > > + uint8_t sched_weights[ODP_TM_MAX_PRIORITIES]; > > +} odp_tm_sched_params_t; > > + > > +/** odp_tm_sched_params_init() must be called to initialize any > > + * odp_tm_sched_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_sched_params_t record which > > + * is to be initialized. > > + */ > > +void odp_tm_sched_params_init(odp_tm_sched_params_t *params); > > + > > +/** odp_tm_sched_create() creates a scheduler profile object, which can > > + * subsequently be attached to any number (including zero) of tm_nodes. > > + * > > + * @param[in] name Optional name associated with this scheduler > > profile. > > + * Can be NULL. If non-NULL must be unique amongst > the > > + * set of all other scheduler profiles. > > + * @param[in] params The profile parameters. See comments associated > > with > > + * the odp_tm_sched_params_t for more details. > > + * @return Returns ODP_TM_INVALID upon failure, or the newly > > + * allocated odp_tm_sched_t value representing this > > profile > > + * object. > > + */ > > +odp_tm_sched_t odp_tm_sched_create(const char *name, > > + odp_tm_sched_params_t *params); > > + > > +/** odp_tm_sched_params_read() "gets" the current set of values > associated > > + * with the specified scheduler profile object, and copies them into the > > + * supplied record. > > + * > > + * @param[in] sched_profile Specifies the scheduler profile whose > values > > + * are to be read. > > + * @param[out] params A pointer to an odp_tm_sched_params_t > record > > + * where the current scheduler profile object > > + * values are copied to. > > + * @return Returns < 0 upon failure or 0 upon > success. > > + */ > > +int odp_tm_sched_params_read(odp_tm_sched_t sched_profile, > > + odp_tm_sched_params_t *params); > > + > > +/** odp_tm_sched_params_update() "sets" the current set of values > > associated > > + * with the specified scheduler profile object. In addition, this call > > has > > + * the effect that all tm_nodes that are associated (attached?) with > this > > + * Scheduler profile object will be updated with the new values. > > + * > > + * @param[in] sched_profile Specifies the Scheduler profile object > whose > > + * values are to be set. > > + * @param[in] params A pointer to an odp_tm_sched_params_t > record > > + * where the new scheduler profile object > > values > > + * are taken from. > > + * @return Returns < 0 upon failure or 0 upon > success. > > + */ > > +int odp_tm_sched_params_update(odp_tm_sched_t sched_profile, > > + odp_tm_sched_params_t *params); > > + > > +/** odp_tm_sched_lookup() can be used to find the scheduler profile > object > > + * created with the specified name. > > + * > > + * @param[in] name Name of a previously created scheduler profile. > > Cannot be > > + * NULL. > > + * @return Returns ODP_TM_INVALID upon failure, or the > scheduler > > + * profile handle created with this name. > > + */ > > +odp_tm_sched_t odp_tm_sched_lookup(const char *name); > > + > > +/** Queue Threshold Profiles - types and functions */ > > + > > +/** The odp_tm_threshold_params_t record type is used to supply the > > parameters > > + * associated with a queue thresholds profile. Since it is expected > that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that > odp_tm_threshold_params_init() > > be > > + * called on variables of this type before any of the fields are filled > in > > + */ > > +typedef struct { > > + uint64_t max_pkts; /**< max pkt cnt for this threshold profile */ > > + uint64_t max_bytes; /**< max byte cnt for this threshold profile > */ > > + odp_bool_t enable_max_pkts; /**< TRUE if max_pkts is valid */ > > + odp_bool_t enable_max_bytes; /**< TRUE if max_bytes is valid */ > > +} odp_tm_threshold_params_t; > > + > > +/** odp_tm_threshold_params_init() must be called to initialize any > > + * odp_tm_threshold_params_t record before it is first used or assigned > > to. > > + * > > + * @param[in] params A pointer to an odp_tm_threshold_params_t record > > which > > + * is to be initialized. > > + */ > > +void odp_tm_threshold_params_init(odp_tm_threshold_params_t *params); > > + > > +/** odp_tm_threshold_create() creates a queue threshold profile object, > > which > > + * can subsequently be attached to any number (including zero) of > > tm_queues or > > + * tm_nodes. > > + * > > + * @param[in] name Optional name associated with this queue threshold > > + * profile. Can be NULL. If non-NULL must be unique > > + * amongst the set of all other queue threshold > > profiles. > > + * @param[in] params The profile parameters. See comments associated > > with > > + * the odp_tm_threshold_params_t for more details. > > + * @return Returns ODP_TM_INVALID upon failure, or the newly > > + * allocated odp_tm_threshold_t value representing > this > > + * profile object. > > + */ > > +odp_tm_threshold_t odp_tm_threshold_create(const char *name, > > + odp_tm_threshold_params_t > *params); > > + > > +/** odp_tm_thresholds_params_read() "gets" the current set of values > > associated > > + * with the specified queue thresholds profile object, and copies them > > into the > > + * supplied record. > > + * > > + * @param[in] threshold_profile Specifies the queue thresholds profile > > + * object whose values are to be read. > > + * @param[out] params A pointer to an > > odp_tm_threshold_params_t > > + * record where the current queue > > thresholds > > + * profile object values are copied to. > > + * @return Returns < 0 upon failure or 0 upon > > success. > > + */ > > +int odp_tm_thresholds_params_read(odp_tm_threshold_t threshold_profile, > > + odp_tm_threshold_params_t *params); > > + > > +/** odp_tm_thresholds_params_update() "sets" the current set of values > > + * associated with the specified queue thresholds profile object. In > > addition, > > + * this call has the effect that all tm_input's and tm_nodes that are > > + * associated (attached?) with this queue thresholds profile object will > > be > > + * updated with the new values. > > + * > > + * @param[in] threshold_profile Specifies the queue thresholds profile > > + * object whose values are to be set. > > + * @param[in] params A pointer to an > odp_tm_threshold_params_t > > + * record where the current queue > thresholds > > + * profile object values are taken from. > > + * @return Returns < 0 upon failure or 0 upon > > success. > > + */ > > +int odp_tm_thresholds_params_update(odp_tm_threshold_t > threshold_profile, > > + odp_tm_threshold_params_t *params); > > + > > +/** odp_tm_thresholds_lookup() can be used to find the queue thresholds > > + * profile object created with the specified name. > > + * > > + * @param[in] name Name of a previously created queue thresholds > profile. > > + * Cannot be NULL. > > + * @return Returns ODP_TM_INVALID upon failure, or the queue > > + * thresholds profile handle created with this name. > > + */ > > +odp_tm_threshold_t odp_tm_thresholds_lookup(const char *name); > > + > > +/** WRED Profiles - types and functions */ > > + > > +/** The odp_tm_wred_params_t record type is used to supply the > parameters > > + * associated with a Random Early Discard profile. Since it is expected > > that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that odp_tm_wred_params_init() be > > called > > + * on variables of this type before any of the fields are filled in. > > + */ > > +typedef struct { > > + /** When min_threshold is set to zero then single-slope WRED is > > + * enabled, as described in the description of med_threshold. > > + * Otherwise dual-slope WRED is enabled whereby the behavior depends > > + * on which of the following three cases exists: > > + * <ol> <li> queue > > + * fullness < min_threshold. In this case the drop probability is > > + * zero. > > + * <li> min_threshold <= queue fullness < med_threshold. In > > + * this case the drop probability increases linearly from zero until > > + * it reaches med_drop_prob at a queue fullness equal to > > + * med_threshold. > > + * <li> med_threshold <= queue fullness. In this case > > + * the drop probability increases linearly from med_drop_prob when > the > > + * queue fullness equals med_threshold until it reaches 100% with a > > + * drop probability of max_drop_prob. </ol> > > + */ > > + odp_tm_percent_t min_threshold; > > + > > + /** The meaning of med_threshold depends upon whether > single-slope > > or > > + * dual-slope WRED is being used or not. When min_threshold is 0 > then > > + * single-slope WRED is enabled in which case the med_threshold > value > > + * represents (as a percentage of max queue fullness) the point at > > + * which the drop probability starts increasing linearly from 0 > until > > + * it becomes equal to max_drop_prob when the queue fullness reaches > > + * 100%. See min_threshold comments for the case of dual-slope > WRED. > > + */ > > + odp_tm_percent_t med_threshold; > > + > > + /** The med_drop_prob is only used when dual-slope WRED is being > > used, > > + * in which case med_drop_prob MUST be < max_drop_prob. See > > + * min_threshold comments for more details. > > + */ > > + odp_tm_percent_t med_drop_prob; > > + > > + /** The max_drop_prob equals the drop probability when the queue > > + * fullness almost equals 100%. Of course once the queue fullness > is > > + * >= 100% of the max queue fullness, the drop probability > > + * discontinuously becomes 100%. > > + */ > > + odp_tm_percent_t max_drop_prob; > > + > > + /** When enable_wred is false, all tm_queues and tm_nodes that > are > > + * attached to this profile will not take part in a Random Early > > + * Discard algorithm. > > + */ > > + odp_bool_t enable_wred; > > + > > + /** When use_byte_fullness is true then WRED will use queue > memory > > + * usage as the fullness criterion, otherwise when use_byte_fullness > > + * is false, WRED will use the queue length (i.e. the number of > > + * packets in the queue) as the fullness criterion. Often will be > set > > + * to true for WRED profiles applied to tm_queues and set to false > for > > + * WRED profiles applied to tm_nodes. > > + */ > > + odp_bool_t use_byte_fullness; > > +} odp_tm_wred_params_t; > > + > > +/** odp_tm_wred_params_init() must be called to initialize any > > + * odp_tm_wred_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_wred_params_t record which > > + * is to be initialized. > > + */ > > +void odp_tm_wred_params_init(odp_tm_wred_params_t *params); > > + > > +/** odp_tm_wred_create() creates a WRED (Weighted Random Early Discard) > > + * profile object, which can subsequently be attached to any number > > (including > > + * zero) of tm_queues or tm_nodes. > > + * > > + * @param[in] name Optional name associated with this WRED profile. > > Can > > + * be NULL. If non-NULL must be unique amongst the > set > > of > > + * all other WRED profiles. > > + * @param[in] params The profile parameters. See comments associated > > with the > > + * odp_tm_wred_params_t for more details. > > + * @return Returns ODP_TM_INVALID upon failure, or the newly > > + * allocated odp_tm_wred_t value representing this > > profile > > + * object. > > + */ > > +odp_tm_wred_t odp_tm_wred_create(const char *name, > > + odp_tm_wred_params_t *params); > > + > > +/** odp_tm_wred_params_read() "gets" the current set of values > associated > > + * with the specified WRED profile object, and copies them into the > > supplied > > + * record. > > + * > > + * @param[in] wred_profile Specifies the WRED profile object whose > > + * values are to be read. > > + * @param[out] params A pointer to an odp_tm_wred_params_t record > > + * where the current WRED profile object > values > > + * are copied to. > > + * @return Returns < 0 upon failure or 0 upon success. > > + */ > > +int odp_tm_wred_params_read(odp_tm_wred_t wred_profile, > > + odp_tm_wred_params_t *params); > > + > > +/** odp_tm_wred_params_update() "sets" the current set of values > > associated > > + * with the specified WRED profile object. In addition, this call has > the > > + * effect that all tm_input's and tm_nodes that are associated > (attached?) > > + * with this WRED profile object will be updated with the new values. > > + * > > + * @param[in] wred_profile Specifies the WRED profile object whose > > + * values are to be set. > > + * @param[in] params A pointer to an odp_tm_wred_params_t record > > + * where the new WRED profile object values > > + * are taken from. > > + * @return Returns < 0 upon failure or 0 upon success. > > + */ > > +int odp_tm_wred_params_update(odp_tm_wred_t wred_profile, > > + odp_tm_wred_params_t *params); > > + > > +/** odp_tm_wred_lookup() can be used to find the WRED profile object > > created > > + * with the specified name. > > + * > > + * @param[in] name Name of a previously created WRED profile. Cannot > be > > + * NULL. > > + * @return Returns ODP_TM_INVALID upon failure, or the WRED > > + * profile handle created with this name. > > + */ > > +odp_tm_wred_t odp_tm_wred_lookup(const char *name); > > + > > +/** The odp_tm_node_params_t record type is used to hold extra > parameters > > when > > + * calling the odp_tm_node_create() function. Many of these fields are > > + * optional EXCEPT for max_fanin and level. Also since it is expected > > that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that odp_tm_node_params_init() be > > called > > + * on variables of this type before any of the fields are filled in. > > + */ > > +typedef struct { > > + /** The max_fan_in sets tha maximum number of src tm_queues and > > + * producer tm_nodes that can be simultaneously be connected to this > > + * tm_node as their destination. > > + */ > > + uint32_t max_fanin; > > + > > + /**> @todo uint8_t num_priorities; ? */ > > + > > + /** The shaper profile to be associated with this tm_node. Can > be > > + * ODP_TM_INVALID and can also be set and changed post-creation via > > + * odp_tm_node_shaper_config(); > > + */ > > + odp_tm_shaper_t shaper_profile; > > + > > + /** The threshold profile to be used in setting the max queue > > fullness > > + * for WRED and/or tail drop? Can be ODP_TM_INVALID and can also be > > + * set and changed post-creation via odp_tm_node_threshold_config(). > > + */ > > + odp_tm_threshold_t threshold_profile; > > + > > + /** The WRED profile(s) to be associated with this tm_node. Any > or > > + * all array elements can be ODP_TM_INVALID and can also be set and > > + * changed post-creation via odp_tm_node_wred_config(). > > + */ > > + odp_tm_wred_t wred_profile[ODP_NUM_PACKET_COLORS]; > > + > > + /** The level (or tm_node stage) sets the level for this tm_node > It > > + * must be in range 0..max_levels-1. Note that the tm_node topology > > + * is constrained such that only tm_node outputs with numerically > > + * greater levels may be connected to the fan-in of tm_node's with > > + * numerically smaller levels. > > + */ > > + uint8_t level; > > +} odp_tm_node_params_t; > > + > > +/** odp_tm_node_params_init() must be called to initialize any > > + * odp_tm_node_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_node_params_t record which > > + * is to be initialized. > > + */ > > +void odp_tm_node_params_init(odp_tm_node_params_t *params); > > + > > +/** Create an tm_node with a specific set of implemented strict priority > > + * levels as given by the priorities array parameter. The set of > priority > > + * levels does not have to "contiguous", but the "priorities" values for > > all > > + * indexes > max_priority MUST be FALSE. Note that the set of > implemented > > + * strict priority levels for an tm_node cannot be changed after tm_node > > + * creation. The level parameter MUST be in the range 0..max_level - 1. > > + * > > + * @param[in] odp_tm Odp_tm is used to identify the TM system into > which > > this > > + * odp_tm_node object is created. > > + * @param[in] name Optional name that can be used later later to find > > this > > + * same odp_tm_node_t. Can be NULL, otherwise must > be > > + * unique across all odp_tm_node objects. > > + * @param[in] params A pointer to a record holding (an extensible) set > of > > + * properties/attributes of this tm_node. > > + * @return Returns ODP_TM_INVALID upon failure, otherwise > > returns > > + * a valid odp_tm_node_t handleif successful. > > + */ > > +odp_tm_node_t odp_tm_node_create(odp_tm_t odp_tm, const char *name, > > + odp_tm_node_params_t *params); > > + > > +/** The odp_tm_node_shaper_config() function is used to dynamically set > or > > + * change the shaper profile associated with this tm_node. > > + * > > + * @param[in] tm_node Specifies the tm_node to be changed. > > + * @param[in] shaper_profile Specifies the shaper profile that should > > + * now be used for the shaper entity within > the > > + * given tm_node. Note that it is legal to > > specify > > + * ODP_TM_INVALID indicating that this > tm_node > > + * no longer implements a shaper function. > > + * @return Returns 0 upon success and < 0 upon > failure. > > + */ > > +int odp_tm_node_shaper_config(odp_tm_node_t tm_node, > > + odp_tm_shaper_t shaper_profile); > > + > > +/** The odp_tm_node_sched_config() function is used to dynamically set > or > > + * change the scheduler profile associated with a tm_node. > > + * > > + * @param[in] tm_node Specifies the tm_node to be changed. > > + * @param[in] tm_fan_in_node Specifies which of the specified tm_node's > > + * fan-in's weights etc are to be changed. > The > > + * fan-in is indentified by the > > "producer"/parent > > + * tm_node actually connected to this fan-in. > > + * @param[in] sched_profile Specifies the scheduler profile that > should > > + * now be used for the WFQ/RR entity within > the > > + * given tm_node. > > + * @return Returns 0 upon success and < 0 upon > failure. > > + */ > > +int odp_tm_node_sched_config(odp_tm_node_t tm_node, > > + odp_tm_node_t tm_fan_in_node, > > + odp_tm_sched_t sched_profile); > > + > > +/** The odp_tm_node_threshold_config() function is used to dynamically > set > > or > > + * change the queue threshold profile associated with this tm_node. > > + * > > + * @param[in] tm_node Specifies the tm_node to be changed. > > + * @param[in] thresholds_profile Specifies the queue threshold profile > > that > > + * should now be used for the given > > tm_node. > > + * @return Returns 0 upon success and < 0 upon > > failure. > > + */ > > +int odp_tm_node_threshold_config(odp_tm_node_t tm_node, > > + odp_tm_threshold_t thresholds_profile); > > + > > +/** The odp_tm_node_wred_config() function is used to dynamically set or > > + * change the WRED profile associated with this tm_node or > > tm_node/pkt_color > > + * combination. > > + * > > + * @param[in] tm_node Specifies the tm_node to be changed. > > + * @param[in] pkt_color Specifies the pkt_color that this profile is > > to be > > + * used with. Can also be the special value > > + * ALL_PKT_COLORS. > > + * @param[in] wred_profile Specifies the WRED profile that should now > be > > used > > + * by this tm_queue, when processing pkts of > this > > + * pkt_color. It can be the value > ODP_TM_INVALID > > + * indicating that this tm_queue/pkt_color > > combination > > + * no longer implements WRED. > > + * @return Returns 0 upon success and < 0 upon failure. > > + */ > > +int odp_tm_node_wred_config(odp_tm_node_t tm_node, > > + odp_packet_color_t pkt_color, > > + odp_tm_wred_t wred_profile); > > + > > +/** odp_tm_node_lookup() can be used to find the tm_node object created > > with > > + * the specified name. > > + * > > + * @param[in] odp_tm Odp_tm is used to identify the TM system into > which > > this > > + * odp_tm_node object is created. > > + * @param[in] name Name of a previously created tm_node. Cannot be > > + * NULL. > > + * @return Returns ODP_TM_INVALID upon failure, or the > tm_node > > + * handle created with this name. > > + */ > > +odp_tm_node_t odp_tm_node_lookup(odp_tm_t odp_tm, const char *name); > > + > > +/** The odp_tm_queue_params_t record type is used to hold extra > parameters > > + * when calling the odp_tm_queue_create() function. Many of these > fields > > are > > + * optional EXCEPT for priority. Also since it is expected that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that odp_tm_queue_params_init() be > > + * called on variables of this type before any of the fields are filled > > in. > > + */ > > +typedef struct { > > + /** The shaper profile to be associated with this tm_queue. Can > be > > + * ODP_TM_INVALID and can also be set and changed post-creation via > > + * odp_tm_queue_shaper_config(); > > + */ > > + odp_tm_shaper_t shaper_profile; > > + > > + /** The threshold profile to be used in setting the max queue > > fullness > > + * for WRED and/or tail drop? Can be ODP_TM_INVALID and can also be > > + * set and changed post-creation via > odp_tm_queue_threshold_config(). > > + */ > > + odp_tm_threshold_t threshold_profile; > > + > > + /** The WRED profile(s) to be associated with this tm_queue. Any > > or > > + * all array elements can be ODP_TM_INVALID and can also be set and > > + * changed post-creation via odp_tm_queue_wred_config(). > > + */ > > + odp_tm_wred_t wred_profile[ODP_NUM_PACKET_COLORS]; > > + > > + /** The strict priority level assigned to packets in this > tm_queue > > - > > + * in other words all packets associated with a given tm_queue MUST > > + * have the same single strict priority level and this level must be > > + * in the range 0..max_priority. > > + */ > > + uint8_t priority; > > +} odp_tm_queue_params_t; > > + > > +/** odp_tm_queue_params_init() must be called to initialize any > > + * odp_tm_queue_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_queue_params_t record which > > + * is to be initialized. > > + */ > > +void odp_tm_queue_params_init(odp_tm_queue_params_t *params); > > + > > +/** Create an tm_queue object. One can specify the maximum queue limits > > + * either as a maximum number of packets in the queue OR as a maximum > > number > > + * of bytes in the queue, or if both are specified, then whichever limit > > is > > + * hit first. Note that in the case of specifying the maximum queue > > memory > > + * size as bytes, the system is free to instead convert this byte value > > into a > > + * number of buffers and instead limit the queue memory usage by buffer > > counts > > + * versus strictly using byte counts. > > + * > > + * @param[in] odp_tm Odp_tm is used to identify the TM system into > which > > this > > + * odp_tm_queue object is created. > > + * @param[in] params A pointer to a record holding (an extensible) set > of > > + * properties/attributes of this tm_queue. > > + * @return Returns ODP_TM_INVALID upon failure, otherwise a > > valid > > + * odp_tm_queue_t handle. > > + */ > > +odp_tm_queue_t odp_tm_queue_create(odp_tm_t odp_tm, > > + odp_tm_queue_params_t *params); > > + > > +/** The odp_tm_queue_shaper_config() function is used to dynamically set > > + * or change the shaper profile associated with this tm_queue. > > + * > > + * @param[in] tm_queue Specifies the tm_queue to be changed. > > + * @param[in] shaper_profile Specifies the shaper profile that should > now > > be > > + * used for shaping the tm_queue's packet > > stream. > > + * Note that it is legal to specify > > ODP_TM_INVALID > > + * indicating that this tm_queue no longer > > + * implements a shaper function. > > + * @return Returns 0 upon success and < 0 upon > failure. > > + */ > > +int odp_tm_queue_shaper_config(odp_tm_queue_t tm_queue, > > + odp_tm_shaper_t shaper_profile); > > + > > +/** The odp_tm_queue_sched_config() function is used to dynamically set > or > > + * change the scheduler profile associated with a tm_node. Note that > > despite > > + * the name, this function affects a tm_node scheduler - specifically > the > > + * scheduler fan-in when such fan-in comes from an tm_queue. > > + * > > + * @param[in] tm_node Specifies the tm_node to be changed. > > + * @param[in] tm_fan_in_queue Specifies which of the specified tm_node's > > + * fan-in's weights etc are to be changed. > The > > + * fan-in is indentified by the > > "producer"/parent > > + * tm_queue actually connected to this > fan-in. > > + * @param[in] sched_profile Specifies the scheduler profile that > should > > + * now be used for the WFQ/RR entity within > the > > + * given tm_node. > > + * @return Returns 0 upon success and < 0 upon > failure. > > + */ > > +int odp_tm_queue_sched_config(odp_tm_node_t tm_node, > > + odp_tm_queue_t tm_fan_in_queue, > > + odp_tm_sched_t sched_profile); > > + > > +/** The odp_tm_queue_threshold_config() function is used to dynamically > > set or > > + * change the queue threshold profile associated with this tm_queue. > > + * > > + * @param[in] tm_queue Specifies the tm_queue to be changed. > > + * @param[in] thresholds_profile Specifies the queue threshold profile > > that > > + * should now be used for the given > > tm_queue. > > + * @return Returns 0 upon success and < 0 upon > > failure. > > + */ > > +int odp_tm_queue_threshold_config(odp_tm_queue_t tm_queue, > > + odp_tm_threshold_t thresholds_profile); > > + > > +/** odp_tm_queue_wred_config() function is used to dynamically set or > > change > > + * the WRED profile associated with this tm_queue or tm_queue/pkt_color > > + * combination. > > + * > > + * @param[in] tm_queue Specifies the tm_queue to be changed. > > + * @param[in] pkt_color Specifies the pkt_color that this profile is > > to be > > + * used with. Can also be the special value > > + * ALL_PKT_COLORS. > > + * @param[in] wred_profile Specifies the WRED profile that should now > be > > used > > + * by this tm_queue, when processing pkts of > this > > + * pkt_color. It can be the value > ODP_TM_INVALID > > + * indicating that this tm_queue/pkt_color > > combination > > + * no longer implements WRED. > > + * @return Returns 0 upon success and < 0 upon failure. > > + */ > > +int odp_tm_queue_wred_config(odp_tm_queue_t tm_queue, > > + odp_packet_color_t pkt_color, > > + odp_tm_wred_t wred_profile); > > + > > +/** Topology setting functions */ > > + > > +/** Connects the "output" of the src_tm_node to be a "producer" of the > > given > > + * dst_tm_node. Note that an ODP_TM_ROOT handle passed in for the > > + * dst_tm_node implies connection to the egress/root object of this TM > > system. > > + * > > + * @param[in] src_tm_node odp_tm_node_t handle of the tm_node whose > > output is > > + * to be connected to the fan-in of the next > > tm_node > > + * as represented by the dst_tm_node. > > + * @param[in] dst_tm_node odp_tm_node_t handle of the tm_node object > that > > will > > + * receive all of the pkt_descs from the src > > tm_node > > + * output. If ODP_TM_ROOT, then attachment is > to > > + * the root egress object/spigot. > > + * @return 0 upon success, < 0 on failure. > > + */ > > +int odp_tm_node_connect(odp_tm_node_t src_tm_node, odp_tm_node_t > > dst_tm_node); > > + > > +/** The odp_queue_connect() function connects the indicated tm_queue to > a > > + * parent tm_node or to the egress/root node. The tm_queue will then > > become > > + * one of the dst node's fan-in set. > > + * > > + * @param[in] tm_queue Specifies the tm_queue. > > + * @param[in] dst_tm_node odp_tm_node_t handle of the tm_node object > that > > will > > + * receive all of the pkt_descs from the src > > tm_node > > + * output. If ODP_TM_ROOT, then attachment is > to > > + * the root egress object/spigot. > > + * @return Returns 0 upon success and < 0 upon failure. > > + */ > > +int odp_tm_queue_connect(odp_tm_queue_t tm_queue, odp_tm_node_t > > dst_tm_node); > > + > > +/** Input API */ > > + > > +/** The odp_tm_enq() function is used to add packets to a given TM > system. > > + * Note that the System Metadata associated with the pkt needed by the > TM > > + * system is (a) a drop_eligible bit, (b) a two bit "pkt_color", (c) a > 16- > > bit > > + * pkt_len, and MAYBE? (d) a signed 8-bit shaper_len_adjust. > > + * > > + * If there is a non-zero shaper_len_adjust, then it is added to the > > pkt_len > > + * after any non-zero shaper_len_adjust that is part of the shaper > > profile. > > + * > > + * The pkt_color bits are a result of some earlier > > Metering/Marking/Policing > > + * processing (typically ingress based), and should not be confused with > > the > > + * shaper_color produced from the TM shaper entities within the > tm_inputs > > and > > + * tm_nodes. > > + * > > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the TM > > system). > > + * @param[in] pkt Handle to a packet. > > + * @return Returns 0 upon success, < 0 upon failure. One of > > the > > + * more common failure reasons is WRED dropage. > > + */ > > +int odp_tm_enq(odp_tm_queue_t tm_queue, odp_packet_t pkt); > > + > > +/** The odp_tm_enq_with_cnt() function behaves identically to > > odp_tm_enq(), > > + * except that it also returns (an approximation to?) the current > tm_queue > > + * packet queue count. > > + * > > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the TM > > system). > > + * @param[in] pkt Handle to a packet. > > + * @return Returns the number of packets previously > enqueued > > on > > + * this tm_queue upon success, < 0 upon failure. > > + */ > > +int odp_tm_enq_with_cnt(odp_tm_queue_t tm_queue, odp_packet_t pkt); > > + > > +/** Dynamic state query functions */ > > + > > +/** The following bit mask constants are used to refine the queue query > > + * functions defined below. > > + */ > > +#define ODP_TM_QUERY_PKT_CNT 0x01 /**< The total_pkt_cnt value */ > > +#define ODP_TM_QUERY_BYTE_CNT 0x02 /**< The total_byte_cnt value > */ > > +#define ODP_TM_QUERY_THRESHOLDS 0x04 /**< The thresholds??? */ > > + > > +/** The odp_tm_queue_info_t record type is used to return the various > > counts > > + * as requested by functions like odp_tm_queue_query() and > > + * odp_tm_total_query(). > > + */ > > +typedef struct { > > + /** The total_pkt_cnt field is the total number of packets > > currently > > + * stored/associated with the requested set of tm_queues. Note that > > + * because the packet queues are potentially being manipulated by > > + * multiple cpu's, the values here are only accurate when the tm > > + * system is "stopped" (i.e. the egress spigot is stopped and no > > + * odp_tm_enq calls are taking place). Implementations are free to > > + * batch update these counters - up to a dozen or so packets. > > + */ > > + uint64_t total_pkt_cnt; > > + > > + /** If the requested set of tm_queues has an odp_tm_threshold_t > > + * profile associated with it, then this is the max_pkt_cnt set in > the > > + * profile params. Returning this field is a convenience to the ODP > > + * programmer, enabling them to quickly see how the total_pkt_cnt > > + * compares to the maximum packet count threshold. Note that there > is > > + * no requirement that total_pkt_cnt be <= max_pkt_cnt. > > + */ > > + uint64_t max_pkt_cnt; > > + > > + /** The total_byte_cnt can either be the actual number of bytes > > used > > + * or an approximation of the number of bytes used based upon the > > + * number of fixed sized buffers used multiplied by the buffer size. > > + * In both cases the total_byte_cnt should correspond to the same > set > > + * of packets that were counted above. For instance, if the > > + * total_pkt_cnt is updated in a batch, then the total_byte_cnt > should > > + * also be updated in the same batch. The approx_byte_cnt field > below > > + * indicates whether the total_byte_cnt is buffer count based or > not. > > + * In the case that the number of bytes used by a packet is rounded > up > > + * to a 2, 4, 8, or 16 byte boundary, it is recommended that > > + * approx_byte_cnt be false. It is implementation dependent whether > > + * the byte count of a packet includes the CRC, but it is > recommended > > + * that it not include headroom, preamble or IPG. Of course when > the > > + * buffer counting method is used, it is expected that any headroom > in > > + * the first buffer is implicitly included. Finally in the case of > > + * variable length pkt based buffering, instead of taking the > > + * total_pkt_cnt and multiplying it by the maximum ethernet packet > > + * size, it is recommended that byte_cnt_valid be FALSE - even when > > + * query_flags includes ODP_TM_QUERY_BYTE_CNT. > > + */ > > + uint64_t total_byte_cnt; > > + > > + /** If the requested set of tm_queues has an odp_tm_threshold_t > > + * profile associated with it, then this is the max_byte_cnt set in > > + * the profile params. Returning this field is a convenience to the > > + * ODP programmer, enabling them to quickly see how the > total_byte_cnt > > + * compares to the maximum byte count threshold. Note that there is > > + * no requirement that total_byte_cnt be <= max_byte_cnt. > > + */ > > + uint64_t max_byte_cnt; > > + > > + /** The following boolean values indicate which of the counts > above > > + * are valid. Invalid count values must be 0. > > + */ > > + odp_bool_t total_pkt_cnt_valid; /**< TRUE if total_pkt_cnt is > valid > > */ > > + odp_bool_t max_pkt_cnt_valid; /**< TRUE if max_pkt_cnt is valid > */ > > + odp_bool_t total_byte_cnt_valid; /**< TRUE if total_byte_cnt is > valid > > */ > > + odp_bool_t max_byte_cnt_valid; /**< TRUE if max_byte_cnt is valid > > */ > > + > > + /** The approx_byte_cnt is TRUE if the total_byte_cnt field is > > valid > > + * AND if the buffer counting method is used. > > + */ > > + odp_bool_t approx_byte_cnt; > > +} odp_tm_queue_info_t; > > + > > +/** The odp_tm_queue_query() function can be used to check a single > > tm_queue's > > + * queue utilization. The query_flags indicate whether or not packet > > counts, > > + * byte counts or both are being requested. It is an error to request > > + * neither. The implementation may still return both sets of counts > > + * regardless of query_flags if the cost of returning all the counts is > > + * comparable to the cost of checking the query_flags. > > + * > > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the > > + * TM system). > > + * @param[out] query_flags A set of flag bits indicating which counters > > are > > + * being requested to be returned in the info > > record. > > + * @param[out] info Pointer to an odp_tm_queue_info_t record > where > > the > > + * requested queue info is returned. > > + * @return Returns 0 upon success, < 0 upon failure. > > + */ > > +int odp_tm_queue_query(odp_tm_queue_t tm_queue, > > + uint32_t query_flags, > > + odp_tm_queue_info_t *info); > > + > > +/** The odp_tm_priority_query() function can be used to check the queue > > + * utilization of all tm_queue's with the given priority. The > query_flags > > + * indicate whether or not packet counts, byte counts or both are being > > + * requested. It is an error to request neither. The implementation > may > > + * still return both sets of counts regardless of query_flags if the > cost > > of > > + * returning all the counts is comparable to the cost of checking the > > + * query_flags. > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + * @param[in] priority Supplies the strict priority level used to > > specify > > + * which tm_queues are included in the info > > values. > > + * @param[out] query_flags A set of flag bits indicating which counters > > are > > + * being requested to be returned in the info > > record. > > + * @param[out] info Pointer to an odp_tm_queue_info_t record > where > > the > > + * requested queue info is returned. > > + * @return Returns 0 upon success, < 0 upon failure. > > + */ > > +int odp_tm_priority_query(odp_tm_t odp_tm, uint8_t priority, > > + uint32_t query_flags, odp_tm_queue_info_t *info); > > + > > +/** The odp_tm_total_query() function can be used to check the queue > > + * utilization of all tm_queue's in a single TM system. The query_flags > > + * indicate whether or not packet counts, byte counts or both are being > > + * requested. It is an error to request neither. The implementation > may > > + * still return both sets of counts regardless of query_flags if the > cost > > of > > + * returning all the counts is comparable to the cost of checking the > > + * query_flags. > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + * @param[out] query_flags A set of flag bits indicating which counters > > are > > + * being requested to be returned in the info > > record. > > + * @param[out] info Pointer to an odp_tm_queue_info_t record > where > > the > > + * requested queue info is returned. > > + * @return Returns 0 upon success, < 0 upon failure. > > + */ > > +int odp_tm_total_query(odp_tm_t odp_tm, uint32_t query_flags, > > + odp_tm_queue_info_t *info); > > + > > +/** The odp_tm_priority_threshold_config() function is only used to > > associate > > + * a maximum packet count and/or a maximum byte count with a strict > > priority > > + * level - for the benefit of the odp_tm_priority_query() function. It > > has no > > + * semantic effects other than returning these queue threshold values in > > the > > + * odp_tm_queue_info_t record. > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + * @param[in] priority Supplies the strict priority level > that > > + * the threshold profile params are > > associated > > + * with. > > + * @param[in] thresholds_profile Specifies the queue threshold profile > > that > > + * should now be associated with the > > supplied > > + * strict priority level. > > + * @return Returns 0 upon success and < 0 upon > > failure. > > + */ > > +int odp_tm_priority_threshold_config(odp_tm_t odp_tm, uint8_t priority, > > + odp_tm_threshold_t > thresholds_profile); > > + > > +/** The odp_tm_total_threshold_config() function is only used to > associate > > a > > + * maximum packet count and/or a maximum byte count with a TM system - > for > > the > > + * benefit of the odp_tm_total_query() function. It has no semantic > > effects > > + * other than returning these queue threshold values in the > > + * odp_tm_queue_info_t record. > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + * @param[in] thresholds_profile Specifies the queue threshold profile > > that > > + * should now be used for the entire TM > > + * system. > > + * @return Returns 0 upon success and < 0 upon > > failure. > > + */ > > +int odp_tm_total_threshold_config(odp_tm_t odp_tm, > > + odp_tm_threshold_t thresholds_profile); > > + > > +/** Misc functions */ > > + > > +/** The odp_tm_periodic_update function is a placeholder for any > external > > + * source of periodic events. In some cases the TM system may already > > have an > > + * internal built-in source of periodic events - in which case calling > > this > > + * function has no effect. > > + */ > > +void odp_tm_periodic_update(void); > > + > > +/** The odp_tm_is_idle function is used to determine if the specified > ODP > > + * traffic management system still has "work" to do (i.e. has at least > one > > + * non-empty tm_queue and perhaps some outstanding timers etc). This > > function > > + * can be used by test programs and ODP applications that wish to know > > when > > + * TM system has completed its work - presumably after they have stopped > > + * sending in new pkts. Note that this function should not be called > > often > > + * since for some implementations this call could take a fairly long > time > > + * to execute! > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + * @return Returns 1 if the TM system is idle and 0 > otherwise. > > + */ > > +odp_bool_t odp_tm_is_idle(odp_tm_t odp_tm); > > + > > +/** The odp_tm_stats_print function is used to write implementation- > > defined > > + * information about the specified TM system to the ODP log. The > intended > > use > > + * is for debugging. > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + */ > > +void odp_tm_stats_print(odp_tm_t odp_tm); > > + > > +/** > > + * @} > > + */ > > + > > +#ifdef __cplusplus > > +} > > +#endif > > + > > +#endif > > diff --git a/platform/linux-generic/include/odp/plat/packet_types.h > > b/platform/linux-generic/include/odp/plat/packet_types.h > > index 45cb801..c3be633 100644 > > --- a/platform/linux-generic/include/odp/plat/packet_types.h > > +++ b/platform/linux-generic/include/odp/plat/packet_types.h > > @@ -36,6 +36,17 @@ typedef ODP_HANDLE_T(odp_packet_seg_t); > > > > #define ODP_PACKET_SEG_INVALID _odp_cast_scalar(odp_packet_seg_t, > > 0xffffffff) > > > > +/** odp_packet_color_t assigns names to the various pkt "colors" */ > > +typedef enum { > > + ODP_PACKET_GREEN = 0, > > + ODP_PACKET_YELLOW = 1, > > + ODP_PACKET_RED = 2, > > + ODP_PACKET_ALL_COLORS = 3, > > +} odp_packet_color_t; > > + > > +/** Sets the maximum number of pkt "colors" */ > > +#define ODP_NUM_PACKET_COLORS 3 > > + > > /** Get printable format of odp_packet_t */ > > static inline uint64_t odp_packet_to_u64(odp_packet_t hdl) > > { > > diff --git a/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > > b/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > > new file mode 100644 > > index 0000000..52df64b > > --- /dev/null > > +++ b/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > > @@ -0,0 +1,185 @@ > > +/* Copyright (c) 2015, Linaro Limited > > + * All rights reserved. > > + * > > + * SPDX-License-Identifier: BSD-3-Clause > > + */ > > + > > +/** > > + * @file > > + * > > + * ODP traffic mngr > > + */ > > + > > +#ifndef ODP_TRAFFIC_MNGR_TYPES_H_ > > +#define ODP_TRAFFIC_MNGR_TYPES_H_ > > + > > +#ifdef __cplusplus > > +extern "C" { > > +#endif > > + > > +#include <odp/std_types.h> > > +#include <odp/plat/strong_types.h> > > + > > +/** @addtogroup odp_traffic_mngr > > + * Macros and operations on a TM system. > > + * @{ > > + */ > > + > > +/** The ODP_TM_MAX_NUM_SYSTEMS constant specifies the maximum number of > TM > > + * systems that may be created. On some platforms this might be much > more > > + * limited to as little as one hardware TM system. > > + */ > > +#define ODP_TM_MAX_NUM_SYSTEMS 64 > > + > > +/** The ODP_TM_MAX_PRIORITIES constant specifies the largest range of > > + * priorities that any TM system can support. All strict priority > values > > MUST > > + * in the range 0..ODP_TM_MAX_PRIORITIES-1. > > + */ > > +#define ODP_TM_MAX_PRIORITIES 16 > > + > > +/** The ODP_TM MAX_LEVELS constant specifies the largest range of > > + * tm_node levels that any TM system can support. Hence all tm_node > level > > + * values MUST be in the range 0..ODP_TM_MAX_LEVELS-1. Smaller tm_node > > + * levels are associated with tm_nodes closer to the TM system egress. > > + */ > > +#define ODP_TM_MAX_LEVELS 8 > > + > > +/** > > + * The smallest SCHED weight is 1 (i.e. 0 is not a legal WFQ/WRR value). > > + */ > > +#define ODP_TM_MIN_SCHED_WEIGHT 1 > > + > > +/** The ODP_TM_MAX_SCHED_WEIGHT constant is the largest weight any TM > > system > > + * can support (at least from a configuration standpoint). A given TM > > system > > + * could have a smaller value. > > + */ > > +#define ODP_TM_MAX_SCHED_WEIGHT 255 > > + > > +/** The ODP_TM_MAX_TM_QUEUES constant is the largest number of tm_queues > > + * that can handled by any one TM system. > > + */ > > +#define ODP_TM_MAX_TM_QUEUES (16 * 1024 * 1024) > > + > > +/** The ODP_TM_MAX_NUM_OUTPUTS constant is the largest number of outputs > > that > > + * can be configured for any one TM system. > > + */ > > +#define ODP_TM_MAX_NUM_OUTPUTS 256 > > + > > +/** The ODP_TM_MAX_NUM_TM_NODES constant is the largest number of > tm_nodes > > that > > + * can be in existence for any one TM system. > > + */ > > +#define ODP_TM_MAX_NUM_TM_NODES (1024 * 1024) > > + > > +/** The ODP_TM_MAX_TM_NODE_FANIN constant is the largest number of > fan-in > > + * "inputs" that can be simultaneously connected to a single tm_node. > > + * *TBD* Does this need to be as large as ODP_TM_MAX_TM_QUEUES? *TBD* > > + */ > > +#define ODP_TM_MAX_TM_NODE_FANIN (1024 * 1024) > > + > > +/** The ODP_TM_MIN_SHAPER_BW constant is the smallest amount of > bandwidth > > that > > + * can a shaper's peak or commit rate can be set to. It is in units of > > + * 1000 bytes/second so that it and the ODP_TM_MAX_SHAPER_BW can both > fit > > in > > + * 32 bits. > > + */ > > +#define ODP_TM_MIN_SHAPER_BW 1 > > + > > +/** The ODP_TM_MAX_SHAPER_BW constant is the largest amound of bandwidth > > that > > + * any shaper's peak or commit rate can be set to. It is in units of > > + * 1000 bytes/second so that it and the ODP_TM_MIN_SHAPER_BW can both > fit > > in > > + * 32 bits. > > + */ > > +#define ODP_TM_MAX_SHAPER_BW 12500000 > > + > > +/** The ODP_NUM_SHAPER_COLORS constant just counts the number of > > enumeration > > + * values defined in the odp_tm_shaper_color_t type. > > + */ > > +#define ODP_NUM_SHAPER_COLORS 3 > > + > > +/** The INVALID_PRIORITY constant is used when one needs to indicate an > > + * invalid priority value. > > + */ > > +#define ODP_TM_INVALID_PRIORITY 255 > > + > > +/** The odp_tm_percent_t type is used when specifying fields that are > > + * percentages. It is a fixed point integer whose units are 1/100 of a > > + * percent. Hence 100% is represented as the integer value 10000. Note > > + * that because it is often used as a ratio of the current queue value > and > > + * maximum queue threshold, it can be > 100%, but in any event will > never > > + * be larger than 500% (i.e. it MUST be capped at 50000). > > + */ > > +typedef uint16_t odp_tm_percent_t; > > + > > +/** The odp_tm_handle_t type is a generic type that can stand for any of > > the > > + * other ODP_TM handle types. > > + */ > > +typedef uint64_t odp_tm_handle_t; > > + > > +/** Each odp_tm_t value represents a specific TM system. Almost all > > + * functions in this API require a odp_tm_t value - either directly > > + * as a function parameter or indirectly by having another ODP TM handle > > value > > + * as a function parameter. > > + */ > > +typedef odp_tm_handle_t odp_tm_t; > > + > > +/** Each odp_tm_queue_t value is an opaque ODP handle representing a > > specific > > + * tm_queue within a specific TM system. > > + */ > > +typedef odp_tm_handle_t odp_tm_queue_t; > > + > > +/** Each odp_tm_node_t value is an opaque ODP handle representing a > > specific > > + * tm_node within a specific TM system. > > + */ > > +typedef odp_tm_handle_t odp_tm_node_t; > > + > > +/** Each odp_tm_shaper_t value is an opaque ODP handle representing a > > specific > > + * shaper profile usable across all TM systems described by this API. A > > given > > + * shaper profile can then be attached to any tm_queue or tm_node. > > + */ > > +typedef odp_tm_handle_t odp_tm_shaper_t; > > + > > +/** Each odp_tm_sched_t value is an opaque ODP handle representing a > > specific > > + * tm_node scheduler profile usable across all TM systems described by > > this > > + * API. A given tm_node scheduler profile can then be attached to any > > tm_node. > > + */ > > +typedef odp_tm_handle_t odp_tm_sched_t; > > + > > +/** Each odp_tm_threshold_t value is an opaque ODP handle representing a > > + * specific queue threshold profile usable across all TM systems > described > > by > > + * this API. A given queue threshold profile can then be attached to > any > > + * tm_queue or tm_node. > > + */ > > +typedef odp_tm_handle_t odp_tm_threshold_t; > > + > > +/** Each odp_tm_wred_t value is an opaque ODP handle representing a > > specific > > + * WRED profile usable across all TM systems described by this API. A > > given > > + * WRED profile can then be attached to any tm_queue or tm_node. > > + */ > > +typedef odp_tm_handle_t odp_tm_wred_t; > > + > > +/** The ODP_TM_INVALID constant can be used with any ODP TM handle type > > and > > + * indicates that this value does NOT represent a valid TM object. > > + */ > > +#define ODP_TM_INVALID 0 > > + > > +/** > > + * @def ODP_TM_ROOT > > + * Constant that is used to refer to the egress/root node of the TM > > subsystem's > > + * tree/hierarchy of nodes. > > + */ > > +#define ODP_TM_ROOT 0 > > + > > +/** Get printable format of odp_queue_t */ > > +static inline uint64_t odp_tm_handle_to_u64(odp_tm_handle_t hdl) > > +{ > > + return hdl; > > +} > > + > > +/** > > + * @} > > + */ > > + > > +#ifdef __cplusplus > > +} > > +#endif > > + > > +#endif > > diff --git a/platform/linux-generic/include/odp/traffic_mngr.h > > b/platform/linux-generic/include/odp/traffic_mngr.h > > new file mode 100644 > > index 0000000..3aa6267 > > --- /dev/null > > +++ b/platform/linux-generic/include/odp/traffic_mngr.h > > @@ -0,0 +1,35 @@ > > +/* Copyright (c) 2015, Linaro Limited > > + * All rights reserved. > > + * > > + * SPDX-License-Identifier: BSD-3-Clause > > + */ > > + > > +/** > > + * @file > > + * > > + * ODP Traffic manager > > + */ > > + > > +#ifndef ODP_PLAT_TRAFFIC_MNGR_H_ > > +#define ODP_PLAT_TRAFFIC_MNGR_H_ > > + > > +#ifdef __cplusplus > > +extern "C" { > > +#endif > > + > > +/** @ingroup odp_traffic_mngr > > + * @{ > > + */ > > + > > +/** > > + * @} > > + */ > > + > > +#include <odp/plat/traffic_mngr_types.h> > > +#include <odp/api/traffic_mngr.h> > > + > > +#ifdef __cplusplus > > +} > > +#endif > > + > > +#endif > > diff --git a/platform/linux-generic/include/odp_packet_internal.h > > b/platform/linux-generic/include/odp_packet_internal.h > > index ba2cd7e..d3eaad0 100644 > > --- a/platform/linux-generic/include/odp_packet_internal.h > > +++ b/platform/linux-generic/include/odp_packet_internal.h > > @@ -61,6 +61,9 @@ typedef union { > > uint32_t tcpopt:1; /**< TCP options present */ > > uint32_t sctp:1; /**< SCTP */ > > uint32_t icmp:1; /**< ICMP */ > > + > > + uint32_t color:2; /**< Packet color for traffic mgmt */ > > + uint32_t nodrop:1; /**< Drop eligibility status */ > > }; > > } input_flags_t; > > > > @@ -102,6 +105,8 @@ typedef union { > > uint32_t l3_chksum:1; /**< L3 chksum override */ > > uint32_t l4_chksum_set:1; /**< L3 chksum bit is valid */ > > uint32_t l4_chksum:1; /**< L4 chksum override */ > > + > > + int8_t shaper_len_adj; /**< adjustment for traffic mgr > */ > > }; > > } output_flags_t; > > > > -- > > 2.1.4 > > > > _______________________________________________ > > lng-odp mailing list > > lng-odp@lists.linaro.org > > https://lists.linaro.org/mailman/listinfo/lng-odp >
OK. Didn’t try, I was just wondering if @def is correct keyword for enum values. -Petri From: EXT Bill Fischofer [mailto:bill.fischofer@linaro.org] Sent: Friday, October 23, 2015 1:34 PM To: Savolainen, Petri (Nokia - FI/Espoo) Cc: lng-odp@lists.linaro.org; Barry Spinney Subject: Re: [lng-odp] [API-NEXT PATCHv6 1/4] api: tm: add tm API definitions They seem to show up just fine under the enumerations of the packet section. What issues do you see? On Fri, Oct 23, 2015 at 3:12 AM, Savolainen, Petri (Nokia - FI/Espoo) <petri.savolainen@nokia.com<mailto:petri.savolainen@nokia.com>> wrote: Reviewed-by: Petri Savolainen <petri.savolainen@nokia.com<mailto:petri.savolainen@nokia.com>> Bill, did you run 'make doxygen-html'? Not sure if @def ODP_PACKET_GREEN works when it's actually an enum. Anyway, it's in the correct file now. -Petri > -----Original Message----- > From: lng-odp [mailto:lng-odp-bounces@lists.linaro.org<mailto:lng-odp-bounces@lists.linaro.org>] On Behalf Of EXT > Bill Fischofer > Sent: Thursday, October 22, 2015 11:44 PM > To: lng-odp@lists.linaro.org<mailto:lng-odp@lists.linaro.org> > Cc: Barry Spinney > Subject: [lng-odp] [API-NEXT PATCHv6 1/4] api: tm: add tm API definitions > > From: Barry Spinney <spinney@ezchip.com<mailto:spinney@ezchip.com>> > > This introduces an API for configuring and using Traffic Management > systems. > > The purpose of this API is as a general packet scheduling system that > accepts packets from input queues and applies strict priority > scheduling, weighted fair queuing scheduling and/or bandwidth controls > to decide which input packet should be chosen as the next output > packet and when this output packet can be sent onwards. > > Signed-off-by: Barry Spinney <spinney@ezchip.com<mailto:spinney@ezchip.com>> > Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org<mailto:bill.fischofer@linaro.org>> > --- > include/odp.h | 1 + > include/odp/api/packet.h | 69 + > include/odp/api/traffic_mngr.h | 1611 > ++++++++++++++++++++ > .../linux-generic/include/odp/plat/packet_types.h | 11 + > .../include/odp/plat/traffic_mngr_types.h | 185 +++ > platform/linux-generic/include/odp/traffic_mngr.h | 35 + > .../linux-generic/include/odp_packet_internal.h | 5 + > 7 files changed, 1917 insertions(+) > create mode 100644 include/odp/api/traffic_mngr.h > create mode 100644 platform/linux- > generic/include/odp/plat/traffic_mngr_types.h > create mode 100644 platform/linux-generic/include/odp/traffic_mngr.h > > diff --git a/include/odp.h b/include/odp.h > index 825c7e1..f6a6ea9 100644 > --- a/include/odp.h > +++ b/include/odp.h > @@ -56,6 +56,7 @@ extern "C" { > #include <odp/thrmask.h> > #include <odp/spinlock_recursive.h> > #include <odp/rwlock_recursive.h> > +#include <odp/traffic_mngr.h> > > #ifdef __cplusplus > } > diff --git a/include/odp/api/packet.h b/include/odp/api/packet.h > index 5d46b7b..0680b3f 100644 > --- a/include/odp/api/packet.h > +++ b/include/odp/api/packet.h > @@ -48,6 +48,26 @@ extern "C" { > * Invalid packet segment > */ > > + /** > + * @typedef odp_packet_color_t > + * Color of packet for shaper/drop processing > + */ > + > + /** > + * @def ODP_PACKET_GREEN > + * Packet is green > + */ > + > + /** > + * @def ODP_PACKET_YELLOW > + * Packet is yellow > + */ > + > + /** > + * @def ODP_PACKET_RED > + * Packet is red > + */ > + > /* > * > * Alloc and free > @@ -700,6 +720,55 @@ odp_packet_seg_t odp_packet_last_seg(odp_packet_t > pkt); > */ > odp_packet_seg_t odp_packet_next_seg(odp_packet_t pkt, odp_packet_seg_t > seg); > > +/** > + * Get packet color > + * > + * @param pkt Packet handle > + * @return packet color > + */ > +odp_packet_color_t odp_packet_color(odp_packet_t pkt); > + > +/** > + * Set packet color > + * > + * @param pkt Packet handle > + * @param color Color to set > + */ > +void odp_packet_color_set(odp_packet_t pkt, odp_packet_color_t color); > + > +/** > + * Get drop eligible status > + * > + * @param pkt Packet handle > + * @return Packet drop eligibility status > + * @retval 0 Packet is not drop eligible > + * @retval 1 Packet is drop > + */ > +odp_bool_t odp_packet_drop_eligible(odp_packet_t pkt); > + > +/** > + * Set drop eligible status > + * > + * @param pkt Packet handle > + * @param status Drop eligibility status > + */ > +void odp_packet_drop_eligible_set(odp_packet_t pkt, odp_bool_t status); > + > +/** > + * Get shaper length adjustment > + * > + * @param pkt Packet handle > + * @return Shaper adjustment (-128..127) > + */ > +int8_t odp_packet_shaper_len_adjust(odp_packet_t pkt); > + > +/** > + * Set shaper length adjustment > + * > + * @param pkt Packet handle > + * @param adj Signed adjustment value > + */ > +void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, int8_t adj); > > /* > * > diff --git a/include/odp/api/traffic_mngr.h > b/include/odp/api/traffic_mngr.h > new file mode 100644 > index 0000000..2459a8b > --- /dev/null > +++ b/include/odp/api/traffic_mngr.h > @@ -0,0 +1,1611 @@ > +/** Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#ifndef ODP_TRAFFIC_MNGR_H_ > +#define ODP_TRAFFIC_MNGR_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include <odp/std_types.h> > +#include <odp/packet_io.h> > + > +/** > + * @file > + * > + */ > + > +/** @defgroup odp_traffic_mngr ODP TRAFFIC MNGR > + * @{ > + * > + * An API for configuring and using Traffic Management systems > + * > + * This file forms a simple interface for creating, configuring and using > + * Traffic Management (TM) subsystems. By TM subsystem it is meant a > general > + * packet scheduling system that accepts packets from input queues and > applies > + * strict priority scheduling, weighted fair queueing scheduling and/or > + * bandwidth controls to decide which input packet should be chosen as the > + * next output packet and when this output packet can be sent onwards. > + * > + * A given platform supporting this TM API could support one or more pure > + * hardware based packet scheduling systems, one or more pure software > + * based systems or one or more hybrid systems - where because of > + * hardware constraints some of the packet scheduling is done in hardware > + * and some is done in software. In addition, there may also be > additional > + * API's beyond those described here for (a) controlling advanced > capabilities > + * supported by specific hardware, software or hybrid subsystems or (b) > + * dealing with constraints and limitations of specific implementations. > + * The intention here is to be the simplest API that covers the vast > majority > + * of packet scheduling requirements. > + * > + * Often a TM subsystem's output(s) will be directly connected > + * to a device's physical (or virtual) output interfaces/links, in which > case > + * sometimes such a system will be called an Egress Packet Scheduler or an > + * Output Link Shaper, etc.. While the TM subsystems configured by this > API > + * can be used in such a way, this API equally well supports the ability > to > + * have the TM subsystem's outputs connect to other TM subsystem input > queues > + * or general software queues or even some combination of these three > cases. > + * > + * <H2>TM Algorithms</H2> > + * > + * The packet scheduling/dropping techniques that can be applied to input > + * traffic include any mixture of the following: > + * <ol> > + * <li> Strict Priority scheduling. > + * <li> Weighted Fair Queueing scheduling (WFQ). > + * <li> Bandwidth Shaping. > + * <li> Weighted Random Early Discard (WRED). > + * </ol> > + * Note that Bandwidth Shaping is the only feature that can cause packets > + * to be "delayed", and Weighted Random Early Discard is the only feature > + * (other than input queues becoming full) that can cause packets to be > + * dropped. > + * > + * <H3>Strict Priority Scheduling</H3> > + * Strict Priority Scheduling (or just priority for short), is a technique > + * where input queues and the packets from them, are assigned a priority > + * value in the range 0 .. ODP_TM_MAX_PRIORITIES - 1. At all times > packets > + * the the smallest priority value will be chosen ahead of packets with a > + * numerically larger priority value. This is called strict priority > + * scheduling because the algorithm strictly enforces the scheduling of > + * higher priority packets over lower priority packets. > + * > + * <H3>Bandwidth Shaping</H3> > + * Bandwidth Shaping (or often just Shaping) is the term used here for the > + * idea of controlling packet rates using single rate and/or dual rate > token > + * bucket algorithms. For single rate shaping a rate (the commit rate) > and > + * a "burst size" (the maximum commit count) are configured. Then an > + * internal signed integer counter called the commitCnt is maintained such > + * that if the commitCnt is positive then packets are eligible to be sent. > + * When such a packet is actually sent then its commitCnt is decremented > + * (usually by its length, but one could decrement by 1 for each packet > + * instead). The commitCnt is then incremented periodically based upon > the > + * configured rate, so that this technique causes the traffic to be > limited > + * to the commit rate over the long term, while allowing some ability to > + * exceed this rate for a very short time (based on the burst size) in > order > + * to catch up if the traffic input temporarily drops below the commit > rate. > + * > + * Dual Rate Shaping is designed to allow certain traffic flows to fairly > + * send more than their assigned commit rate when the scheduler has > excess > + * capacity. The idea being that it may be better to allow some types of > + * traffic to send more than their committed bandwidth rather than letting > + * the TM outputs be idle. The configuration of Dual Rate Shaping > requires > + * additionally a peak rate and a peak burst size. The peak rate must be > + * greater than the related comls mit rate, but the burst sizes have no > similar > + * constraint. Also for every input priority that has Dual Rate shaping > + * enabled, there needs to be an additional equal or lower priority (equal > or > + * higher numeric priority value) assigned. Then if the traffic exceeds > its > + * commit rate but not its peak rate, the "excess" traffic will be sent at > the > + * lower priority level - which by the strict priority algorithm should > + * cause no degradation of the higher priority traffic, while allowing for > + * less idle outputs. > + * > + * <H3>Weighted Fair Queuing</H3> > + * Weighted Fair Queuing (WFQ) is used to arbitrate amongst multiple input > + * packets with the same priority. Each input can be assigned a weight in > the > + * range MIN_WFQ_WEIGHT..MAX_WFQ_WEIGHT (nominally 1..255) that affects > the way > + * the algorithm chooses the next packet. If all of the weights are equal > AND > + * all of the input packets are the same length then the algorithm is > + * equivalent to a round robin scheduling. If all of the weights are > equal > + * but the packets have different lengths then the WFQ algorithm will > attempt > + * to choose the packet such that inputs each get a fair share of the > + * bandwidth - in other words it implements a weighted round robin > algorithm > + * where the weighting is based on frame length. > + * > + * When the input weights are not all equal and the input packet lengths > vary > + * then the WFQ algorithm will schedule packets such that the packet with > + * the lowest "Virtual Finish Time" is chosen first. An input packet's > + * Virtual Finish Time is roughly calculated based on the WFQ object's > base > + * Virtual Finish Time when the packet becomes the first packet in its > queue > + * plus its frame length divided by its weight. > + * @code > + * virtualFinishTime = wfqVirtualTimeBase + (pktLength / wfqWeight) > + * @endcode > + * In a system running at full capacity with no bandwidth limits - over > the > + * long term - each input fan-in's average transmit rate will be the same > + * fraction of the output bandwidth as the fraction of its weight divided > by > + * the sum of all of the WFQ fan-in weights. Hence larger WFQ weights > result > + * in better "service" for a given fan-in. > + * @code > + * totalWfqWeight = 0; > + * for (each fan-in entity - fanIn - feeding this WFQ scheduler) > + * totalWfqWeight += fanIn->sfqWeight; > + * > + * fanIn->avgTransmitRate = avgOutputRate * fanIn->sfqWeight / > totalWfqWeight; > + * @endcode > + * > + * <H3>Weighted Random Early Discard</H3> > + * The Weighted Random Early Discard (WRED) algorithm deals with the > situation > + * where an input packet rate exceeds some output rate (including > + * the case where Bandwidth Shaping limits some output rates). Without > WRED > + * enabled and configured, the TM system will just implement a tail > dropping > + * scheme whereby whichever packet is unlucky enough to arrive when an TM > + * input queue is full will be discarded regardless of priority or any > other > + * consideration. > + * WRED allows one to configure the system to use a better/fairer > algorithm > + * than simple tail dropping. It works by measuring the "fullness" of > + * various packet queues and converting this percentage into a probability > + * of random packet dropping with the help of some configurable > parameters. > + * Then a random number is picked and together with the drop probability, > + * a decision is made to accept the packet or drop it. > + * A basic parameterization of WRED requires three parameters: > + * <ol> > + * <li> the maximum queue level (which could be either a maximum number of > + * packets or a maximum amount of memory (i.e. bytes/buffers) used), > + * <li> a starting threshold - which is a number in the range 0..100 > + * representing a percentage of the maximum queue level at which the > + * drop probability becomes non-zero, > + * <li> a drop probability - which is a number in the range 0..100 > + * representing a probability (0 means no drop and 100 means > + * certain drop) - which is used when the queue is near 100% full. > + * </ol> > + * > + * Note that all packet drops for a TM system only occur when a new packet > + * arrives at a given TM system input queue. At that time either the WRED > + * algorithm, if enabled for this input queue, or the "input queue full" > + * tail drop algorithm will make a drop/no drop decision. After this > point, > + * any packets not dropped, will at some point be sent out a TM output - > + * assuming that the topology is fully connected and enabled. > + * > + * <H2>Hierarchical Scheduling and tm_nodes</H2> > + * This API supports the ability to do Hierarchical Scheduling whereby the > + * final scheduling decision is controlled by equal priority schedulers, > + * strict priority multiplexers, bandwidth shapers - at multiple levels - > all > + * forming a tree rooted at a single egress object. In other words, all > + * tm_queues and tm_nodes have the property that their logical "output" > feeds > + * into one fan-in of a subsequent tm_node or egresss object - forming a > proper > + * tree. See the following link - > + * <A HREF="diagram1.svg">Example Tm_node</A> - for an example. > + * > + * Multi-level/hierarchical scheduling adds both great control and > significant > + * complexity. Logically, despite the implication of the tm_node tree > + * diagrams, there are no queues between the levels of hierarchy. Instead > all > + * packets are held in their input queue, until such time that the > totality of > + * all of the tm_nodes in the single path from input queue to output > object > + * agrees that this packet should be the next to be chosen to leave the TM > + * system through the output object "portal". Hence what flows from level > to > + * level is the "local choice" of what packet/tm_queue should next be > + * serviced. > + * > + * <H3>tm_nodes</H3> > + * Tm_nodes are the main "entity"/object that a TM system is composed of. > + * Each tm_node is a mini-TM subsystem of its own, but the interconnection > + * and interplay of a multi-level "tree" of tm_nodes can allow the user > + * to specify some very sophisticated behaviours. > + * Each tm_node can contain a set of scheduler (one per strict priority > level), > + * a strict priority multiplexer, a bandwidth shaper and a WRED component > - or > + * a subset of these. > + * > + * In its full generality an tm_node consists of a set of "fan-in" > connections > + * to preceding tm_queues or tm_nodes. The fan-in for a single tm_node > + * can range from 1 to many many thousands. This fan-in is divided first > + * into a WFQ scheduler per priority level. So if 4 priority levels are > + * implemented by this tm_node, there would be 4 WFQ schedulers - each > with > + * its own unique fan-in. After the WFQ schedulers a priority chooser > comes > + * next - where it will always choose the highest priority WFQ output > + * available. The output of the priority chooser then feeds a bandwidth > + * shaper function which then finally uses the shaper's propagation table > + * to determine its output packet and its priority. This output could > + * then be remapped via a priority map profile and then becomes one of the > + * input fan-in to perhaps another level of tm_nodes, and so on. > + * > + * During this process it is important to remember that the bandwidth > shaping > + * function never causes packets to be dropped. Instead all packet drops > + * occur because of tm_queue fullness or be running the WRED algorithm > + * at the time a new packet attempts to be appended to the end of some > + * input queue. > + * > + * The WRED profile associated with an tm_node considers the entire set of > + * tm_queues feeding directly or indirectly into it as its measure of > + * queue fullness. > + * > + * <H3>tm_queues</H3> > + * tm_queues are the second major type of "entity"/object that a TM > + * system is composed of. All packets MUST first enter the TM system via > + * some tm_queue. Then logically, the head packets of all of the > tm_queues > + * are examined simultaneously by the entire TM system, and ONE tm_queue > is > + * chosen send its head packet out of the TM system's egress. Abstractly > + * packets stay in the tm_queue until they are chosen at which time they > are > + * instantly transferred from tm_queue to/through the corresponding TM > egress. > + * It is also important to note that packets in the same tm_queue MUST > always > + * stay in order. In other words, the second packet in an tm_queue must > never > + * leave the TM system through a TM egress spigot before the first packet > has > + * left the system. So tm_queue packet order must always be maintained. > + * > + * <H3>TM egress</H3> > + * Note that TM egress objects are NOT referred to as queues, because in > + * many/most cases they don't have multi-packet structure but instead are > + * viewed as a port/spigot through which the TM system schedules and > finally > + * transfers input packets through. > + * > + * <H2>Ideal versus Actual Behavior</H2> > + * It is important to recognize the difference between the "abstract" > + * mathematical model of the prescribed behavior and real implementations. > + * The model describes the Ideal, but theoretically desired behavior, but > such > + * an Ideal is generally not practical to implement. Instead, one > understands > + * that virtually all Real TM systems attempt to approximate the Ideal > behavior > + * as given by the TM configuration as best as they can - while still > + * attaining high packet processing performance. The idea is that instead > of > + * trying too hard to be "perfect" at the granularity of say microseconds, > it > + * may be better to instead try to match the long term Ideal behavior over > a > + * much more reasonable period of time like a millisecond. It is > generally > + * better to have a stable implementation that when averaged over a period > of > + * several milliseconds matches the Ideal behavior very closely than to > have > + * an implementation that is perhaps more accurate over a period of > + * microseconds, but whose millisecond averaged behavior drifts away from > the > + * Ideal case. > + * > + * <H2>Other TM Concepts</H2> > + * > + * <H3>Profiles</H3> > + * This specification often packages related TM system parameters into > + * records/objects called profiles. These profiles can then be associated > with > + * various entities like tm_nodes and tm_queue's. This way the amount of > + * storage associated with setting related parameters can be reduced and > + * in addition it is common to re-use the same set of parameter set over > + * and over again, and also to be able to change the parameter set once > + * and have it affect lots of entities with which it is associated > with/applied > + * to. > + * > + * <H3>Absolute Limits versus odp_tm_capability_t</H3> > + * This header file defines some constants representing the absolute > maximum > + * settings for any TM system, though in most cases a TM system can (and > + * should) be created/instantiated with smaller values, since lower values > + * will often result in faster operation and/or less memory used. > + */ > + > +/** > + * @def ODP_TM_MAX_NUM_SYSTEMS > + * The maximum number of TM systems that may be created. On some > platforms > + * this might be much more limited to as little as one hardware TM system. > + */ > + > +/** > + * @def ODP_TM_MAX_PRIORITIES > + * The largest range of priorities that any TM system can support. All > strict > + * priority values MUST in the range 0..ODP_TM_MAX_PRIORITIES-1. > + */ > + > +/** > + * @def ODP_TM_MAX_LEVELS > + * The largest range of tm_node levels that any TM system can support. > Hence > + * all tm_node level values MUST be in the range 0..ODP_TM_MAX_LEVELS-1. > + * Smaller tm_node levels are associated with tm_nodes closer to the TM > system > + * egress. > + */ > + > +/** > + * @def ODP_TM_MIN_SCHED_WEIGHT > + * The smallest SCHED weight is 1 (i.e. 0 is not a legal WFQ/WRR value). > + */ > + > +/** > + * @def ODP_TM_MAX_SCHED_WEIGHT > + * The largest weight any TM system can support (at least from a > configuration > + * standpoint). A given TM system could have a smaller value. > + */ > + > +/** > + * @def ODP_TM_MAX_TM_QUEUES > + * The largest number of tm_queues that can handled by any one TM system. > + */ > + > +/** > + * @def ODP_TM_MAX_NUM_OUTPUTS > + * The largest number of outputs that can be configured for any one TM > system. > + */ > + > +/** > + * @def ODP_TM_MAX_NUM_TM_NODES > + * The largest number of tm_nodes that can be in existence for any one TM > + * system. > + */ > + > +/** > + * @def ODP_TM_MAX_TM_NODE_FANIN > + * The largest number of fan-in "inputs" that can be simultaneously > connected > + * to a single tm_node. > + * @todo Does this need to be as large as ODP_TM_MAX_TM_QUEUES? > + */ > + > +/** > + * @def ODP_TM_MIN_SHAPER_BW > + * The largest amound of bandwidth that any shaper's peak or commit rate > can > + * be set to. It is in units of 1000 bytes/second. > + */ > + > +/** > + * @def ODP_TM_MAX_SHAPER_BW > + * The largest amound of bandwidth that any shaper's peak or commit rate > can > + * be set to. It is in units of 1000 bytes/second. > + */ > + > +/** > + * @def ODP_NUM_SHAPER_COLORS > + * The number of enumeration values defined in the odp_tm_shaper_color_t > type. > + */ > + > +/** > + * @def ODP_TM_INVALID_PRIORITY > + * Used to indicate an invalid priority value. > + */ > + > +/** > + * @typedef odp_tm_percent_t > + * Is used when specifying fields that are percentages. It is a fixed > point > + * integer whose units are 1/100 of a percent. Hence 100% is represented > as > + * the integer value 10000. Note that because it is often used as a ratio > of > + * the current queue value and maximum queue threshold, it can be > 100%, > but > + * in any event will never be larger than 500% (i.e. it MUST be capped at > + * 50000). > + */ > + > +/** > + * @typedef odp_tm_t > + * Each odp_tm_t value represents a specific TM system. Almost all > functions > + * in this API require a odp_tm_t value - either directly as a function > + * parameter or indirectly by having another ODP TM handle value as a > function > + * parameter. > + */ > + > +/** > + * @typedef odp_tm_queue_t > + * Each odp_tm_queue_t value is an opaque ODP handle representing a > specific > + * tm_queue within a specific TM system. > + */ > + > +/** > + * @typedef odp_tm_node_t > + * Each odp_tm_queue_t value is an opaque ODP handle representing a > specific > + * tm node within a specific TM system. > + */ > + > +/** > + * @typedef odp_tm_shaper_t > + * Each odp_tm_shaper_t value is an opaque ODP handle representing a > specific > + * shaper profile usable across all TM systems described by this API. A > given > + * shaper profile can then be attached to any tm_queue or tm_node. > + */ > + > +/** > + * @typedef odp_tm_sched_t > + * Each odp_tm_sched_t value is an opaque ODP handle representing a > specific > + * tm_node scheduler profile usable across all TM systems described by > this > + * API. A given tm_node scheduler profile can then be attached to any > + * tm_node. > + */ > + > +/** > + * @typedef odp_tm_threshold_t > + * Each odp_tm_threshold_t value is an opaque ODP handle representing a > + * specific queue threshold profile usable across all TM systems described > by > + * this API. A given queue threshold profile can then be attached to any > + * tm_queue or tm_node. > + */ > + > +/** > + * @typedef odp_tm_wred_t > + * Each odp_tm_wred_t value is an opaque ODP handle representing a > specific > + * WRED profile usable across all TM systems described by this API. A > given > + * WRED profile can then be attached to any tm_queue or tm_node. > + */ > + > +/** > + * @def ODP_TM_INVALID > + * Constant that can be used with any ODP TM handle type and indicates > that > + * this value does NOT represent a valid TM object. > + */ > + > +/** > + * @def ODP_TM_ROOT > + * Constant that is used to refer to the egress/root node of the TM > subsystem's > + * tree/hierarchy of nodes. > + */ > + > +/** The odp_tm_capability_t type is used to describe the feature set and > limits > + * of a TM system. It is passed to the odp_tm_create() function > indirectly > + * by being part of the odp_tm_params_t record. > + */ > +typedef struct { > + /** max_tm_queues specifies the maximum number of tm_queues that > can > + * be in existence for this TM System. > + */ > + uint32_t max_tm_queues; > + > + /** max_fanin_per_level specifies the maximum number of fan_in link > + * to any given scheduler (whether weighted or using fair queueing or > + * round robin) belonging to tm_nodes at the given level. > + */ > + uint32_t max_fanin_per_level[ODP_TM_MAX_LEVELS]; > + > + /** max_priority specifies the maximum number of strict priority > + * levels used by any tm_queue or tm_node. Note that any given > + * tm_queue or tm_node can use a subset of these levels. max_priority > + * must be in the range 0..ODP_TM_MAX_PRIORITIES - 1. Note that lower > + * numeric values represent higher (more important or time critical) > + * priorities. > + */ > + uint8_t max_priority; > + > + /** max_levels specifies that maximum number of levels of > hierarchical > + * scheduling allowed by this TM System. This is a count of the > + * tm_node stages and does not include tm_queues or tm_egress objects. > + * Hence any given tm_node will have associated tm_node_level in the > + * range 0 to max_levels - 1, where tm_node's at level 0 output's only > + * go to egress objects and tm_nodes whose level is max_levels - 1 > + * have their fan_in only from tm_queues. > + */ > + uint8_t max_levels; > + > + /** tm_queue_shaper_supported indicates that the tm_queues support > + * proper TM shaping. Note that TM Shaping is NOT the same thing as > + * Ingress Metering/Policing as specified by RFC 2697 (A Single Rate > + * Three Color Marker) or RFC 2698 (A Two Rate Three Color Marker). > + * These RFC's can be used for a Diffserv traffic conditioner, or > + * other ingress policing. They make no mention of and have no > + * algorithms for delaying packets - which is what TM shapers are > + * expected to do. > + */ > + odp_bool_t tm_queue_shaper_supported; > + > + /** tm_node_shaper_supported indicates that the tm_nodes (at least > for > + * some hierarchical levels) support proper T < M shaping. > + */ > + odp_bool_t tm_node_shaper_supported; > + > + /** red_supported indicates that the tm_queues support some form of > + * Random Early Discard. > + */ > + odp_bool_t red_supported; > + > + /** hierarchical_red_supported indicates that this TM system > supports > + * some form of RED where the queue fullness of tm_nodes contributes > + * to the overall RED DROP/NO-DROP decision. > + */ > + odp_bool_t hierarchical_red_supported; > + > + /** weights_supported indicates that the tm_node schedulers (at > least > + * for some hierarchical levels) can have their different weights for > + * their fan-ins. > + */ > + odp_bool_t weights_supported; > + > + /** fair_queuing_supported indicates the the tm_node schedulers (at > + * least for some hierarchical levels) can implement WFQ or FQ > + * scheduling disciplines, otherwise these schedulers can only > + * implement WRR or RR algorithms, > + */ > + odp_bool_t fair_queuing_supported; > +} odp_tm_capability_t; > + > +/** The odp_tm_egress_fcn_t type defines the parameter profile of the > egress > + * function callback. Using an egress function callback is just one of > several > + * ways of getting packets out from an egress spigot. > + * > + */ > +typedef void (*odp_tm_egress_fcn_t) (odp_packet_t odp_pkt); > + > +/** The tm_egress_kind_e enumeration type is used to indicate the kind of > + * egress object ("spigot") associated with this TM system. Most of these > + * kinds are optional - with ODP_TM_EGRESS_PKT_IO being the only mandatory > + * kind. The TM_EGRESS_FN - if implemented - is useful for testing the TM > + * subsystem, and users are warned that its performance might be limited. > + */ > +typedef enum { > + ODP_TM_EGRESS_PKT_IO, > + ODP_TM_EGRESS_FN, > +} odp_tm_egress_kind_t; > + > +/** The odp_tm_egress_t type is used to describe that type of "egress > spigot" > + * associated with this TM system. It is passed to the odp_tm_create() > + * function indirectly by being part of the odp_tm_params_t record. > + */ > +typedef struct { > + odp_tm_egress_kind_t egress_kind; /**< Union discriminator */ > + > + union { > + odp_pktio_t pktio; > + odp_tm_egress_fcn_t egress_fcn; > + }; > +} odp_tm_egress_t; > + > +/** The odp_tm_params_t record type is used to hold extra parameters when > + * calling the odp_tm_create() function. > + * Since it is expected that implementations might augment this record > type > + * with platform specific additional fields - it is required that > + * odp_tm_params_init() be called on variables of this type before any of > the > + * fields are filled in. > + */ > +typedef struct { > + odp_tm_capability_t capability; /**< capability record */ > + odp_tm_egress_t egress; /**< describes the egress "spigot" */ > +} odp_tm_params_t; > + > +/** odp_tm_capability_init() must be called to initialize any > + * odp_tm_capability_t record before it is first used or assigned to. > + * > + * @param[in] capability A pointer to an odp_tm_capability_t record which > + * is to be initialized. > + */ > +void odp_tm_capability_init(odp_tm_capability_t *capability); > + > +/** odp_tm_params_init() must be called to initialize any > + * odp_tm_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_params_t record which > + * is to be initialized. > + */ > +void odp_tm_params_init(odp_tm_params_t *params); > + > +/** Create/instantiate a TM Packet Scheduling system. > + * > + * @param[in] name The name to be assigned to this TM system. Cannot > be > + * NULL, and also must be unique amongst all other TM > system > + * names. > + * @param[in] params The params to be used when creating this TM system. > + * @return Returns ODP_TM_INVALID upon failure, otherwise the > newly > + * created TM system's odp_tm_t handle is returned. > + */ > +odp_tm_t odp_tm_create(const char *name, odp_tm_params_t *params); > + > +/** Find a pre-existing TM Packet Scheduling system. This function can be > + * used either to find a TM system created previously with odp_tm_create > OR > + * get the odp_tm_t of a built-in TM system - usually based on HW. In this > + * later case the format of the name used to refer to a specific built-in > + * hardware TM system may be platform dependent, but in any case a name of > + * "HW_TM_%u" where the number starts at 1, can be used to find a built-in > + * system independently of the best capability match. If name is NULL > then > + * the existing (built-in or created by odp_tm_create) TM system that best > + * matches capability is returned. > + * > + * @param[in] name If NULL then only uses the capability parameter > to > + * find a closest match, otherwise if the name is > + * matched by an existing TM system it is returned. > + * @param[in] capability Used when the name is NULL (in which > + * case the closest match is returned) or when the > + * name is not-NULL, but doesn't match > + * any existing TM system in which case the > + * capability is used to find the FIRST > + * TM system matching exactly these limits. > + * @return If an existing TM system (built-in or previously > + * created via odp_tm_create) is found, its > + * odp_tm_t value is returned, otherwise > + * ODP_TM_INVALID is returned. > + */ > +odp_tm_t odp_tm_find(const char *name, odp_tm_capability_t *capability); > + > +/** odp_tm_capability() can be used to query the actual limits of a given > TM > + * system. This function can be used for both built-in TM systems AND TM > + * system's created via odp_tm_create(). > + * > + * @param[in] odp_tm The odp_tm_t value of the TM system to be > + * queried. > + * @param[out] capability A pointer to a odp_tm_capability_t record > + * where the actual limits used by the TM system > are > + * copied into. Note that these limits do NOT > + * have to match the capability passed in if > + * a TM system was created by odp_tm_create, > + * but of course these limits in some cases could > + * be larger. > + * @return Returns 0 upon success, < 0 upon failure (which > + * indicates that the odp_tm value did not > + * exist). > + */ > +int odp_tm_capability(odp_tm_t odp_tm, odp_tm_capability_t *capability); > + > +/** odp_tm_destroy() may be used to destroy TM systems created via > + * odp_tm_create(). It generally CANNOT be used to destroy built-in TM > + * systems. Also some platforms MAY not support destroying of TM systems > + * created via odp_tm_create() under certain conditions. For example a > given > + * platform may require that the TM system be first "drained" of all of > its > + * queued packets before it will accept a odp_tm_destroy() call. > + * > + * In general calling odp_tm_destroy() on an active TM system does not > + * guarantee anything about the disposition of any packets queued within > the > + * TM system, other than EVENTUALLY these packets will be either sent (in > ANY > + * order) or freed. > + * > + * @param[in] odp_tm The odp_tm_t value of the TM system to be destroyed > (and > + * hence destroyed (and hence freed). > + * @return 0 upon success, < 0 upon failure. > + */ > +int odp_tm_destroy(odp_tm_t odp_tm); > + > +/** Shaper profile types and functions */ > + > +/** Possible values of running the shaper algorithm. ODP_TM_SHAPER_GREEN > + * means that the traffic is within the commit specification (rate and > burst > + * size), ODP_TM_SHAPER_YELLOW means that the traffic is within the peak > + * specification (rate and burst size) and ODP_TM_SHAPER_RED means that > the > + * traffic is exceeding both its commit and peak specifications. Note > that > + * packets can also have an assigned <b> packet color</b> of > ODP_PACKET_GREEN, > + * ODP_PACKET_YELLOW or ODP_PACKET_RED which has a different meaning and > + * purpose than the shaper colors. > + */ > +typedef enum { > + ODP_TM_SHAPER_GREEN, ODP_TM_SHAPER_YELLOW, ODP_TM_SHAPER_RED > +} odp_tm_shaper_color_t; > + > +/** The odp_tm_shaper_params_t record type is used to supply the > parameters > + * associated with a shaper profile. Since it is expected that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_shaper_params_init() be > + * called on variables of this type before any of the fields are filled > in. > + */ > +typedef struct { > + /** The committed information rate for this shaper profile. The > units > + * for this integer are always in bits per second. > + */ > + uint64_t commit_bps; > + > + /** The peak information rate for this shaper profile. The units > for > + * this integer are always in bits per second. > + */ > + uint64_t peak_bps; > + > + /** The commit burst tolerance for this shaper profile. The units > for > + * this field are always bits. This value sets an upper limit for the > + * size of the commitCnt. > + */ > + uint32_t commit_burst; > + > + /** The peak burst tolerance for this shaper profile. The units > for > + * this field are always bits. This value sets an upper limit for the > + * size of the peakCnt. > + */ > + uint32_t peak_burst; > + > + /** The shaper_len_adjust is a value between -128 and 127 which is > + * directly added to the frame_len of a packet associated with this > + * profile. The frame_len would normally include the outermost > + * Ethernet header (DA, SA, ...) through to the outermost Ethernet CRC > + * inclusive. Hence this field - when non-zero - will usually be set > + * to a value approximating the "time" (in units of bytes) taken by > + * the Ethernet preamble and Inter Frame Gap. Traditionally this > + * would be the value 20 (8 + 12), but in same cases can be as low as > + * 9 (4 + 5). > + */ > + int8_t shaper_len_adjust; > + > + /** If dual_rate is TRUE it indicates the desire for the > + * implementation to use dual rate shaping for packets associated with > + * this profile. The precise semantics of dual rate shaping are > + * implementation specific, but in any case require a non-zero set of > + * both commit and peak parameters. > + */ > + odp_bool_t dual_rate; > +} odp_tm_shaper_params_t; > + > +/** odp_tm_shaper_params_init() must be called to initialize any > + * odp_tm_shaper_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_shaper_params_t record which > + * is to be initialized. > + */ > +void odp_tm_shaper_params_init(odp_tm_shaper_params_t *params); > + > +/** odp_tm_shaper_create() creates a shaper profile object, which can > + * subsequently be attached to any number (including zero) of tm_queues > + * or tm_nodes. > + * > + * @param[in] name Optional name associated with this shaper profile. > Can > + * be NULL. If non-NULL must be unique amongst the set > of > + * all other shaper profiles. > + * @param[in] params The profile parameters. See comments associated > with > + * the odp_tm_shaper_params_t for more details. > + * @return Returns ODP_TM_INVALID upon failure, or the newly > + * allocated odp_tm_shaper_t value representing this > + * profile object. > + */ > +odp_tm_shaper_t odp_tm_shaper_create(const char *name, > + odp_tm_shaper_params_t *params); > + > +/** odp_tm_shaper_params_read() "gets" the current set of values > associated > + * with the specified shaper profile object, and copies them into the > supplied > + * record. > + * > + * @param[in] shaper_profile Specifies the shaper profile object whose > + * values are to be read. > + * @param[out] params A pointer to an odp_tm_shaper_params_t > record > + * where the current shaper profile object > values > + * are copied to. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_shaper_params_read(odp_tm_shaper_t shaper_profile, > + odp_tm_shaper_params_t *params); > + > +/** odp_tm_shaper_params_update() "sets" the current set of values > associated > + * with the specified shaper profile object. In addition, this call has > the > + * effect that all tm_input's and tm_nodes that are associated (attached?) > + * with this shaper profile object will be updated with the new values. > + * > + * @param[in] shaper_profile Specifies the shaper profile object whose > + * values are to be set. > + * @param[in] params A pointer to an odp_tm_shaper_params_t > record > + * where the new shaper profile object values > + * are taken from. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_shaper_params_update(odp_tm_shaper_t shaper_profile, > + odp_tm_shaper_params_t *params); > + > +/** odp_tm_shaper_lookup() can be used to find the shaper profile object > + * created with the specified name. > + * > + * @param[in] name Name of a previously created shaper profile. Cannot > be > + * NULL. > + * @return Returns ODP_TM_INVALID upon failure, or the shaper > + * profile handle created with this name. > + */ > +odp_tm_shaper_t odp_tm_shaper_lookup(const char *name); > + > +/** Scheduler Profiles - types and functions */ > + > +/** The odp_tm_sched_mode_t type is used to control whether a tm_node > + * scheduler takes into account packet lengths (by setting the sched_mode > to > + * ODP_TM_BYTE_BASED_WEIGHTS) or instead treat packets with different > lengths > + * the same (by setting the sched_mode to ODP_TM_FRAME_BASED_WEIGHTS). > + * Normally the sched_mode will be set to ODP_TM_BYTE_BASED_WEIGHTS, > otherwise > + * the scheduler becomes a weighted round robin scheduler. > + */ > +typedef enum { > + ODP_TM_BYTE_BASED_WEIGHTS, /**< Use the packet length in > + scheduler algorithm */ > + ODP_TM_FRAME_BASED_WEIGHTS /**< Ignore the packet length */ > +} odp_tm_sched_mode_t; > + > +/** The odp_tm_sched_params_t record type is used to supply the parameters > + * associated with a scheduler profile. Since it is expected that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_sched_params_init() be > + * called on variables of this type before any of the fields are filled > in. > + */ > +typedef struct { > + /** sched_modes indicates whether weighted scheduling should be > used > + * or not - on a priority basis. > + */ > + odp_tm_sched_mode_t sched_modes[ODP_TM_MAX_PRIORITIES]; > + > + /** In the case that sched_modes for a given strict priority level > + * indicates the use of weighted scheduling, this field supplies the > + * weighting factors. The weights - when defined - are used such that > + * the (adjusted) frame lengths are divided by these 8-bit weights > + * (i.e. they are divisors and not multipliers). Consequently a > + * weight of 0 (when sched_mode is ODP_TM_BYTE_BASED_WEIGHTS) is > + * illegal. > + */ > + uint8_t sched_weights[ODP_TM_MAX_PRIORITIES]; > +} odp_tm_sched_params_t; > + > +/** odp_tm_sched_params_init() must be called to initialize any > + * odp_tm_sched_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_sched_params_t record which > + * is to be initialized. > + */ > +void odp_tm_sched_params_init(odp_tm_sched_params_t *params); > + > +/** odp_tm_sched_create() creates a scheduler profile object, which can > + * subsequently be attached to any number (including zero) of tm_nodes. > + * > + * @param[in] name Optional name associated with this scheduler > profile. > + * Can be NULL. If non-NULL must be unique amongst the > + * set of all other scheduler profiles. > + * @param[in] params The profile parameters. See comments associated > with > + * the odp_tm_sched_params_t for more details. > + * @return Returns ODP_TM_INVALID upon failure, or the newly > + * allocated odp_tm_sched_t value representing this > profile > + * object. > + */ > +odp_tm_sched_t odp_tm_sched_create(const char *name, > + odp_tm_sched_params_t *params); > + > +/** odp_tm_sched_params_read() "gets" the current set of values associated > + * with the specified scheduler profile object, and copies them into the > + * supplied record. > + * > + * @param[in] sched_profile Specifies the scheduler profile whose values > + * are to be read. > + * @param[out] params A pointer to an odp_tm_sched_params_t record > + * where the current scheduler profile object > + * values are copied to. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_sched_params_read(odp_tm_sched_t sched_profile, > + odp_tm_sched_params_t *params); > + > +/** odp_tm_sched_params_update() "sets" the current set of values > associated > + * with the specified scheduler profile object. In addition, this call > has > + * the effect that all tm_nodes that are associated (attached?) with this > + * Scheduler profile object will be updated with the new values. > + * > + * @param[in] sched_profile Specifies the Scheduler profile object whose > + * values are to be set. > + * @param[in] params A pointer to an odp_tm_sched_params_t record > + * where the new scheduler profile object > values > + * are taken from. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_sched_params_update(odp_tm_sched_t sched_profile, > + odp_tm_sched_params_t *params); > + > +/** odp_tm_sched_lookup() can be used to find the scheduler profile object > + * created with the specified name. > + * > + * @param[in] name Name of a previously created scheduler profile. > Cannot be > + * NULL. > + * @return Returns ODP_TM_INVALID upon failure, or the scheduler > + * profile handle created with this name. > + */ > +odp_tm_sched_t odp_tm_sched_lookup(const char *name); > + > +/** Queue Threshold Profiles - types and functions */ > + > +/** The odp_tm_threshold_params_t record type is used to supply the > parameters > + * associated with a queue thresholds profile. Since it is expected that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_threshold_params_init() > be > + * called on variables of this type before any of the fields are filled in > + */ > +typedef struct { > + uint64_t max_pkts; /**< max pkt cnt for this threshold profile */ > + uint64_t max_bytes; /**< max byte cnt for this threshold profile */ > + odp_bool_t enable_max_pkts; /**< TRUE if max_pkts is valid */ > + odp_bool_t enable_max_bytes; /**< TRUE if max_bytes is valid */ > +} odp_tm_threshold_params_t; > + > +/** odp_tm_threshold_params_init() must be called to initialize any > + * odp_tm_threshold_params_t record before it is first used or assigned > to. > + * > + * @param[in] params A pointer to an odp_tm_threshold_params_t record > which > + * is to be initialized. > + */ > +void odp_tm_threshold_params_init(odp_tm_threshold_params_t *params); > + > +/** odp_tm_threshold_create() creates a queue threshold profile object, > which > + * can subsequently be attached to any number (including zero) of > tm_queues or > + * tm_nodes. > + * > + * @param[in] name Optional name associated with this queue threshold > + * profile. Can be NULL. If non-NULL must be unique > + * amongst the set of all other queue threshold > profiles. > + * @param[in] params The profile parameters. See comments associated > with > + * the odp_tm_threshold_params_t for more details. > + * @return Returns ODP_TM_INVALID upon failure, or the newly > + * allocated odp_tm_threshold_t value representing this > + * profile object. > + */ > +odp_tm_threshold_t odp_tm_threshold_create(const char *name, > + odp_tm_threshold_params_t *params); > + > +/** odp_tm_thresholds_params_read() "gets" the current set of values > associated > + * with the specified queue thresholds profile object, and copies them > into the > + * supplied record. > + * > + * @param[in] threshold_profile Specifies the queue thresholds profile > + * object whose values are to be read. > + * @param[out] params A pointer to an > odp_tm_threshold_params_t > + * record where the current queue > thresholds > + * profile object values are copied to. > + * @return Returns < 0 upon failure or 0 upon > success. > + */ > +int odp_tm_thresholds_params_read(odp_tm_threshold_t threshold_profile, > + odp_tm_threshold_params_t *params); > + > +/** odp_tm_thresholds_params_update() "sets" the current set of values > + * associated with the specified queue thresholds profile object. In > addition, > + * this call has the effect that all tm_input's and tm_nodes that are > + * associated (attached?) with this queue thresholds profile object will > be > + * updated with the new values. > + * > + * @param[in] threshold_profile Specifies the queue thresholds profile > + * object whose values are to be set. > + * @param[in] params A pointer to an odp_tm_threshold_params_t > + * record where the current queue thresholds > + * profile object values are taken from. > + * @return Returns < 0 upon failure or 0 upon > success. > + */ > +int odp_tm_thresholds_params_update(odp_tm_threshold_t threshold_profile, > + odp_tm_threshold_params_t *params); > + > +/** odp_tm_thresholds_lookup() can be used to find the queue thresholds > + * profile object created with the specified name. > + * > + * @param[in] name Name of a previously created queue thresholds profile. > + * Cannot be NULL. > + * @return Returns ODP_TM_INVALID upon failure, or the queue > + * thresholds profile handle created with this name. > + */ > +odp_tm_threshold_t odp_tm_thresholds_lookup(const char *name); > + > +/** WRED Profiles - types and functions */ > + > +/** The odp_tm_wred_params_t record type is used to supply the parameters > + * associated with a Random Early Discard profile. Since it is expected > that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_wred_params_init() be > called > + * on variables of this type before any of the fields are filled in. > + */ > +typedef struct { > + /** When min_threshold is set to zero then single-slope WRED is > + * enabled, as described in the description of med_threshold. > + * Otherwise dual-slope WRED is enabled whereby the behavior depends > + * on which of the following three cases exists: > + * <ol> <li> queue > + * fullness < min_threshold. In this case the drop probability is > + * zero. > + * <li> min_threshold <= queue fullness < med_threshold. In > + * this case the drop probability increases linearly from zero until > + * it reaches med_drop_prob at a queue fullness equal to > + * med_threshold. > + * <li> med_threshold <= queue fullness. In this case > + * the drop probability increases linearly from med_drop_prob when the > + * queue fullness equals med_threshold until it reaches 100% with a > + * drop probability of max_drop_prob. </ol> > + */ > + odp_tm_percent_t min_threshold; > + > + /** The meaning of med_threshold depends upon whether single-slope > or > + * dual-slope WRED is being used or not. When min_threshold is 0 then > + * single-slope WRED is enabled in which case the med_threshold value > + * represents (as a percentage of max queue fullness) the point at > + * which the drop probability starts increasing linearly from 0 until > + * it becomes equal to max_drop_prob when the queue fullness reaches > + * 100%. See min_threshold comments for the case of dual-slope WRED. > + */ > + odp_tm_percent_t med_threshold; > + > + /** The med_drop_prob is only used when dual-slope WRED is being > used, > + * in which case med_drop_prob MUST be < max_drop_prob. See > + * min_threshold comments for more details. > + */ > + odp_tm_percent_t med_drop_prob; > + > + /** The max_drop_prob equals the drop probability when the queue > + * fullness almost equals 100%. Of course once the queue fullness is > + * >= 100% of the max queue fullness, the drop probability > + * discontinuously becomes 100%. > + */ > + odp_tm_percent_t max_drop_prob; > + > + /** When enable_wred is false, all tm_queues and tm_nodes that are > + * attached to this profile will not take part in a Random Early > + * Discard algorithm. > + */ > + odp_bool_t enable_wred; > + > + /** When use_byte_fullness is true then WRED will use queue memory > + * usage as the fullness criterion, otherwise when use_byte_fullness > + * is false, WRED will use the queue length (i.e. the number of > + * packets in the queue) as the fullness criterion. Often will be set > + * to true for WRED profiles applied to tm_queues and set to false for > + * WRED profiles applied to tm_nodes. > + */ > + odp_bool_t use_byte_fullness; > +} odp_tm_wred_params_t; > + > +/** odp_tm_wred_params_init() must be called to initialize any > + * odp_tm_wred_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_wred_params_t record which > + * is to be initialized. > + */ > +void odp_tm_wred_params_init(odp_tm_wred_params_t *params); > + > +/** odp_tm_wred_create() creates a WRED (Weighted Random Early Discard) > + * profile object, which can subsequently be attached to any number > (including > + * zero) of tm_queues or tm_nodes. > + * > + * @param[in] name Optional name associated with this WRED profile. > Can > + * be NULL. If non-NULL must be unique amongst the set > of > + * all other WRED profiles. > + * @param[in] params The profile parameters. See comments associated > with the > + * odp_tm_wred_params_t for more details. > + * @return Returns ODP_TM_INVALID upon failure, or the newly > + * allocated odp_tm_wred_t value representing this > profile > + * object. > + */ > +odp_tm_wred_t odp_tm_wred_create(const char *name, > + odp_tm_wred_params_t *params); > + > +/** odp_tm_wred_params_read() "gets" the current set of values associated > + * with the specified WRED profile object, and copies them into the > supplied > + * record. > + * > + * @param[in] wred_profile Specifies the WRED profile object whose > + * values are to be read. > + * @param[out] params A pointer to an odp_tm_wred_params_t record > + * where the current WRED profile object values > + * are copied to. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_wred_params_read(odp_tm_wred_t wred_profile, > + odp_tm_wred_params_t *params); > + > +/** odp_tm_wred_params_update() "sets" the current set of values > associated > + * with the specified WRED profile object. In addition, this call has the > + * effect that all tm_input's and tm_nodes that are associated (attached?) > + * with this WRED profile object will be updated with the new values. > + * > + * @param[in] wred_profile Specifies the WRED profile object whose > + * values are to be set. > + * @param[in] params A pointer to an odp_tm_wred_params_t record > + * where the new WRED profile object values > + * are taken from. > + * @return Returns < 0 upon failure or 0 upon success. > + */ > +int odp_tm_wred_params_update(odp_tm_wred_t wred_profile, > + odp_tm_wred_params_t *params); > + > +/** odp_tm_wred_lookup() can be used to find the WRED profile object > created > + * with the specified name. > + * > + * @param[in] name Name of a previously created WRED profile. Cannot be > + * NULL. > + * @return Returns ODP_TM_INVALID upon failure, or the WRED > + * profile handle created with this name. > + */ > +odp_tm_wred_t odp_tm_wred_lookup(const char *name); > + > +/** The odp_tm_node_params_t record type is used to hold extra parameters > when > + * calling the odp_tm_node_create() function. Many of these fields are > + * optional EXCEPT for max_fanin and level. Also since it is expected > that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_node_params_init() be > called > + * on variables of this type before any of the fields are filled in. > + */ > +typedef struct { > + /** The max_fan_in sets tha maximum number of src tm_queues and > + * producer tm_nodes that can be simultaneously be connected to this > + * tm_node as their destination. > + */ > + uint32_t max_fanin; > + > + /**> @todo uint8_t num_priorities; ? */ > + > + /** The shaper profile to be associated with this tm_node. Can be > + * ODP_TM_INVALID and can also be set and changed post-creation via > + * odp_tm_node_shaper_config(); > + */ > + odp_tm_shaper_t shaper_profile; > + > + /** The threshold profile to be used in setting the max queue > fullness > + * for WRED and/or tail drop? Can be ODP_TM_INVALID and can also be > + * set and changed post-creation via odp_tm_node_threshold_config(). > + */ > + odp_tm_threshold_t threshold_profile; > + > + /** The WRED profile(s) to be associated with this tm_node. Any or > + * all array elements can be ODP_TM_INVALID and can also be set and > + * changed post-creation via odp_tm_node_wred_config(). > + */ > + odp_tm_wred_t wred_profile[ODP_NUM_PACKET_COLORS]; > + > + /** The level (or tm_node stage) sets the level for this tm_node It > + * must be in range 0..max_levels-1. Note that the tm_node topology > + * is constrained such that only tm_node outputs with numerically > + * greater levels may be connected to the fan-in of tm_node's with > + * numerically smaller levels. > + */ > + uint8_t level; > +} odp_tm_node_params_t; > + > +/** odp_tm_node_params_init() must be called to initialize any > + * odp_tm_node_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_node_params_t record which > + * is to be initialized. > + */ > +void odp_tm_node_params_init(odp_tm_node_params_t *params); > + > +/** Create an tm_node with a specific set of implemented strict priority > + * levels as given by the priorities array parameter. The set of priority > + * levels does not have to "contiguous", but the "priorities" values for > all > + * indexes > max_priority MUST be FALSE. Note that the set of implemented > + * strict priority levels for an tm_node cannot be changed after tm_node > + * creation. The level parameter MUST be in the range 0..max_level - 1. > + * > + * @param[in] odp_tm Odp_tm is used to identify the TM system into which > this > + * odp_tm_node object is created. > + * @param[in] name Optional name that can be used later later to find > this > + * same odp_tm_node_t. Can be NULL, otherwise must be > + * unique across all odp_tm_node objects. > + * @param[in] params A pointer to a record holding (an extensible) set of > + * properties/attributes of this tm_node. > + * @return Returns ODP_TM_INVALID upon failure, otherwise > returns > + * a valid odp_tm_node_t handleif successful. > + */ > +odp_tm_node_t odp_tm_node_create(odp_tm_t odp_tm, const char *name, > + odp_tm_node_params_t *params); > + > +/** The odp_tm_node_shaper_config() function is used to dynamically set or > + * change the shaper profile associated with this tm_node. > + * > + * @param[in] tm_node Specifies the tm_node to be changed. > + * @param[in] shaper_profile Specifies the shaper profile that should > + * now be used for the shaper entity within the > + * given tm_node. Note that it is legal to > specify > + * ODP_TM_INVALID indicating that this tm_node > + * no longer implements a shaper function. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_node_shaper_config(odp_tm_node_t tm_node, > + odp_tm_shaper_t shaper_profile); > + > +/** The odp_tm_node_sched_config() function is used to dynamically set or > + * change the scheduler profile associated with a tm_node. > + * > + * @param[in] tm_node Specifies the tm_node to be changed. > + * @param[in] tm_fan_in_node Specifies which of the specified tm_node's > + * fan-in's weights etc are to be changed. The > + * fan-in is indentified by the > "producer"/parent > + * tm_node actually connected to this fan-in. > + * @param[in] sched_profile Specifies the scheduler profile that should > + * now be used for the WFQ/RR entity within the > + * given tm_node. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_node_sched_config(odp_tm_node_t tm_node, > + odp_tm_node_t tm_fan_in_node, > + odp_tm_sched_t sched_profile); > + > +/** The odp_tm_node_threshold_config() function is used to dynamically set > or > + * change the queue threshold profile associated with this tm_node. > + * > + * @param[in] tm_node Specifies the tm_node to be changed. > + * @param[in] thresholds_profile Specifies the queue threshold profile > that > + * should now be used for the given > tm_node. > + * @return Returns 0 upon success and < 0 upon > failure. > + */ > +int odp_tm_node_threshold_config(odp_tm_node_t tm_node, > + odp_tm_threshold_t thresholds_profile); > + > +/** The odp_tm_node_wred_config() function is used to dynamically set or > + * change the WRED profile associated with this tm_node or > tm_node/pkt_color > + * combination. > + * > + * @param[in] tm_node Specifies the tm_node to be changed. > + * @param[in] pkt_color Specifies the pkt_color that this profile is > to be > + * used with. Can also be the special value > + * ALL_PKT_COLORS. > + * @param[in] wred_profile Specifies the WRED profile that should now be > used > + * by this tm_queue, when processing pkts of this > + * pkt_color. It can be the value ODP_TM_INVALID > + * indicating that this tm_queue/pkt_color > combination > + * no longer implements WRED. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_node_wred_config(odp_tm_node_t tm_node, > + odp_packet_color_t pkt_color, > + odp_tm_wred_t wred_profile); > + > +/** odp_tm_node_lookup() can be used to find the tm_node object created > with > + * the specified name. > + * > + * @param[in] odp_tm Odp_tm is used to identify the TM system into which > this > + * odp_tm_node object is created. > + * @param[in] name Name of a previously created tm_node. Cannot be > + * NULL. > + * @return Returns ODP_TM_INVALID upon failure, or the tm_node > + * handle created with this name. > + */ > +odp_tm_node_t odp_tm_node_lookup(odp_tm_t odp_tm, const char *name); > + > +/** The odp_tm_queue_params_t record type is used to hold extra parameters > + * when calling the odp_tm_queue_create() function. Many of these fields > are > + * optional EXCEPT for priority. Also since it is expected that > + * implementations might augment this record type with platform specific > + * additional fields - it is required that odp_tm_queue_params_init() be > + * called on variables of this type before any of the fields are filled > in. > + */ > +typedef struct { > + /** The shaper profile to be associated with this tm_queue. Can be > + * ODP_TM_INVALID and can also be set and changed post-creation via > + * odp_tm_queue_shaper_config(); > + */ > + odp_tm_shaper_t shaper_profile; > + > + /** The threshold profile to be used in setting the max queue > fullness > + * for WRED and/or tail drop? Can be ODP_TM_INVALID and can also be > + * set and changed post-creation via odp_tm_queue_threshold_config(). > + */ > + odp_tm_threshold_t threshold_profile; > + > + /** The WRED profile(s) to be associated with this tm_queue. Any > or > + * all array elements can be ODP_TM_INVALID and can also be set and > + * changed post-creation via odp_tm_queue_wred_config(). > + */ > + odp_tm_wred_t wred_profile[ODP_NUM_PACKET_COLORS]; > + > + /** The strict priority level assigned to packets in this tm_queue > - > + * in other words all packets associated with a given tm_queue MUST > + * have the same single strict priority level and this level must be > + * in the range 0..max_priority. > + */ > + uint8_t priority; > +} odp_tm_queue_params_t; > + > +/** odp_tm_queue_params_init() must be called to initialize any > + * odp_tm_queue_params_t record before it is first used or assigned to. > + * > + * @param[in] params A pointer to an odp_tm_queue_params_t record which > + * is to be initialized. > + */ > +void odp_tm_queue_params_init(odp_tm_queue_params_t *params); > + > +/** Create an tm_queue object. One can specify the maximum queue limits > + * either as a maximum number of packets in the queue OR as a maximum > number > + * of bytes in the queue, or if both are specified, then whichever limit > is > + * hit first. Note that in the case of specifying the maximum queue > memory > + * size as bytes, the system is free to instead convert this byte value > into a > + * number of buffers and instead limit the queue memory usage by buffer > counts > + * versus strictly using byte counts. > + * > + * @param[in] odp_tm Odp_tm is used to identify the TM system into which > this > + * odp_tm_queue object is created. > + * @param[in] params A pointer to a record holding (an extensible) set of > + * properties/attributes of this tm_queue. > + * @return Returns ODP_TM_INVALID upon failure, otherwise a > valid > + * odp_tm_queue_t handle. > + */ > +odp_tm_queue_t odp_tm_queue_create(odp_tm_t odp_tm, > + odp_tm_queue_params_t *params); > + > +/** The odp_tm_queue_shaper_config() function is used to dynamically set > + * or change the shaper profile associated with this tm_queue. > + * > + * @param[in] tm_queue Specifies the tm_queue to be changed. > + * @param[in] shaper_profile Specifies the shaper profile that should now > be > + * used for shaping the tm_queue's packet > stream. > + * Note that it is legal to specify > ODP_TM_INVALID > + * indicating that this tm_queue no longer > + * implements a shaper function. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_queue_shaper_config(odp_tm_queue_t tm_queue, > + odp_tm_shaper_t shaper_profile); > + > +/** The odp_tm_queue_sched_config() function is used to dynamically set or > + * change the scheduler profile associated with a tm_node. Note that > despite > + * the name, this function affects a tm_node scheduler - specifically the > + * scheduler fan-in when such fan-in comes from an tm_queue. > + * > + * @param[in] tm_node Specifies the tm_node to be changed. > + * @param[in] tm_fan_in_queue Specifies which of the specified tm_node's > + * fan-in's weights etc are to be changed. The > + * fan-in is indentified by the > "producer"/parent > + * tm_queue actually connected to this fan-in. > + * @param[in] sched_profile Specifies the scheduler profile that should > + * now be used for the WFQ/RR entity within the > + * given tm_node. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_queue_sched_config(odp_tm_node_t tm_node, > + odp_tm_queue_t tm_fan_in_queue, > + odp_tm_sched_t sched_profile); > + > +/** The odp_tm_queue_threshold_config() function is used to dynamically > set or > + * change the queue threshold profile associated with this tm_queue. > + * > + * @param[in] tm_queue Specifies the tm_queue to be changed. > + * @param[in] thresholds_profile Specifies the queue threshold profile > that > + * should now be used for the given > tm_queue. > + * @return Returns 0 upon success and < 0 upon > failure. > + */ > +int odp_tm_queue_threshold_config(odp_tm_queue_t tm_queue, > + odp_tm_threshold_t thresholds_profile); > + > +/** odp_tm_queue_wred_config() function is used to dynamically set or > change > + * the WRED profile associated with this tm_queue or tm_queue/pkt_color > + * combination. > + * > + * @param[in] tm_queue Specifies the tm_queue to be changed. > + * @param[in] pkt_color Specifies the pkt_color that this profile is > to be > + * used with. Can also be the special value > + * ALL_PKT_COLORS. > + * @param[in] wred_profile Specifies the WRED profile that should now be > used > + * by this tm_queue, when processing pkts of this > + * pkt_color. It can be the value ODP_TM_INVALID > + * indicating that this tm_queue/pkt_color > combination > + * no longer implements WRED. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_queue_wred_config(odp_tm_queue_t tm_queue, > + odp_packet_color_t pkt_color, > + odp_tm_wred_t wred_profile); > + > +/** Topology setting functions */ > + > +/** Connects the "output" of the src_tm_node to be a "producer" of the > given > + * dst_tm_node. Note that an ODP_TM_ROOT handle passed in for the > + * dst_tm_node implies connection to the egress/root object of this TM > system. > + * > + * @param[in] src_tm_node odp_tm_node_t handle of the tm_node whose > output is > + * to be connected to the fan-in of the next > tm_node > + * as represented by the dst_tm_node. > + * @param[in] dst_tm_node odp_tm_node_t handle of the tm_node object that > will > + * receive all of the pkt_descs from the src > tm_node > + * output. If ODP_TM_ROOT, then attachment is to > + * the root egress object/spigot. > + * @return 0 upon success, < 0 on failure. > + */ > +int odp_tm_node_connect(odp_tm_node_t src_tm_node, odp_tm_node_t > dst_tm_node); > + > +/** The odp_queue_connect() function connects the indicated tm_queue to a > + * parent tm_node or to the egress/root node. The tm_queue will then > become > + * one of the dst node's fan-in set. > + * > + * @param[in] tm_queue Specifies the tm_queue. > + * @param[in] dst_tm_node odp_tm_node_t handle of the tm_node object that > will > + * receive all of the pkt_descs from the src > tm_node > + * output. If ODP_TM_ROOT, then attachment is to > + * the root egress object/spigot. > + * @return Returns 0 upon success and < 0 upon failure. > + */ > +int odp_tm_queue_connect(odp_tm_queue_t tm_queue, odp_tm_node_t > dst_tm_node); > + > +/** Input API */ > + > +/** The odp_tm_enq() function is used to add packets to a given TM system. > + * Note that the System Metadata associated with the pkt needed by the TM > + * system is (a) a drop_eligible bit, (b) a two bit "pkt_color", (c) a 16- > bit > + * pkt_len, and MAYBE? (d) a signed 8-bit shaper_len_adjust. > + * > + * If there is a non-zero shaper_len_adjust, then it is added to the > pkt_len > + * after any non-zero shaper_len_adjust that is part of the shaper > profile. > + * > + * The pkt_color bits are a result of some earlier > Metering/Marking/Policing > + * processing (typically ingress based), and should not be confused with > the > + * shaper_color produced from the TM shaper entities within the tm_inputs > and > + * tm_nodes. > + * > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the TM > system). > + * @param[in] pkt Handle to a packet. > + * @return Returns 0 upon success, < 0 upon failure. One of > the > + * more common failure reasons is WRED dropage. > + */ > +int odp_tm_enq(odp_tm_queue_t tm_queue, odp_packet_t pkt); > + > +/** The odp_tm_enq_with_cnt() function behaves identically to > odp_tm_enq(), > + * except that it also returns (an approximation to?) the current tm_queue > + * packet queue count. > + * > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the TM > system). > + * @param[in] pkt Handle to a packet. > + * @return Returns the number of packets previously enqueued > on > + * this tm_queue upon success, < 0 upon failure. > + */ > +int odp_tm_enq_with_cnt(odp_tm_queue_t tm_queue, odp_packet_t pkt); > + > +/** Dynamic state query functions */ > + > +/** The following bit mask constants are used to refine the queue query > + * functions defined below. > + */ > +#define ODP_TM_QUERY_PKT_CNT 0x01 /**< The total_pkt_cnt value */ > +#define ODP_TM_QUERY_BYTE_CNT 0x02 /**< The total_byte_cnt value */ > +#define ODP_TM_QUERY_THRESHOLDS 0x04 /**< The thresholds??? */ > + > +/** The odp_tm_queue_info_t record type is used to return the various > counts > + * as requested by functions like odp_tm_queue_query() and > + * odp_tm_total_query(). > + */ > +typedef struct { > + /** The total_pkt_cnt field is the total number of packets > currently > + * stored/associated with the requested set of tm_queues. Note that > + * because the packet queues are potentially being manipulated by > + * multiple cpu's, the values here are only accurate when the tm > + * system is "stopped" (i.e. the egress spigot is stopped and no > + * odp_tm_enq calls are taking place). Implementations are free to > + * batch update these counters - up to a dozen or so packets. > + */ > + uint64_t total_pkt_cnt; > + > + /** If the requested set of tm_queues has an odp_tm_threshold_t > + * profile associated with it, then this is the max_pkt_cnt set in the > + * profile params. Returning this field is a convenience to the ODP > + * programmer, enabling them to quickly see how the total_pkt_cnt > + * compares to the maximum packet count threshold. Note that there is > + * no requirement that total_pkt_cnt be <= max_pkt_cnt. > + */ > + uint64_t max_pkt_cnt; > + > + /** The total_byte_cnt can either be the actual number of bytes > used > + * or an approximation of the number of bytes used based upon the > + * number of fixed sized buffers used multiplied by the buffer size. > + * In both cases the total_byte_cnt should correspond to the same set > + * of packets that were counted above. For instance, if the > + * total_pkt_cnt is updated in a batch, then the total_byte_cnt should > + * also be updated in the same batch. The approx_byte_cnt field below > + * indicates whether the total_byte_cnt is buffer count based or not. > + * In the case that the number of bytes used by a packet is rounded up > + * to a 2, 4, 8, or 16 byte boundary, it is recommended that > + * approx_byte_cnt be false. It is implementation dependent whether > + * the byte count of a packet includes the CRC, but it is recommended > + * that it not include headroom, preamble or IPG. Of course when the > + * buffer counting method is used, it is expected that any headroom in > + * the first buffer is implicitly included. Finally in the case of > + * variable length pkt based buffering, instead of taking the > + * total_pkt_cnt and multiplying it by the maximum ethernet packet > + * size, it is recommended that byte_cnt_valid be FALSE - even when > + * query_flags includes ODP_TM_QUERY_BYTE_CNT. > + */ > + uint64_t total_byte_cnt; > + > + /** If the requested set of tm_queues has an odp_tm_threshold_t > + * profile associated with it, then this is the max_byte_cnt set in > + * the profile params. Returning this field is a convenience to the > + * ODP programmer, enabling them to quickly see how the total_byte_cnt > + * compares to the maximum byte count threshold. Note that there is > + * no requirement that total_byte_cnt be <= max_byte_cnt. > + */ > + uint64_t max_byte_cnt; > + > + /** The following boolean values indicate which of the counts above > + * are valid. Invalid count values must be 0. > + */ > + odp_bool_t total_pkt_cnt_valid; /**< TRUE if total_pkt_cnt is valid > */ > + odp_bool_t max_pkt_cnt_valid; /**< TRUE if max_pkt_cnt is valid */ > + odp_bool_t total_byte_cnt_valid; /**< TRUE if total_byte_cnt is valid > */ > + odp_bool_t max_byte_cnt_valid; /**< TRUE if max_byte_cnt is valid > */ > + > + /** The approx_byte_cnt is TRUE if the total_byte_cnt field is > valid > + * AND if the buffer counting method is used. > + */ > + odp_bool_t approx_byte_cnt; > +} odp_tm_queue_info_t; > + > +/** The odp_tm_queue_query() function can be used to check a single > tm_queue's > + * queue utilization. The query_flags indicate whether or not packet > counts, > + * byte counts or both are being requested. It is an error to request > + * neither. The implementation may still return both sets of counts > + * regardless of query_flags if the cost of returning all the counts is > + * comparable to the cost of checking the query_flags. > + * > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the > + * TM system). > + * @param[out] query_flags A set of flag bits indicating which counters > are > + * being requested to be returned in the info > record. > + * @param[out] info Pointer to an odp_tm_queue_info_t record where > the > + * requested queue info is returned. > + * @return Returns 0 upon success, < 0 upon failure. > + */ > +int odp_tm_queue_query(odp_tm_queue_t tm_queue, > + uint32_t query_flags, > + odp_tm_queue_info_t *info); > + > +/** The odp_tm_priority_query() function can be used to check the queue > + * utilization of all tm_queue's with the given priority. The query_flags > + * indicate whether or not packet counts, byte counts or both are being > + * requested. It is an error to request neither. The implementation may > + * still return both sets of counts regardless of query_flags if the cost > of > + * returning all the counts is comparable to the cost of checking the > + * query_flags. > + * > + * @param[in] odp_tm Specifies the TM system. > + * @param[in] priority Supplies the strict priority level used to > specify > + * which tm_queues are included in the info > values. > + * @param[out] query_flags A set of flag bits indicating which counters > are > + * being requested to be returned in the info > record. > + * @param[out] info Pointer to an odp_tm_queue_info_t record where > the > + * requested queue info is returned. > + * @return Returns 0 upon success, < 0 upon failure. > + */ > +int odp_tm_priority_query(odp_tm_t odp_tm, uint8_t priority, > + uint32_t query_flags, odp_tm_queue_info_t *info); > + > +/** The odp_tm_total_query() function can be used to check the queue > + * utilization of all tm_queue's in a single TM system. The query_flags > + * indicate whether or not packet counts, byte counts or both are being > + * requested. It is an error to request neither. The implementation may > + * still return both sets of counts regardless of query_flags if the cost > of > + * returning all the counts is comparable to the cost of checking the > + * query_flags. > + * > + * @param[in] odp_tm Specifies the TM system. > + * @param[out] query_flags A set of flag bits indicating which counters > are > + * being requested to be returned in the info > record. > + * @param[out] info Pointer to an odp_tm_queue_info_t record where > the > + * requested queue info is returned. > + * @return Returns 0 upon success, < 0 upon failure. > + */ > +int odp_tm_total_query(odp_tm_t odp_tm, uint32_t query_flags, > + odp_tm_queue_info_t *info); > + > +/** The odp_tm_priority_threshold_config() function is only used to > associate > + * a maximum packet count and/or a maximum byte count with a strict > priority > + * level - for the benefit of the odp_tm_priority_query() function. It > has no > + * semantic effects other than returning these queue threshold values in > the > + * odp_tm_queue_info_t record. > + * > + * @param[in] odp_tm Specifies the TM system. > + * @param[in] priority Supplies the strict priority level that > + * the threshold profile params are > associated > + * with. > + * @param[in] thresholds_profile Specifies the queue threshold profile > that > + * should now be associated with the > supplied > + * strict priority level. > + * @return Returns 0 upon success and < 0 upon > failure. > + */ > +int odp_tm_priority_threshold_config(odp_tm_t odp_tm, uint8_t priority, > + odp_tm_threshold_t thresholds_profile); > + > +/** The odp_tm_total_threshold_config() function is only used to associate > a > + * maximum packet count and/or a maximum byte count with a TM system - for > the > + * benefit of the odp_tm_total_query() function. It has no semantic > effects > + * other than returning these queue threshold values in the > + * odp_tm_queue_info_t record. > + * > + * @param[in] odp_tm Specifies the TM system. > + * @param[in] thresholds_profile Specifies the queue threshold profile > that > + * should now be used for the entire TM > + * system. > + * @return Returns 0 upon success and < 0 upon > failure. > + */ > +int odp_tm_total_threshold_config(odp_tm_t odp_tm, > + odp_tm_threshold_t thresholds_profile); > + > +/** Misc functions */ > + > +/** The odp_tm_periodic_update function is a placeholder for any external > + * source of periodic events. In some cases the TM system may already > have an > + * internal built-in source of periodic events - in which case calling > this > + * function has no effect. > + */ > +void odp_tm_periodic_update(void); > + > +/** The odp_tm_is_idle function is used to determine if the specified ODP > + * traffic management system still has "work" to do (i.e. has at least one > + * non-empty tm_queue and perhaps some outstanding timers etc). This > function > + * can be used by test programs and ODP applications that wish to know > when > + * TM system has completed its work - presumably after they have stopped > + * sending in new pkts. Note that this function should not be called > often > + * since for some implementations this call could take a fairly long time > + * to execute! > + * > + * @param[in] odp_tm Specifies the TM system. > + * @return Returns 1 if the TM system is idle and 0 otherwise. > + */ > +odp_bool_t odp_tm_is_idle(odp_tm_t odp_tm); > + > +/** The odp_tm_stats_print function is used to write implementation- > defined > + * information about the specified TM system to the ODP log. The intended > use > + * is for debugging. > + * > + * @param[in] odp_tm Specifies the TM system. > + */ > +void odp_tm_stats_print(odp_tm_t odp_tm); > + > +/** > + * @} > + */ > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-generic/include/odp/plat/packet_types.h > b/platform/linux-generic/include/odp/plat/packet_types.h > index 45cb801..c3be633 100644 > --- a/platform/linux-generic/include/odp/plat/packet_types.h > +++ b/platform/linux-generic/include/odp/plat/packet_types.h > @@ -36,6 +36,17 @@ typedef ODP_HANDLE_T(odp_packet_seg_t); > > #define ODP_PACKET_SEG_INVALID _odp_cast_scalar(odp_packet_seg_t, > 0xffffffff) > > +/** odp_packet_color_t assigns names to the various pkt "colors" */ > +typedef enum { > + ODP_PACKET_GREEN = 0, > + ODP_PACKET_YELLOW = 1, > + ODP_PACKET_RED = 2, > + ODP_PACKET_ALL_COLORS = 3, > +} odp_packet_color_t; > + > +/** Sets the maximum number of pkt "colors" */ > +#define ODP_NUM_PACKET_COLORS 3 > + > /** Get printable format of odp_packet_t */ > static inline uint64_t odp_packet_to_u64(odp_packet_t hdl) > { > diff --git a/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > b/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > new file mode 100644 > index 0000000..52df64b > --- /dev/null > +++ b/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > @@ -0,0 +1,185 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/** > + * @file > + * > + * ODP traffic mngr > + */ > + > +#ifndef ODP_TRAFFIC_MNGR_TYPES_H_ > +#define ODP_TRAFFIC_MNGR_TYPES_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include <odp/std_types.h> > +#include <odp/plat/strong_types.h> > + > +/** @addtogroup odp_traffic_mngr > + * Macros and operations on a TM system. > + * @{ > + */ > + > +/** The ODP_TM_MAX_NUM_SYSTEMS constant specifies the maximum number of TM > + * systems that may be created. On some platforms this might be much more > + * limited to as little as one hardware TM system. > + */ > +#define ODP_TM_MAX_NUM_SYSTEMS 64 > + > +/** The ODP_TM_MAX_PRIORITIES constant specifies the largest range of > + * priorities that any TM system can support. All strict priority values > MUST > + * in the range 0..ODP_TM_MAX_PRIORITIES-1. > + */ > +#define ODP_TM_MAX_PRIORITIES 16 > + > +/** The ODP_TM MAX_LEVELS constant specifies the largest range of > + * tm_node levels that any TM system can support. Hence all tm_node level > + * values MUST be in the range 0..ODP_TM_MAX_LEVELS-1. Smaller tm_node > + * levels are associated with tm_nodes closer to the TM system egress. > + */ > +#define ODP_TM_MAX_LEVELS 8 > + > +/** > + * The smallest SCHED weight is 1 (i.e. 0 is not a legal WFQ/WRR value). > + */ > +#define ODP_TM_MIN_SCHED_WEIGHT 1 > + > +/** The ODP_TM_MAX_SCHED_WEIGHT constant is the largest weight any TM > system > + * can support (at least from a configuration standpoint). A given TM > system > + * could have a smaller value. > + */ > +#define ODP_TM_MAX_SCHED_WEIGHT 255 > + > +/** The ODP_TM_MAX_TM_QUEUES constant is the largest number of tm_queues > + * that can handled by any one TM system. > + */ > +#define ODP_TM_MAX_TM_QUEUES (16 * 1024 * 1024) > + > +/** The ODP_TM_MAX_NUM_OUTPUTS constant is the largest number of outputs > that > + * can be configured for any one TM system. > + */ > +#define ODP_TM_MAX_NUM_OUTPUTS 256 > + > +/** The ODP_TM_MAX_NUM_TM_NODES constant is the largest number of tm_nodes > that > + * can be in existence for any one TM system. > + */ > +#define ODP_TM_MAX_NUM_TM_NODES (1024 * 1024) > + > +/** The ODP_TM_MAX_TM_NODE_FANIN constant is the largest number of fan-in > + * "inputs" that can be simultaneously connected to a single tm_node. > + * *TBD* Does this need to be as large as ODP_TM_MAX_TM_QUEUES? *TBD* > + */ > +#define ODP_TM_MAX_TM_NODE_FANIN (1024 * 1024) > + > +/** The ODP_TM_MIN_SHAPER_BW constant is the smallest amount of bandwidth > that > + * can a shaper's peak or commit rate can be set to. It is in units of > + * 1000 bytes/second so that it and the ODP_TM_MAX_SHAPER_BW can both fit > in > + * 32 bits. > + */ > +#define ODP_TM_MIN_SHAPER_BW 1 > + > +/** The ODP_TM_MAX_SHAPER_BW constant is the largest amound of bandwidth > that > + * any shaper's peak or commit rate can be set to. It is in units of > + * 1000 bytes/second so that it and the ODP_TM_MIN_SHAPER_BW can both fit > in > + * 32 bits. > + */ > +#define ODP_TM_MAX_SHAPER_BW 12500000 > + > +/** The ODP_NUM_SHAPER_COLORS constant just counts the number of > enumeration > + * values defined in the odp_tm_shaper_color_t type. > + */ > +#define ODP_NUM_SHAPER_COLORS 3 > + > +/** The INVALID_PRIORITY constant is used when one needs to indicate an > + * invalid priority value. > + */ > +#define ODP_TM_INVALID_PRIORITY 255 > + > +/** The odp_tm_percent_t type is used when specifying fields that are > + * percentages. It is a fixed point integer whose units are 1/100 of a > + * percent. Hence 100% is represented as the integer value 10000. Note > + * that because it is often used as a ratio of the current queue value and > + * maximum queue threshold, it can be > 100%, but in any event will never > + * be larger than 500% (i.e. it MUST be capped at 50000). > + */ > +typedef uint16_t odp_tm_percent_t; > + > +/** The odp_tm_handle_t type is a generic type that can stand for any of > the > + * other ODP_TM handle types. > + */ > +typedef uint64_t odp_tm_handle_t; > + > +/** Each odp_tm_t value represents a specific TM system. Almost all > + * functions in this API require a odp_tm_t value - either directly > + * as a function parameter or indirectly by having another ODP TM handle > value > + * as a function parameter. > + */ > +typedef odp_tm_handle_t odp_tm_t; > + > +/** Each odp_tm_queue_t value is an opaque ODP handle representing a > specific > + * tm_queue within a specific TM system. > + */ > +typedef odp_tm_handle_t odp_tm_queue_t; > + > +/** Each odp_tm_node_t value is an opaque ODP handle representing a > specific > + * tm_node within a specific TM system. > + */ > +typedef odp_tm_handle_t odp_tm_node_t; > + > +/** Each odp_tm_shaper_t value is an opaque ODP handle representing a > specific > + * shaper profile usable across all TM systems described by this API. A > given > + * shaper profile can then be attached to any tm_queue or tm_node. > + */ > +typedef odp_tm_handle_t odp_tm_shaper_t; > + > +/** Each odp_tm_sched_t value is an opaque ODP handle representing a > specific > + * tm_node scheduler profile usable across all TM systems described by > this > + * API. A given tm_node scheduler profile can then be attached to any > tm_node. > + */ > +typedef odp_tm_handle_t odp_tm_sched_t; > + > +/** Each odp_tm_threshold_t value is an opaque ODP handle representing a > + * specific queue threshold profile usable across all TM systems described > by > + * this API. A given queue threshold profile can then be attached to any > + * tm_queue or tm_node. > + */ > +typedef odp_tm_handle_t odp_tm_threshold_t; > + > +/** Each odp_tm_wred_t value is an opaque ODP handle representing a > specific > + * WRED profile usable across all TM systems described by this API. A > given > + * WRED profile can then be attached to any tm_queue or tm_node. > + */ > +typedef odp_tm_handle_t odp_tm_wred_t; > + > +/** The ODP_TM_INVALID constant can be used with any ODP TM handle type > and > + * indicates that this value does NOT represent a valid TM object. > + */ > +#define ODP_TM_INVALID 0 > + > +/** > + * @def ODP_TM_ROOT > + * Constant that is used to refer to the egress/root node of the TM > subsystem's > + * tree/hierarchy of nodes. > + */ > +#define ODP_TM_ROOT 0 > + > +/** Get printable format of odp_queue_t */ > +static inline uint64_t odp_tm_handle_to_u64(odp_tm_handle_t hdl) > +{ > + return hdl; > +} > + > +/** > + * @} > + */ > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-generic/include/odp/traffic_mngr.h > b/platform/linux-generic/include/odp/traffic_mngr.h > new file mode 100644 > index 0000000..3aa6267 > --- /dev/null > +++ b/platform/linux-generic/include/odp/traffic_mngr.h > @@ -0,0 +1,35 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +/** > + * @file > + * > + * ODP Traffic manager > + */ > + > +#ifndef ODP_PLAT_TRAFFIC_MNGR_H_ > +#define ODP_PLAT_TRAFFIC_MNGR_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/** @ingroup odp_traffic_mngr > + * @{ > + */ > + > +/** > + * @} > + */ > + > +#include <odp/plat/traffic_mngr_types.h> > +#include <odp/api/traffic_mngr.h> > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-generic/include/odp_packet_internal.h > b/platform/linux-generic/include/odp_packet_internal.h > index ba2cd7e..d3eaad0 100644 > --- a/platform/linux-generic/include/odp_packet_internal.h > +++ b/platform/linux-generic/include/odp_packet_internal.h > @@ -61,6 +61,9 @@ typedef union { > uint32_t tcpopt:1; /**< TCP options present */ > uint32_t sctp:1; /**< SCTP */ > uint32_t icmp:1; /**< ICMP */ > + > + uint32_t color:2; /**< Packet color for traffic mgmt */ > + uint32_t nodrop:1; /**< Drop eligibility status */ > }; > } input_flags_t; > > @@ -102,6 +105,8 @@ typedef union { > uint32_t l3_chksum:1; /**< L3 chksum override */ > uint32_t l4_chksum_set:1; /**< L3 chksum bit is valid */ > uint32_t l4_chksum:1; /**< L4 chksum override */ > + > + int8_t shaper_len_adj; /**< adjustment for traffic mgr */ > }; > } output_flags_t; > > -- > 2.1.4 > > _______________________________________________ > lng-odp mailing list > lng-odp@lists.linaro.org<mailto:lng-odp@lists.linaro.org> > https://lists.linaro.org/mailman/listinfo/lng-odp
I think whether they implementation uses enum values or #defines is independent at that level. The abstract type odp_packet_color_t may or may not be an enum at the implementation's option. On Fri, Oct 23, 2015 at 5:37 AM, Savolainen, Petri (Nokia - FI/Espoo) < petri.savolainen@nokia.com> wrote: > OK. Didn’t try, I was just wondering if @def is correct keyword for enum > values. > > > > -Petri > > > > > > *From:* EXT Bill Fischofer [mailto:bill.fischofer@linaro.org] > *Sent:* Friday, October 23, 2015 1:34 PM > *To:* Savolainen, Petri (Nokia - FI/Espoo) > *Cc:* lng-odp@lists.linaro.org; Barry Spinney > *Subject:* Re: [lng-odp] [API-NEXT PATCHv6 1/4] api: tm: add tm API > definitions > > > > They seem to show up just fine under the enumerations of the packet > section. What issues do you see? > > > > On Fri, Oct 23, 2015 at 3:12 AM, Savolainen, Petri (Nokia - FI/Espoo) < > petri.savolainen@nokia.com> wrote: > > Reviewed-by: Petri Savolainen <petri.savolainen@nokia.com> > > > Bill, did you run 'make doxygen-html'? > > Not sure if @def ODP_PACKET_GREEN works when it's actually an enum. Anyway, > it's in the correct file now. > > -Petri > > > > > > -----Original Message----- > > From: lng-odp [mailto:lng-odp-bounces@lists.linaro.org] On Behalf Of EXT > > Bill Fischofer > > Sent: Thursday, October 22, 2015 11:44 PM > > To: lng-odp@lists.linaro.org > > Cc: Barry Spinney > > Subject: [lng-odp] [API-NEXT PATCHv6 1/4] api: tm: add tm API definitions > > > > From: Barry Spinney <spinney@ezchip.com> > > > > This introduces an API for configuring and using Traffic Management > > systems. > > > > The purpose of this API is as a general packet scheduling system that > > accepts packets from input queues and applies strict priority > > scheduling, weighted fair queuing scheduling and/or bandwidth controls > > to decide which input packet should be chosen as the next output > > packet and when this output packet can be sent onwards. > > > > Signed-off-by: Barry Spinney <spinney@ezchip.com> > > Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org> > > --- > > include/odp.h | 1 + > > include/odp/api/packet.h | 69 + > > include/odp/api/traffic_mngr.h | 1611 > > ++++++++++++++++++++ > > .../linux-generic/include/odp/plat/packet_types.h | 11 + > > .../include/odp/plat/traffic_mngr_types.h | 185 +++ > > platform/linux-generic/include/odp/traffic_mngr.h | 35 + > > .../linux-generic/include/odp_packet_internal.h | 5 + > > 7 files changed, 1917 insertions(+) > > create mode 100644 include/odp/api/traffic_mngr.h > > create mode 100644 platform/linux- > > generic/include/odp/plat/traffic_mngr_types.h > > create mode 100644 platform/linux-generic/include/odp/traffic_mngr.h > > > > diff --git a/include/odp.h b/include/odp.h > > index 825c7e1..f6a6ea9 100644 > > --- a/include/odp.h > > +++ b/include/odp.h > > @@ -56,6 +56,7 @@ extern "C" { > > #include <odp/thrmask.h> > > #include <odp/spinlock_recursive.h> > > #include <odp/rwlock_recursive.h> > > +#include <odp/traffic_mngr.h> > > > > #ifdef __cplusplus > > } > > diff --git a/include/odp/api/packet.h b/include/odp/api/packet.h > > index 5d46b7b..0680b3f 100644 > > --- a/include/odp/api/packet.h > > +++ b/include/odp/api/packet.h > > @@ -48,6 +48,26 @@ extern "C" { > > * Invalid packet segment > > */ > > > > + /** > > + * @typedef odp_packet_color_t > > + * Color of packet for shaper/drop processing > > + */ > > + > > + /** > > + * @def ODP_PACKET_GREEN > > + * Packet is green > > + */ > > + > > + /** > > + * @def ODP_PACKET_YELLOW > > + * Packet is yellow > > + */ > > + > > + /** > > + * @def ODP_PACKET_RED > > + * Packet is red > > + */ > > + > > /* > > * > > * Alloc and free > > @@ -700,6 +720,55 @@ odp_packet_seg_t odp_packet_last_seg(odp_packet_t > > pkt); > > */ > > odp_packet_seg_t odp_packet_next_seg(odp_packet_t pkt, odp_packet_seg_t > > seg); > > > > +/** > > + * Get packet color > > + * > > + * @param pkt Packet handle > > + * @return packet color > > + */ > > +odp_packet_color_t odp_packet_color(odp_packet_t pkt); > > + > > +/** > > + * Set packet color > > + * > > + * @param pkt Packet handle > > + * @param color Color to set > > + */ > > +void odp_packet_color_set(odp_packet_t pkt, odp_packet_color_t color); > > + > > +/** > > + * Get drop eligible status > > + * > > + * @param pkt Packet handle > > + * @return Packet drop eligibility status > > + * @retval 0 Packet is not drop eligible > > + * @retval 1 Packet is drop > > + */ > > +odp_bool_t odp_packet_drop_eligible(odp_packet_t pkt); > > + > > +/** > > + * Set drop eligible status > > + * > > + * @param pkt Packet handle > > + * @param status Drop eligibility status > > + */ > > +void odp_packet_drop_eligible_set(odp_packet_t pkt, odp_bool_t status); > > + > > +/** > > + * Get shaper length adjustment > > + * > > + * @param pkt Packet handle > > + * @return Shaper adjustment (-128..127) > > + */ > > +int8_t odp_packet_shaper_len_adjust(odp_packet_t pkt); > > + > > +/** > > + * Set shaper length adjustment > > + * > > + * @param pkt Packet handle > > + * @param adj Signed adjustment value > > + */ > > +void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, int8_t adj); > > > > /* > > * > > diff --git a/include/odp/api/traffic_mngr.h > > b/include/odp/api/traffic_mngr.h > > new file mode 100644 > > index 0000000..2459a8b > > --- /dev/null > > +++ b/include/odp/api/traffic_mngr.h > > @@ -0,0 +1,1611 @@ > > +/** Copyright (c) 2015, Linaro Limited > > + * All rights reserved. > > + * > > + * SPDX-License-Identifier: BSD-3-Clause > > + */ > > + > > +#ifndef ODP_TRAFFIC_MNGR_H_ > > +#define ODP_TRAFFIC_MNGR_H_ > > + > > +#ifdef __cplusplus > > +extern "C" { > > +#endif > > + > > +#include <odp/std_types.h> > > +#include <odp/packet_io.h> > > + > > +/** > > + * @file > > + * > > + */ > > + > > +/** @defgroup odp_traffic_mngr ODP TRAFFIC MNGR > > + * @{ > > + * > > + * An API for configuring and using Traffic Management systems > > + * > > + * This file forms a simple interface for creating, configuring and > using > > + * Traffic Management (TM) subsystems. By TM subsystem it is meant a > > general > > + * packet scheduling system that accepts packets from input queues and > > applies > > + * strict priority scheduling, weighted fair queueing scheduling and/or > > + * bandwidth controls to decide which input packet should be chosen as > the > > + * next output packet and when this output packet can be sent onwards. > > + * > > + * A given platform supporting this TM API could support one or more > pure > > + * hardware based packet scheduling systems, one or more pure software > > + * based systems or one or more hybrid systems - where because of > > + * hardware constraints some of the packet scheduling is done in > hardware > > + * and some is done in software. In addition, there may also be > > additional > > + * API's beyond those described here for (a) controlling advanced > > capabilities > > + * supported by specific hardware, software or hybrid subsystems or (b) > > + * dealing with constraints and limitations of specific implementations. > > + * The intention here is to be the simplest API that covers the vast > > majority > > + * of packet scheduling requirements. > > + * > > + * Often a TM subsystem's output(s) will be directly connected > > + * to a device's physical (or virtual) output interfaces/links, in which > > case > > + * sometimes such a system will be called an Egress Packet Scheduler or > an > > + * Output Link Shaper, etc.. While the TM subsystems configured by this > > API > > + * can be used in such a way, this API equally well supports the ability > > to > > + * have the TM subsystem's outputs connect to other TM subsystem input > > queues > > + * or general software queues or even some combination of these three > > cases. > > + * > > + * <H2>TM Algorithms</H2> > > + * > > + * The packet scheduling/dropping techniques that can be applied to > input > > + * traffic include any mixture of the following: > > + * <ol> > > + * <li> Strict Priority scheduling. > > + * <li> Weighted Fair Queueing scheduling (WFQ). > > + * <li> Bandwidth Shaping. > > + * <li> Weighted Random Early Discard (WRED). > > + * </ol> > > + * Note that Bandwidth Shaping is the only feature that can cause > packets > > + * to be "delayed", and Weighted Random Early Discard is the only > feature > > + * (other than input queues becoming full) that can cause packets to be > > + * dropped. > > + * > > + * <H3>Strict Priority Scheduling</H3> > > + * Strict Priority Scheduling (or just priority for short), is a > technique > > + * where input queues and the packets from them, are assigned a priority > > + * value in the range 0 .. ODP_TM_MAX_PRIORITIES - 1. At all times > > packets > > + * the the smallest priority value will be chosen ahead of packets with > a > > + * numerically larger priority value. This is called strict priority > > + * scheduling because the algorithm strictly enforces the scheduling of > > + * higher priority packets over lower priority packets. > > + * > > + * <H3>Bandwidth Shaping</H3> > > + * Bandwidth Shaping (or often just Shaping) is the term used here for > the > > + * idea of controlling packet rates using single rate and/or dual rate > > token > > + * bucket algorithms. For single rate shaping a rate (the commit rate) > > and > > + * a "burst size" (the maximum commit count) are configured. Then an > > + * internal signed integer counter called the commitCnt is maintained > such > > + * that if the commitCnt is positive then packets are eligible to be > sent. > > + * When such a packet is actually sent then its commitCnt is decremented > > + * (usually by its length, but one could decrement by 1 for each packet > > + * instead). The commitCnt is then incremented periodically based upon > > the > > + * configured rate, so that this technique causes the traffic to be > > limited > > + * to the commit rate over the long term, while allowing some ability to > > + * exceed this rate for a very short time (based on the burst size) in > > order > > + * to catch up if the traffic input temporarily drops below the commit > > rate. > > + * > > + * Dual Rate Shaping is designed to allow certain traffic flows to > fairly > > + * send more than their assigned commit rate when the scheduler has > > excess > > + * capacity. The idea being that it may be better to allow some types > of > > + * traffic to send more than their committed bandwidth rather than > letting > > + * the TM outputs be idle. The configuration of Dual Rate Shaping > > requires > > + * additionally a peak rate and a peak burst size. The peak rate must > be > > + * greater than the related comls mit rate, but the burst sizes have no > > similar > > + * constraint. Also for every input priority that has Dual Rate shaping > > + * enabled, there needs to be an additional equal or lower priority > (equal > > or > > + * higher numeric priority value) assigned. Then if the traffic exceeds > > its > > + * commit rate but not its peak rate, the "excess" traffic will be sent > at > > the > > + * lower priority level - which by the strict priority algorithm should > > + * cause no degradation of the higher priority traffic, while allowing > for > > + * less idle outputs. > > + * > > + * <H3>Weighted Fair Queuing</H3> > > + * Weighted Fair Queuing (WFQ) is used to arbitrate amongst multiple > input > > + * packets with the same priority. Each input can be assigned a weight > in > > the > > + * range MIN_WFQ_WEIGHT..MAX_WFQ_WEIGHT (nominally 1..255) that affects > > the way > > + * the algorithm chooses the next packet. If all of the weights are > equal > > AND > > + * all of the input packets are the same length then the algorithm is > > + * equivalent to a round robin scheduling. If all of the weights are > > equal > > + * but the packets have different lengths then the WFQ algorithm will > > attempt > > + * to choose the packet such that inputs each get a fair share of the > > + * bandwidth - in other words it implements a weighted round robin > > algorithm > > + * where the weighting is based on frame length. > > + * > > + * When the input weights are not all equal and the input packet lengths > > vary > > + * then the WFQ algorithm will schedule packets such that the packet > with > > + * the lowest "Virtual Finish Time" is chosen first. An input packet's > > + * Virtual Finish Time is roughly calculated based on the WFQ object's > > base > > + * Virtual Finish Time when the packet becomes the first packet in its > > queue > > + * plus its frame length divided by its weight. > > + * @code > > + * virtualFinishTime = wfqVirtualTimeBase + (pktLength / wfqWeight) > > + * @endcode > > + * In a system running at full capacity with no bandwidth limits - over > > the > > + * long term - each input fan-in's average transmit rate will be the > same > > + * fraction of the output bandwidth as the fraction of its weight > divided > > by > > + * the sum of all of the WFQ fan-in weights. Hence larger WFQ weights > > result > > + * in better "service" for a given fan-in. > > + * @code > > + * totalWfqWeight = 0; > > + * for (each fan-in entity - fanIn - feeding this WFQ scheduler) > > + * totalWfqWeight += fanIn->sfqWeight; > > + * > > + * fanIn->avgTransmitRate = avgOutputRate * fanIn->sfqWeight / > > totalWfqWeight; > > + * @endcode > > + * > > + * <H3>Weighted Random Early Discard</H3> > > + * The Weighted Random Early Discard (WRED) algorithm deals with the > > situation > > + * where an input packet rate exceeds some output rate (including > > + * the case where Bandwidth Shaping limits some output rates). Without > > WRED > > + * enabled and configured, the TM system will just implement a tail > > dropping > > + * scheme whereby whichever packet is unlucky enough to arrive when an > TM > > + * input queue is full will be discarded regardless of priority or any > > other > > + * consideration. > > + * WRED allows one to configure the system to use a better/fairer > > algorithm > > + * than simple tail dropping. It works by measuring the "fullness" of > > + * various packet queues and converting this percentage into a > probability > > + * of random packet dropping with the help of some configurable > > parameters. > > + * Then a random number is picked and together with the drop > probability, > > + * a decision is made to accept the packet or drop it. > > + * A basic parameterization of WRED requires three parameters: > > + * <ol> > > + * <li> the maximum queue level (which could be either a maximum number > of > > + * packets or a maximum amount of memory (i.e. bytes/buffers) > used), > > + * <li> a starting threshold - which is a number in the range 0..100 > > + * representing a percentage of the maximum queue level at which > the > > + * drop probability becomes non-zero, > > + * <li> a drop probability - which is a number in the range 0..100 > > + * representing a probability (0 means no drop and 100 means > > + * certain drop) - which is used when the queue is near 100% full. > > + * </ol> > > + * > > + * Note that all packet drops for a TM system only occur when a new > packet > > + * arrives at a given TM system input queue. At that time either the > WRED > > + * algorithm, if enabled for this input queue, or the "input queue full" > > + * tail drop algorithm will make a drop/no drop decision. After this > > point, > > + * any packets not dropped, will at some point be sent out a TM output - > > + * assuming that the topology is fully connected and enabled. > > + * > > + * <H2>Hierarchical Scheduling and tm_nodes</H2> > > + * This API supports the ability to do Hierarchical Scheduling whereby > the > > + * final scheduling decision is controlled by equal priority schedulers, > > + * strict priority multiplexers, bandwidth shapers - at multiple levels > - > > all > > + * forming a tree rooted at a single egress object. In other words, all > > + * tm_queues and tm_nodes have the property that their logical "output" > > feeds > > + * into one fan-in of a subsequent tm_node or egresss object - forming a > > proper > > + * tree. See the following link - > > + * <A HREF="diagram1.svg">Example Tm_node</A> - for an example. > > + * > > + * Multi-level/hierarchical scheduling adds both great control and > > significant > > + * complexity. Logically, despite the implication of the tm_node tree > > + * diagrams, there are no queues between the levels of hierarchy. > Instead > > all > > + * packets are held in their input queue, until such time that the > > totality of > > + * all of the tm_nodes in the single path from input queue to output > > object > > + * agrees that this packet should be the next to be chosen to leave the > TM > > + * system through the output object "portal". Hence what flows from > level > > to > > + * level is the "local choice" of what packet/tm_queue should next be > > + * serviced. > > + * > > + * <H3>tm_nodes</H3> > > + * Tm_nodes are the main "entity"/object that a TM system is composed > of. > > + * Each tm_node is a mini-TM subsystem of its own, but the > interconnection > > + * and interplay of a multi-level "tree" of tm_nodes can allow the user > > + * to specify some very sophisticated behaviours. > > + * Each tm_node can contain a set of scheduler (one per strict priority > > level), > > + * a strict priority multiplexer, a bandwidth shaper and a WRED > component > > - or > > + * a subset of these. > > + * > > + * In its full generality an tm_node consists of a set of "fan-in" > > connections > > + * to preceding tm_queues or tm_nodes. The fan-in for a single tm_node > > + * can range from 1 to many many thousands. This fan-in is divided > first > > + * into a WFQ scheduler per priority level. So if 4 priority levels are > > + * implemented by this tm_node, there would be 4 WFQ schedulers - each > > with > > + * its own unique fan-in. After the WFQ schedulers a priority chooser > > comes > > + * next - where it will always choose the highest priority WFQ output > > + * available. The output of the priority chooser then feeds a bandwidth > > + * shaper function which then finally uses the shaper's propagation > table > > + * to determine its output packet and its priority. This output could > > + * then be remapped via a priority map profile and then becomes one of > the > > + * input fan-in to perhaps another level of tm_nodes, and so on. > > + * > > + * During this process it is important to remember that the bandwidth > > shaping > > + * function never causes packets to be dropped. Instead all packet > drops > > + * occur because of tm_queue fullness or be running the WRED algorithm > > + * at the time a new packet attempts to be appended to the end of some > > + * input queue. > > + * > > + * The WRED profile associated with an tm_node considers the entire set > of > > + * tm_queues feeding directly or indirectly into it as its measure of > > + * queue fullness. > > + * > > + * <H3>tm_queues</H3> > > + * tm_queues are the second major type of "entity"/object that a TM > > + * system is composed of. All packets MUST first enter the TM system > via > > + * some tm_queue. Then logically, the head packets of all of the > > tm_queues > > + * are examined simultaneously by the entire TM system, and ONE tm_queue > > is > > + * chosen send its head packet out of the TM system's egress. > Abstractly > > + * packets stay in the tm_queue until they are chosen at which time they > > are > > + * instantly transferred from tm_queue to/through the corresponding TM > > egress. > > + * It is also important to note that packets in the same tm_queue MUST > > always > > + * stay in order. In other words, the second packet in an tm_queue must > > never > > + * leave the TM system through a TM egress spigot before the first > packet > > has > > + * left the system. So tm_queue packet order must always be maintained. > > + * > > + * <H3>TM egress</H3> > > + * Note that TM egress objects are NOT referred to as queues, because in > > + * many/most cases they don't have multi-packet structure but instead > are > > + * viewed as a port/spigot through which the TM system schedules and > > finally > > + * transfers input packets through. > > + * > > + * <H2>Ideal versus Actual Behavior</H2> > > + * It is important to recognize the difference between the "abstract" > > + * mathematical model of the prescribed behavior and real > implementations. > > + * The model describes the Ideal, but theoretically desired behavior, > but > > such > > + * an Ideal is generally not practical to implement. Instead, one > > understands > > + * that virtually all Real TM systems attempt to approximate the Ideal > > behavior > > + * as given by the TM configuration as best as they can - while still > > + * attaining high packet processing performance. The idea is that > instead > > of > > + * trying too hard to be "perfect" at the granularity of say > microseconds, > > it > > + * may be better to instead try to match the long term Ideal behavior > over > > a > > + * much more reasonable period of time like a millisecond. It is > > generally > > + * better to have a stable implementation that when averaged over a > period > > of > > + * several milliseconds matches the Ideal behavior very closely than to > > have > > + * an implementation that is perhaps more accurate over a period of > > + * microseconds, but whose millisecond averaged behavior drifts away > from > > the > > + * Ideal case. > > + * > > + * <H2>Other TM Concepts</H2> > > + * > > + * <H3>Profiles</H3> > > + * This specification often packages related TM system parameters into > > + * records/objects called profiles. These profiles can then be > associated > > with > > + * various entities like tm_nodes and tm_queue's. This way the amount > of > > + * storage associated with setting related parameters can be reduced and > > + * in addition it is common to re-use the same set of parameter set over > > + * and over again, and also to be able to change the parameter set once > > + * and have it affect lots of entities with which it is associated > > with/applied > > + * to. > > + * > > + * <H3>Absolute Limits versus odp_tm_capability_t</H3> > > + * This header file defines some constants representing the absolute > > maximum > > + * settings for any TM system, though in most cases a TM system can (and > > + * should) be created/instantiated with smaller values, since lower > values > > + * will often result in faster operation and/or less memory used. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_NUM_SYSTEMS > > + * The maximum number of TM systems that may be created. On some > > platforms > > + * this might be much more limited to as little as one hardware TM > system. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_PRIORITIES > > + * The largest range of priorities that any TM system can support. All > > strict > > + * priority values MUST in the range 0..ODP_TM_MAX_PRIORITIES-1. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_LEVELS > > + * The largest range of tm_node levels that any TM system can support. > > Hence > > + * all tm_node level values MUST be in the range 0..ODP_TM_MAX_LEVELS-1. > > + * Smaller tm_node levels are associated with tm_nodes closer to the TM > > system > > + * egress. > > + */ > > + > > +/** > > + * @def ODP_TM_MIN_SCHED_WEIGHT > > + * The smallest SCHED weight is 1 (i.e. 0 is not a legal WFQ/WRR value). > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_SCHED_WEIGHT > > + * The largest weight any TM system can support (at least from a > > configuration > > + * standpoint). A given TM system could have a smaller value. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_TM_QUEUES > > + * The largest number of tm_queues that can handled by any one TM > system. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_NUM_OUTPUTS > > + * The largest number of outputs that can be configured for any one TM > > system. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_NUM_TM_NODES > > + * The largest number of tm_nodes that can be in existence for any one > TM > > + * system. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_TM_NODE_FANIN > > + * The largest number of fan-in "inputs" that can be simultaneously > > connected > > + * to a single tm_node. > > + * @todo Does this need to be as large as ODP_TM_MAX_TM_QUEUES? > > + */ > > + > > +/** > > + * @def ODP_TM_MIN_SHAPER_BW > > + * The largest amound of bandwidth that any shaper's peak or commit rate > > can > > + * be set to. It is in units of 1000 bytes/second. > > + */ > > + > > +/** > > + * @def ODP_TM_MAX_SHAPER_BW > > + * The largest amound of bandwidth that any shaper's peak or commit rate > > can > > + * be set to. It is in units of 1000 bytes/second. > > + */ > > + > > +/** > > + * @def ODP_NUM_SHAPER_COLORS > > + * The number of enumeration values defined in the odp_tm_shaper_color_t > > type. > > + */ > > + > > +/** > > + * @def ODP_TM_INVALID_PRIORITY > > + * Used to indicate an invalid priority value. > > + */ > > + > > +/** > > + * @typedef odp_tm_percent_t > > + * Is used when specifying fields that are percentages. It is a fixed > > point > > + * integer whose units are 1/100 of a percent. Hence 100% is > represented > > as > > + * the integer value 10000. Note that because it is often used as a > ratio > > of > > + * the current queue value and maximum queue threshold, it can be > > 100%, > > but > > + * in any event will never be larger than 500% (i.e. it MUST be capped > at > > + * 50000). > > + */ > > + > > +/** > > + * @typedef odp_tm_t > > + * Each odp_tm_t value represents a specific TM system. Almost all > > functions > > + * in this API require a odp_tm_t value - either directly as a function > > + * parameter or indirectly by having another ODP TM handle value as a > > function > > + * parameter. > > + */ > > + > > +/** > > + * @typedef odp_tm_queue_t > > + * Each odp_tm_queue_t value is an opaque ODP handle representing a > > specific > > + * tm_queue within a specific TM system. > > + */ > > + > > +/** > > + * @typedef odp_tm_node_t > > + * Each odp_tm_queue_t value is an opaque ODP handle representing a > > specific > > + * tm node within a specific TM system. > > + */ > > + > > +/** > > + * @typedef odp_tm_shaper_t > > + * Each odp_tm_shaper_t value is an opaque ODP handle representing a > > specific > > + * shaper profile usable across all TM systems described by this API. A > > given > > + * shaper profile can then be attached to any tm_queue or tm_node. > > + */ > > + > > +/** > > + * @typedef odp_tm_sched_t > > + * Each odp_tm_sched_t value is an opaque ODP handle representing a > > specific > > + * tm_node scheduler profile usable across all TM systems described by > > this > > + * API. A given tm_node scheduler profile can then be attached to any > > + * tm_node. > > + */ > > + > > +/** > > + * @typedef odp_tm_threshold_t > > + * Each odp_tm_threshold_t value is an opaque ODP handle representing a > > + * specific queue threshold profile usable across all TM systems > described > > by > > + * this API. A given queue threshold profile can then be attached to > any > > + * tm_queue or tm_node. > > + */ > > + > > +/** > > + * @typedef odp_tm_wred_t > > + * Each odp_tm_wred_t value is an opaque ODP handle representing a > > specific > > + * WRED profile usable across all TM systems described by this API. A > > given > > + * WRED profile can then be attached to any tm_queue or tm_node. > > + */ > > + > > +/** > > + * @def ODP_TM_INVALID > > + * Constant that can be used with any ODP TM handle type and indicates > > that > > + * this value does NOT represent a valid TM object. > > + */ > > + > > +/** > > + * @def ODP_TM_ROOT > > + * Constant that is used to refer to the egress/root node of the TM > > subsystem's > > + * tree/hierarchy of nodes. > > + */ > > + > > +/** The odp_tm_capability_t type is used to describe the feature set and > > limits > > + * of a TM system. It is passed to the odp_tm_create() function > > indirectly > > + * by being part of the odp_tm_params_t record. > > + */ > > +typedef struct { > > + /** max_tm_queues specifies the maximum number of tm_queues that > > can > > + * be in existence for this TM System. > > + */ > > + uint32_t max_tm_queues; > > + > > + /** max_fanin_per_level specifies the maximum number of fan_in > link > > + * to any given scheduler (whether weighted or using fair queueing > or > > + * round robin) belonging to tm_nodes at the given level. > > + */ > > + uint32_t max_fanin_per_level[ODP_TM_MAX_LEVELS]; > > + > > + /** max_priority specifies the maximum number of strict priority > > + * levels used by any tm_queue or tm_node. Note that any given > > + * tm_queue or tm_node can use a subset of these levels. > max_priority > > + * must be in the range 0..ODP_TM_MAX_PRIORITIES - 1. Note that > lower > > + * numeric values represent higher (more important or time critical) > > + * priorities. > > + */ > > + uint8_t max_priority; > > + > > + /** max_levels specifies that maximum number of levels of > > hierarchical > > + * scheduling allowed by this TM System. This is a count of the > > + * tm_node stages and does not include tm_queues or tm_egress > objects. > > + * Hence any given tm_node will have associated tm_node_level in the > > + * range 0 to max_levels - 1, where tm_node's at level 0 output's > only > > + * go to egress objects and tm_nodes whose level is max_levels - 1 > > + * have their fan_in only from tm_queues. > > + */ > > + uint8_t max_levels; > > + > > + /** tm_queue_shaper_supported indicates that the tm_queues > support > > + * proper TM shaping. Note that TM Shaping is NOT the same thing as > > + * Ingress Metering/Policing as specified by RFC 2697 (A Single Rate > > + * Three Color Marker) or RFC 2698 (A Two Rate Three Color Marker). > > + * These RFC's can be used for a Diffserv traffic conditioner, or > > + * other ingress policing. They make no mention of and have no > > + * algorithms for delaying packets - which is what TM shapers are > > + * expected to do. > > + */ > > + odp_bool_t tm_queue_shaper_supported; > > + > > + /** tm_node_shaper_supported indicates that the tm_nodes (at > least > > for > > + * some hierarchical levels) support proper T < M shaping. > > + */ > > + odp_bool_t tm_node_shaper_supported; > > + > > + /** red_supported indicates that the tm_queues support some form > of > > + * Random Early Discard. > > + */ > > + odp_bool_t red_supported; > > + > > + /** hierarchical_red_supported indicates that this TM system > > supports > > + * some form of RED where the queue fullness of tm_nodes contributes > > + * to the overall RED DROP/NO-DROP decision. > > + */ > > + odp_bool_t hierarchical_red_supported; > > + > > + /** weights_supported indicates that the tm_node schedulers (at > > least > > + * for some hierarchical levels) can have their different weights > for > > + * their fan-ins. > > + */ > > + odp_bool_t weights_supported; > > + > > + /** fair_queuing_supported indicates the the tm_node schedulers > (at > > + * least for some hierarchical levels) can implement WFQ or FQ > > + * scheduling disciplines, otherwise these schedulers can only > > + * implement WRR or RR algorithms, > > + */ > > + odp_bool_t fair_queuing_supported; > > +} odp_tm_capability_t; > > + > > +/** The odp_tm_egress_fcn_t type defines the parameter profile of the > > egress > > + * function callback. Using an egress function callback is just one of > > several > > + * ways of getting packets out from an egress spigot. > > + * > > + */ > > +typedef void (*odp_tm_egress_fcn_t) (odp_packet_t odp_pkt); > > + > > +/** The tm_egress_kind_e enumeration type is used to indicate the kind > of > > + * egress object ("spigot") associated with this TM system. Most of > these > > + * kinds are optional - with ODP_TM_EGRESS_PKT_IO being the only > mandatory > > + * kind. The TM_EGRESS_FN - if implemented - is useful for testing the > TM > > + * subsystem, and users are warned that its performance might be > limited. > > + */ > > +typedef enum { > > + ODP_TM_EGRESS_PKT_IO, > > + ODP_TM_EGRESS_FN, > > +} odp_tm_egress_kind_t; > > + > > +/** The odp_tm_egress_t type is used to describe that type of "egress > > spigot" > > + * associated with this TM system. It is passed to the odp_tm_create() > > + * function indirectly by being part of the odp_tm_params_t record. > > + */ > > +typedef struct { > > + odp_tm_egress_kind_t egress_kind; /**< Union discriminator */ > > + > > + union { > > + odp_pktio_t pktio; > > + odp_tm_egress_fcn_t egress_fcn; > > + }; > > +} odp_tm_egress_t; > > + > > +/** The odp_tm_params_t record type is used to hold extra parameters > when > > + * calling the odp_tm_create() function. > > + * Since it is expected that implementations might augment this record > > type > > + * with platform specific additional fields - it is required that > > + * odp_tm_params_init() be called on variables of this type before any > of > > the > > + * fields are filled in. > > + */ > > +typedef struct { > > + odp_tm_capability_t capability; /**< capability record */ > > + odp_tm_egress_t egress; /**< describes the egress "spigot" */ > > +} odp_tm_params_t; > > + > > +/** odp_tm_capability_init() must be called to initialize any > > + * odp_tm_capability_t record before it is first used or assigned to. > > + * > > + * @param[in] capability A pointer to an odp_tm_capability_t record > which > > + * is to be initialized. > > + */ > > +void odp_tm_capability_init(odp_tm_capability_t *capability); > > + > > +/** odp_tm_params_init() must be called to initialize any > > + * odp_tm_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_params_t record which > > + * is to be initialized. > > + */ > > +void odp_tm_params_init(odp_tm_params_t *params); > > + > > +/** Create/instantiate a TM Packet Scheduling system. > > + * > > + * @param[in] name The name to be assigned to this TM system. Cannot > > be > > + * NULL, and also must be unique amongst all other TM > > system > > + * names. > > + * @param[in] params The params to be used when creating this TM > system. > > + * @return Returns ODP_TM_INVALID upon failure, otherwise the > > newly > > + * created TM system's odp_tm_t handle is returned. > > + */ > > +odp_tm_t odp_tm_create(const char *name, odp_tm_params_t *params); > > + > > +/** Find a pre-existing TM Packet Scheduling system. This function can > be > > + * used either to find a TM system created previously with odp_tm_create > > OR > > + * get the odp_tm_t of a built-in TM system - usually based on HW. In > this > > + * later case the format of the name used to refer to a specific > built-in > > + * hardware TM system may be platform dependent, but in any case a name > of > > + * "HW_TM_%u" where the number starts at 1, can be used to find a > built-in > > + * system independently of the best capability match. If name is NULL > > then > > + * the existing (built-in or created by odp_tm_create) TM system that > best > > + * matches capability is returned. > > + * > > + * @param[in] name If NULL then only uses the capability > parameter > > to > > + * find a closest match, otherwise if the name is > > + * matched by an existing TM system it is > returned. > > + * @param[in] capability Used when the name is NULL (in which > > + * case the closest match is returned) or when > the > > + * name is not-NULL, but doesn't match > > + * any existing TM system in which case the > > + * capability is used to find the FIRST > > + * TM system matching exactly these limits. > > + * @return If an existing TM system (built-in or > previously > > + * created via odp_tm_create) is found, its > > + * odp_tm_t value is returned, otherwise > > + * ODP_TM_INVALID is returned. > > + */ > > +odp_tm_t odp_tm_find(const char *name, odp_tm_capability_t *capability); > > + > > +/** odp_tm_capability() can be used to query the actual limits of a > given > > TM > > + * system. This function can be used for both built-in TM systems AND > TM > > + * system's created via odp_tm_create(). > > + * > > + * @param[in] odp_tm The odp_tm_t value of the TM system to be > > + * queried. > > + * @param[out] capability A pointer to a odp_tm_capability_t record > > + * where the actual limits used by the TM system > > are > > + * copied into. Note that these limits do NOT > > + * have to match the capability passed in if > > + * a TM system was created by odp_tm_create, > > + * but of course these limits in some cases > could > > + * be larger. > > + * @return Returns 0 upon success, < 0 upon failure > (which > > + * indicates that the odp_tm value did not > > + * exist). > > + */ > > +int odp_tm_capability(odp_tm_t odp_tm, odp_tm_capability_t *capability); > > + > > +/** odp_tm_destroy() may be used to destroy TM systems created via > > + * odp_tm_create(). It generally CANNOT be used to destroy built-in TM > > + * systems. Also some platforms MAY not support destroying of TM > systems > > + * created via odp_tm_create() under certain conditions. For example a > > given > > + * platform may require that the TM system be first "drained" of all of > > its > > + * queued packets before it will accept a odp_tm_destroy() call. > > + * > > + * In general calling odp_tm_destroy() on an active TM system does not > > + * guarantee anything about the disposition of any packets queued within > > the > > + * TM system, other than EVENTUALLY these packets will be either sent > (in > > ANY > > + * order) or freed. > > + * > > + * @param[in] odp_tm The odp_tm_t value of the TM system to be > destroyed > > (and > > + * hence destroyed (and hence freed). > > + * @return 0 upon success, < 0 upon failure. > > + */ > > +int odp_tm_destroy(odp_tm_t odp_tm); > > + > > +/** Shaper profile types and functions */ > > + > > +/** Possible values of running the shaper algorithm. > ODP_TM_SHAPER_GREEN > > + * means that the traffic is within the commit specification (rate and > > burst > > + * size), ODP_TM_SHAPER_YELLOW means that the traffic is within the peak > > + * specification (rate and burst size) and ODP_TM_SHAPER_RED means that > > the > > + * traffic is exceeding both its commit and peak specifications. Note > > that > > + * packets can also have an assigned <b> packet color</b> of > > ODP_PACKET_GREEN, > > + * ODP_PACKET_YELLOW or ODP_PACKET_RED which has a different meaning and > > + * purpose than the shaper colors. > > + */ > > +typedef enum { > > + ODP_TM_SHAPER_GREEN, ODP_TM_SHAPER_YELLOW, ODP_TM_SHAPER_RED > > +} odp_tm_shaper_color_t; > > + > > +/** The odp_tm_shaper_params_t record type is used to supply the > > parameters > > + * associated with a shaper profile. Since it is expected that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that odp_tm_shaper_params_init() > be > > + * called on variables of this type before any of the fields are filled > > in. > > + */ > > +typedef struct { > > + /** The committed information rate for this shaper profile. The > > units > > + * for this integer are always in bits per second. > > + */ > > + uint64_t commit_bps; > > + > > + /** The peak information rate for this shaper profile. The units > > for > > + * this integer are always in bits per second. > > + */ > > + uint64_t peak_bps; > > + > > + /** The commit burst tolerance for this shaper profile. The > units > > for > > + * this field are always bits. This value sets an upper limit for > the > > + * size of the commitCnt. > > + */ > > + uint32_t commit_burst; > > + > > + /** The peak burst tolerance for this shaper profile. The units > > for > > + * this field are always bits. This value sets an upper limit for > the > > + * size of the peakCnt. > > + */ > > + uint32_t peak_burst; > > + > > + /** The shaper_len_adjust is a value between -128 and 127 which > is > > + * directly added to the frame_len of a packet associated with this > > + * profile. The frame_len would normally include the outermost > > + * Ethernet header (DA, SA, ...) through to the outermost Ethernet > CRC > > + * inclusive. Hence this field - when non-zero - will usually be > set > > + * to a value approximating the "time" (in units of bytes) taken by > > + * the Ethernet preamble and Inter Frame Gap. Traditionally this > > + * would be the value 20 (8 + 12), but in same cases can be as low > as > > + * 9 (4 + 5). > > + */ > > + int8_t shaper_len_adjust; > > + > > + /** If dual_rate is TRUE it indicates the desire for the > > + * implementation to use dual rate shaping for packets associated > with > > + * this profile. The precise semantics of dual rate shaping are > > + * implementation specific, but in any case require a non-zero set > of > > + * both commit and peak parameters. > > + */ > > + odp_bool_t dual_rate; > > +} odp_tm_shaper_params_t; > > + > > +/** odp_tm_shaper_params_init() must be called to initialize any > > + * odp_tm_shaper_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_shaper_params_t record > which > > + * is to be initialized. > > + */ > > +void odp_tm_shaper_params_init(odp_tm_shaper_params_t *params); > > + > > +/** odp_tm_shaper_create() creates a shaper profile object, which can > > + * subsequently be attached to any number (including zero) of tm_queues > > + * or tm_nodes. > > + * > > + * @param[in] name Optional name associated with this shaper profile. > > Can > > + * be NULL. If non-NULL must be unique amongst the > set > > of > > + * all other shaper profiles. > > + * @param[in] params The profile parameters. See comments associated > > with > > + * the odp_tm_shaper_params_t for more details. > > + * @return Returns ODP_TM_INVALID upon failure, or the newly > > + * allocated odp_tm_shaper_t value representing this > > + * profile object. > > + */ > > +odp_tm_shaper_t odp_tm_shaper_create(const char *name, > > + odp_tm_shaper_params_t *params); > > + > > +/** odp_tm_shaper_params_read() "gets" the current set of values > > associated > > + * with the specified shaper profile object, and copies them into the > > supplied > > + * record. > > + * > > + * @param[in] shaper_profile Specifies the shaper profile object whose > > + * values are to be read. > > + * @param[out] params A pointer to an odp_tm_shaper_params_t > > record > > + * where the current shaper profile object > > values > > + * are copied to. > > + * @return Returns < 0 upon failure or 0 upon > success. > > + */ > > +int odp_tm_shaper_params_read(odp_tm_shaper_t shaper_profile, > > + odp_tm_shaper_params_t *params); > > + > > +/** odp_tm_shaper_params_update() "sets" the current set of values > > associated > > + * with the specified shaper profile object. In addition, this call has > > the > > + * effect that all tm_input's and tm_nodes that are associated > (attached?) > > + * with this shaper profile object will be updated with the new values. > > + * > > + * @param[in] shaper_profile Specifies the shaper profile object whose > > + * values are to be set. > > + * @param[in] params A pointer to an odp_tm_shaper_params_t > > record > > + * where the new shaper profile object values > > + * are taken from. > > + * @return Returns < 0 upon failure or 0 upon > success. > > + */ > > +int odp_tm_shaper_params_update(odp_tm_shaper_t shaper_profile, > > + odp_tm_shaper_params_t *params); > > + > > +/** odp_tm_shaper_lookup() can be used to find the shaper profile object > > + * created with the specified name. > > + * > > + * @param[in] name Name of a previously created shaper profile. Cannot > > be > > + * NULL. > > + * @return Returns ODP_TM_INVALID upon failure, or the shaper > > + * profile handle created with this name. > > + */ > > +odp_tm_shaper_t odp_tm_shaper_lookup(const char *name); > > + > > +/** Scheduler Profiles - types and functions */ > > + > > +/** The odp_tm_sched_mode_t type is used to control whether a tm_node > > + * scheduler takes into account packet lengths (by setting the > sched_mode > > to > > + * ODP_TM_BYTE_BASED_WEIGHTS) or instead treat packets with different > > lengths > > + * the same (by setting the sched_mode to ODP_TM_FRAME_BASED_WEIGHTS). > > + * Normally the sched_mode will be set to ODP_TM_BYTE_BASED_WEIGHTS, > > otherwise > > + * the scheduler becomes a weighted round robin scheduler. > > + */ > > +typedef enum { > > + ODP_TM_BYTE_BASED_WEIGHTS, /**< Use the packet length in > > + scheduler algorithm */ > > + ODP_TM_FRAME_BASED_WEIGHTS /**< Ignore the packet length */ > > +} odp_tm_sched_mode_t; > > + > > +/** The odp_tm_sched_params_t record type is used to supply the > parameters > > + * associated with a scheduler profile. Since it is expected that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that odp_tm_sched_params_init() be > > + * called on variables of this type before any of the fields are filled > > in. > > + */ > > +typedef struct { > > + /** sched_modes indicates whether weighted scheduling should be > > used > > + * or not - on a priority basis. > > + */ > > + odp_tm_sched_mode_t sched_modes[ODP_TM_MAX_PRIORITIES]; > > + > > + /** In the case that sched_modes for a given strict priority > level > > + * indicates the use of weighted scheduling, this field supplies the > > + * weighting factors. The weights - when defined - are used such > that > > + * the (adjusted) frame lengths are divided by these 8-bit weights > > + * (i.e. they are divisors and not multipliers). Consequently a > > + * weight of 0 (when sched_mode is ODP_TM_BYTE_BASED_WEIGHTS) is > > + * illegal. > > + */ > > + uint8_t sched_weights[ODP_TM_MAX_PRIORITIES]; > > +} odp_tm_sched_params_t; > > + > > +/** odp_tm_sched_params_init() must be called to initialize any > > + * odp_tm_sched_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_sched_params_t record which > > + * is to be initialized. > > + */ > > +void odp_tm_sched_params_init(odp_tm_sched_params_t *params); > > + > > +/** odp_tm_sched_create() creates a scheduler profile object, which can > > + * subsequently be attached to any number (including zero) of tm_nodes. > > + * > > + * @param[in] name Optional name associated with this scheduler > > profile. > > + * Can be NULL. If non-NULL must be unique amongst > the > > + * set of all other scheduler profiles. > > + * @param[in] params The profile parameters. See comments associated > > with > > + * the odp_tm_sched_params_t for more details. > > + * @return Returns ODP_TM_INVALID upon failure, or the newly > > + * allocated odp_tm_sched_t value representing this > > profile > > + * object. > > + */ > > +odp_tm_sched_t odp_tm_sched_create(const char *name, > > + odp_tm_sched_params_t *params); > > + > > +/** odp_tm_sched_params_read() "gets" the current set of values > associated > > + * with the specified scheduler profile object, and copies them into the > > + * supplied record. > > + * > > + * @param[in] sched_profile Specifies the scheduler profile whose > values > > + * are to be read. > > + * @param[out] params A pointer to an odp_tm_sched_params_t > record > > + * where the current scheduler profile object > > + * values are copied to. > > + * @return Returns < 0 upon failure or 0 upon > success. > > + */ > > +int odp_tm_sched_params_read(odp_tm_sched_t sched_profile, > > + odp_tm_sched_params_t *params); > > + > > +/** odp_tm_sched_params_update() "sets" the current set of values > > associated > > + * with the specified scheduler profile object. In addition, this call > > has > > + * the effect that all tm_nodes that are associated (attached?) with > this > > + * Scheduler profile object will be updated with the new values. > > + * > > + * @param[in] sched_profile Specifies the Scheduler profile object > whose > > + * values are to be set. > > + * @param[in] params A pointer to an odp_tm_sched_params_t > record > > + * where the new scheduler profile object > > values > > + * are taken from. > > + * @return Returns < 0 upon failure or 0 upon > success. > > + */ > > +int odp_tm_sched_params_update(odp_tm_sched_t sched_profile, > > + odp_tm_sched_params_t *params); > > + > > +/** odp_tm_sched_lookup() can be used to find the scheduler profile > object > > + * created with the specified name. > > + * > > + * @param[in] name Name of a previously created scheduler profile. > > Cannot be > > + * NULL. > > + * @return Returns ODP_TM_INVALID upon failure, or the > scheduler > > + * profile handle created with this name. > > + */ > > +odp_tm_sched_t odp_tm_sched_lookup(const char *name); > > + > > +/** Queue Threshold Profiles - types and functions */ > > + > > +/** The odp_tm_threshold_params_t record type is used to supply the > > parameters > > + * associated with a queue thresholds profile. Since it is expected > that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that > odp_tm_threshold_params_init() > > be > > + * called on variables of this type before any of the fields are filled > in > > + */ > > +typedef struct { > > + uint64_t max_pkts; /**< max pkt cnt for this threshold profile */ > > + uint64_t max_bytes; /**< max byte cnt for this threshold profile > */ > > + odp_bool_t enable_max_pkts; /**< TRUE if max_pkts is valid */ > > + odp_bool_t enable_max_bytes; /**< TRUE if max_bytes is valid */ > > +} odp_tm_threshold_params_t; > > + > > +/** odp_tm_threshold_params_init() must be called to initialize any > > + * odp_tm_threshold_params_t record before it is first used or assigned > > to. > > + * > > + * @param[in] params A pointer to an odp_tm_threshold_params_t record > > which > > + * is to be initialized. > > + */ > > +void odp_tm_threshold_params_init(odp_tm_threshold_params_t *params); > > + > > +/** odp_tm_threshold_create() creates a queue threshold profile object, > > which > > + * can subsequently be attached to any number (including zero) of > > tm_queues or > > + * tm_nodes. > > + * > > + * @param[in] name Optional name associated with this queue threshold > > + * profile. Can be NULL. If non-NULL must be unique > > + * amongst the set of all other queue threshold > > profiles. > > + * @param[in] params The profile parameters. See comments associated > > with > > + * the odp_tm_threshold_params_t for more details. > > + * @return Returns ODP_TM_INVALID upon failure, or the newly > > + * allocated odp_tm_threshold_t value representing > this > > + * profile object. > > + */ > > +odp_tm_threshold_t odp_tm_threshold_create(const char *name, > > + odp_tm_threshold_params_t > *params); > > + > > +/** odp_tm_thresholds_params_read() "gets" the current set of values > > associated > > + * with the specified queue thresholds profile object, and copies them > > into the > > + * supplied record. > > + * > > + * @param[in] threshold_profile Specifies the queue thresholds profile > > + * object whose values are to be read. > > + * @param[out] params A pointer to an > > odp_tm_threshold_params_t > > + * record where the current queue > > thresholds > > + * profile object values are copied to. > > + * @return Returns < 0 upon failure or 0 upon > > success. > > + */ > > +int odp_tm_thresholds_params_read(odp_tm_threshold_t threshold_profile, > > + odp_tm_threshold_params_t *params); > > + > > +/** odp_tm_thresholds_params_update() "sets" the current set of values > > + * associated with the specified queue thresholds profile object. In > > addition, > > + * this call has the effect that all tm_input's and tm_nodes that are > > + * associated (attached?) with this queue thresholds profile object will > > be > > + * updated with the new values. > > + * > > + * @param[in] threshold_profile Specifies the queue thresholds profile > > + * object whose values are to be set. > > + * @param[in] params A pointer to an > odp_tm_threshold_params_t > > + * record where the current queue > thresholds > > + * profile object values are taken from. > > + * @return Returns < 0 upon failure or 0 upon > > success. > > + */ > > +int odp_tm_thresholds_params_update(odp_tm_threshold_t > threshold_profile, > > + odp_tm_threshold_params_t *params); > > + > > +/** odp_tm_thresholds_lookup() can be used to find the queue thresholds > > + * profile object created with the specified name. > > + * > > + * @param[in] name Name of a previously created queue thresholds > profile. > > + * Cannot be NULL. > > + * @return Returns ODP_TM_INVALID upon failure, or the queue > > + * thresholds profile handle created with this name. > > + */ > > +odp_tm_threshold_t odp_tm_thresholds_lookup(const char *name); > > + > > +/** WRED Profiles - types and functions */ > > + > > +/** The odp_tm_wred_params_t record type is used to supply the > parameters > > + * associated with a Random Early Discard profile. Since it is expected > > that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that odp_tm_wred_params_init() be > > called > > + * on variables of this type before any of the fields are filled in. > > + */ > > +typedef struct { > > + /** When min_threshold is set to zero then single-slope WRED is > > + * enabled, as described in the description of med_threshold. > > + * Otherwise dual-slope WRED is enabled whereby the behavior depends > > + * on which of the following three cases exists: > > + * <ol> <li> queue > > + * fullness < min_threshold. In this case the drop probability is > > + * zero. > > + * <li> min_threshold <= queue fullness < med_threshold. In > > + * this case the drop probability increases linearly from zero until > > + * it reaches med_drop_prob at a queue fullness equal to > > + * med_threshold. > > + * <li> med_threshold <= queue fullness. In this case > > + * the drop probability increases linearly from med_drop_prob when > the > > + * queue fullness equals med_threshold until it reaches 100% with a > > + * drop probability of max_drop_prob. </ol> > > + */ > > + odp_tm_percent_t min_threshold; > > + > > + /** The meaning of med_threshold depends upon whether > single-slope > > or > > + * dual-slope WRED is being used or not. When min_threshold is 0 > then > > + * single-slope WRED is enabled in which case the med_threshold > value > > + * represents (as a percentage of max queue fullness) the point at > > + * which the drop probability starts increasing linearly from 0 > until > > + * it becomes equal to max_drop_prob when the queue fullness reaches > > + * 100%. See min_threshold comments for the case of dual-slope > WRED. > > + */ > > + odp_tm_percent_t med_threshold; > > + > > + /** The med_drop_prob is only used when dual-slope WRED is being > > used, > > + * in which case med_drop_prob MUST be < max_drop_prob. See > > + * min_threshold comments for more details. > > + */ > > + odp_tm_percent_t med_drop_prob; > > + > > + /** The max_drop_prob equals the drop probability when the queue > > + * fullness almost equals 100%. Of course once the queue fullness > is > > + * >= 100% of the max queue fullness, the drop probability > > + * discontinuously becomes 100%. > > + */ > > + odp_tm_percent_t max_drop_prob; > > + > > + /** When enable_wred is false, all tm_queues and tm_nodes that > are > > + * attached to this profile will not take part in a Random Early > > + * Discard algorithm. > > + */ > > + odp_bool_t enable_wred; > > + > > + /** When use_byte_fullness is true then WRED will use queue > memory > > + * usage as the fullness criterion, otherwise when use_byte_fullness > > + * is false, WRED will use the queue length (i.e. the number of > > + * packets in the queue) as the fullness criterion. Often will be > set > > + * to true for WRED profiles applied to tm_queues and set to false > for > > + * WRED profiles applied to tm_nodes. > > + */ > > + odp_bool_t use_byte_fullness; > > +} odp_tm_wred_params_t; > > + > > +/** odp_tm_wred_params_init() must be called to initialize any > > + * odp_tm_wred_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_wred_params_t record which > > + * is to be initialized. > > + */ > > +void odp_tm_wred_params_init(odp_tm_wred_params_t *params); > > + > > +/** odp_tm_wred_create() creates a WRED (Weighted Random Early Discard) > > + * profile object, which can subsequently be attached to any number > > (including > > + * zero) of tm_queues or tm_nodes. > > + * > > + * @param[in] name Optional name associated with this WRED profile. > > Can > > + * be NULL. If non-NULL must be unique amongst the > set > > of > > + * all other WRED profiles. > > + * @param[in] params The profile parameters. See comments associated > > with the > > + * odp_tm_wred_params_t for more details. > > + * @return Returns ODP_TM_INVALID upon failure, or the newly > > + * allocated odp_tm_wred_t value representing this > > profile > > + * object. > > + */ > > +odp_tm_wred_t odp_tm_wred_create(const char *name, > > + odp_tm_wred_params_t *params); > > + > > +/** odp_tm_wred_params_read() "gets" the current set of values > associated > > + * with the specified WRED profile object, and copies them into the > > supplied > > + * record. > > + * > > + * @param[in] wred_profile Specifies the WRED profile object whose > > + * values are to be read. > > + * @param[out] params A pointer to an odp_tm_wred_params_t record > > + * where the current WRED profile object > values > > + * are copied to. > > + * @return Returns < 0 upon failure or 0 upon success. > > + */ > > +int odp_tm_wred_params_read(odp_tm_wred_t wred_profile, > > + odp_tm_wred_params_t *params); > > + > > +/** odp_tm_wred_params_update() "sets" the current set of values > > associated > > + * with the specified WRED profile object. In addition, this call has > the > > + * effect that all tm_input's and tm_nodes that are associated > (attached?) > > + * with this WRED profile object will be updated with the new values. > > + * > > + * @param[in] wred_profile Specifies the WRED profile object whose > > + * values are to be set. > > + * @param[in] params A pointer to an odp_tm_wred_params_t record > > + * where the new WRED profile object values > > + * are taken from. > > + * @return Returns < 0 upon failure or 0 upon success. > > + */ > > +int odp_tm_wred_params_update(odp_tm_wred_t wred_profile, > > + odp_tm_wred_params_t *params); > > + > > +/** odp_tm_wred_lookup() can be used to find the WRED profile object > > created > > + * with the specified name. > > + * > > + * @param[in] name Name of a previously created WRED profile. Cannot > be > > + * NULL. > > + * @return Returns ODP_TM_INVALID upon failure, or the WRED > > + * profile handle created with this name. > > + */ > > +odp_tm_wred_t odp_tm_wred_lookup(const char *name); > > + > > +/** The odp_tm_node_params_t record type is used to hold extra > parameters > > when > > + * calling the odp_tm_node_create() function. Many of these fields are > > + * optional EXCEPT for max_fanin and level. Also since it is expected > > that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that odp_tm_node_params_init() be > > called > > + * on variables of this type before any of the fields are filled in. > > + */ > > +typedef struct { > > + /** The max_fan_in sets tha maximum number of src tm_queues and > > + * producer tm_nodes that can be simultaneously be connected to this > > + * tm_node as their destination. > > + */ > > + uint32_t max_fanin; > > + > > + /**> @todo uint8_t num_priorities; ? */ > > + > > + /** The shaper profile to be associated with this tm_node. Can > be > > + * ODP_TM_INVALID and can also be set and changed post-creation via > > + * odp_tm_node_shaper_config(); > > + */ > > + odp_tm_shaper_t shaper_profile; > > + > > + /** The threshold profile to be used in setting the max queue > > fullness > > + * for WRED and/or tail drop? Can be ODP_TM_INVALID and can also be > > + * set and changed post-creation via odp_tm_node_threshold_config(). > > + */ > > + odp_tm_threshold_t threshold_profile; > > + > > + /** The WRED profile(s) to be associated with this tm_node. Any > or > > + * all array elements can be ODP_TM_INVALID and can also be set and > > + * changed post-creation via odp_tm_node_wred_config(). > > + */ > > + odp_tm_wred_t wred_profile[ODP_NUM_PACKET_COLORS]; > > + > > + /** The level (or tm_node stage) sets the level for this tm_node > It > > + * must be in range 0..max_levels-1. Note that the tm_node topology > > + * is constrained such that only tm_node outputs with numerically > > + * greater levels may be connected to the fan-in of tm_node's with > > + * numerically smaller levels. > > + */ > > + uint8_t level; > > +} odp_tm_node_params_t; > > + > > +/** odp_tm_node_params_init() must be called to initialize any > > + * odp_tm_node_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_node_params_t record which > > + * is to be initialized. > > + */ > > +void odp_tm_node_params_init(odp_tm_node_params_t *params); > > + > > +/** Create an tm_node with a specific set of implemented strict priority > > + * levels as given by the priorities array parameter. The set of > priority > > + * levels does not have to "contiguous", but the "priorities" values for > > all > > + * indexes > max_priority MUST be FALSE. Note that the set of > implemented > > + * strict priority levels for an tm_node cannot be changed after tm_node > > + * creation. The level parameter MUST be in the range 0..max_level - 1. > > + * > > + * @param[in] odp_tm Odp_tm is used to identify the TM system into > which > > this > > + * odp_tm_node object is created. > > + * @param[in] name Optional name that can be used later later to find > > this > > + * same odp_tm_node_t. Can be NULL, otherwise must > be > > + * unique across all odp_tm_node objects. > > + * @param[in] params A pointer to a record holding (an extensible) set > of > > + * properties/attributes of this tm_node. > > + * @return Returns ODP_TM_INVALID upon failure, otherwise > > returns > > + * a valid odp_tm_node_t handleif successful. > > + */ > > +odp_tm_node_t odp_tm_node_create(odp_tm_t odp_tm, const char *name, > > + odp_tm_node_params_t *params); > > + > > +/** The odp_tm_node_shaper_config() function is used to dynamically set > or > > + * change the shaper profile associated with this tm_node. > > + * > > + * @param[in] tm_node Specifies the tm_node to be changed. > > + * @param[in] shaper_profile Specifies the shaper profile that should > > + * now be used for the shaper entity within > the > > + * given tm_node. Note that it is legal to > > specify > > + * ODP_TM_INVALID indicating that this > tm_node > > + * no longer implements a shaper function. > > + * @return Returns 0 upon success and < 0 upon > failure. > > + */ > > +int odp_tm_node_shaper_config(odp_tm_node_t tm_node, > > + odp_tm_shaper_t shaper_profile); > > + > > +/** The odp_tm_node_sched_config() function is used to dynamically set > or > > + * change the scheduler profile associated with a tm_node. > > + * > > + * @param[in] tm_node Specifies the tm_node to be changed. > > + * @param[in] tm_fan_in_node Specifies which of the specified tm_node's > > + * fan-in's weights etc are to be changed. > The > > + * fan-in is indentified by the > > "producer"/parent > > + * tm_node actually connected to this fan-in. > > + * @param[in] sched_profile Specifies the scheduler profile that > should > > + * now be used for the WFQ/RR entity within > the > > + * given tm_node. > > + * @return Returns 0 upon success and < 0 upon > failure. > > + */ > > +int odp_tm_node_sched_config(odp_tm_node_t tm_node, > > + odp_tm_node_t tm_fan_in_node, > > + odp_tm_sched_t sched_profile); > > + > > +/** The odp_tm_node_threshold_config() function is used to dynamically > set > > or > > + * change the queue threshold profile associated with this tm_node. > > + * > > + * @param[in] tm_node Specifies the tm_node to be changed. > > + * @param[in] thresholds_profile Specifies the queue threshold profile > > that > > + * should now be used for the given > > tm_node. > > + * @return Returns 0 upon success and < 0 upon > > failure. > > + */ > > +int odp_tm_node_threshold_config(odp_tm_node_t tm_node, > > + odp_tm_threshold_t thresholds_profile); > > + > > +/** The odp_tm_node_wred_config() function is used to dynamically set or > > + * change the WRED profile associated with this tm_node or > > tm_node/pkt_color > > + * combination. > > + * > > + * @param[in] tm_node Specifies the tm_node to be changed. > > + * @param[in] pkt_color Specifies the pkt_color that this profile is > > to be > > + * used with. Can also be the special value > > + * ALL_PKT_COLORS. > > + * @param[in] wred_profile Specifies the WRED profile that should now > be > > used > > + * by this tm_queue, when processing pkts of > this > > + * pkt_color. It can be the value > ODP_TM_INVALID > > + * indicating that this tm_queue/pkt_color > > combination > > + * no longer implements WRED. > > + * @return Returns 0 upon success and < 0 upon failure. > > + */ > > +int odp_tm_node_wred_config(odp_tm_node_t tm_node, > > + odp_packet_color_t pkt_color, > > + odp_tm_wred_t wred_profile); > > + > > +/** odp_tm_node_lookup() can be used to find the tm_node object created > > with > > + * the specified name. > > + * > > + * @param[in] odp_tm Odp_tm is used to identify the TM system into > which > > this > > + * odp_tm_node object is created. > > + * @param[in] name Name of a previously created tm_node. Cannot be > > + * NULL. > > + * @return Returns ODP_TM_INVALID upon failure, or the > tm_node > > + * handle created with this name. > > + */ > > +odp_tm_node_t odp_tm_node_lookup(odp_tm_t odp_tm, const char *name); > > + > > +/** The odp_tm_queue_params_t record type is used to hold extra > parameters > > + * when calling the odp_tm_queue_create() function. Many of these > fields > > are > > + * optional EXCEPT for priority. Also since it is expected that > > + * implementations might augment this record type with platform specific > > + * additional fields - it is required that odp_tm_queue_params_init() be > > + * called on variables of this type before any of the fields are filled > > in. > > + */ > > +typedef struct { > > + /** The shaper profile to be associated with this tm_queue. Can > be > > + * ODP_TM_INVALID and can also be set and changed post-creation via > > + * odp_tm_queue_shaper_config(); > > + */ > > + odp_tm_shaper_t shaper_profile; > > + > > + /** The threshold profile to be used in setting the max queue > > fullness > > + * for WRED and/or tail drop? Can be ODP_TM_INVALID and can also be > > + * set and changed post-creation via > odp_tm_queue_threshold_config(). > > + */ > > + odp_tm_threshold_t threshold_profile; > > + > > + /** The WRED profile(s) to be associated with this tm_queue. Any > > or > > + * all array elements can be ODP_TM_INVALID and can also be set and > > + * changed post-creation via odp_tm_queue_wred_config(). > > + */ > > + odp_tm_wred_t wred_profile[ODP_NUM_PACKET_COLORS]; > > + > > + /** The strict priority level assigned to packets in this > tm_queue > > - > > + * in other words all packets associated with a given tm_queue MUST > > + * have the same single strict priority level and this level must be > > + * in the range 0..max_priority. > > + */ > > + uint8_t priority; > > +} odp_tm_queue_params_t; > > + > > +/** odp_tm_queue_params_init() must be called to initialize any > > + * odp_tm_queue_params_t record before it is first used or assigned to. > > + * > > + * @param[in] params A pointer to an odp_tm_queue_params_t record which > > + * is to be initialized. > > + */ > > +void odp_tm_queue_params_init(odp_tm_queue_params_t *params); > > + > > +/** Create an tm_queue object. One can specify the maximum queue limits > > + * either as a maximum number of packets in the queue OR as a maximum > > number > > + * of bytes in the queue, or if both are specified, then whichever limit > > is > > + * hit first. Note that in the case of specifying the maximum queue > > memory > > + * size as bytes, the system is free to instead convert this byte value > > into a > > + * number of buffers and instead limit the queue memory usage by buffer > > counts > > + * versus strictly using byte counts. > > + * > > + * @param[in] odp_tm Odp_tm is used to identify the TM system into > which > > this > > + * odp_tm_queue object is created. > > + * @param[in] params A pointer to a record holding (an extensible) set > of > > + * properties/attributes of this tm_queue. > > + * @return Returns ODP_TM_INVALID upon failure, otherwise a > > valid > > + * odp_tm_queue_t handle. > > + */ > > +odp_tm_queue_t odp_tm_queue_create(odp_tm_t odp_tm, > > + odp_tm_queue_params_t *params); > > + > > +/** The odp_tm_queue_shaper_config() function is used to dynamically set > > + * or change the shaper profile associated with this tm_queue. > > + * > > + * @param[in] tm_queue Specifies the tm_queue to be changed. > > + * @param[in] shaper_profile Specifies the shaper profile that should > now > > be > > + * used for shaping the tm_queue's packet > > stream. > > + * Note that it is legal to specify > > ODP_TM_INVALID > > + * indicating that this tm_queue no longer > > + * implements a shaper function. > > + * @return Returns 0 upon success and < 0 upon > failure. > > + */ > > +int odp_tm_queue_shaper_config(odp_tm_queue_t tm_queue, > > + odp_tm_shaper_t shaper_profile); > > + > > +/** The odp_tm_queue_sched_config() function is used to dynamically set > or > > + * change the scheduler profile associated with a tm_node. Note that > > despite > > + * the name, this function affects a tm_node scheduler - specifically > the > > + * scheduler fan-in when such fan-in comes from an tm_queue. > > + * > > + * @param[in] tm_node Specifies the tm_node to be changed. > > + * @param[in] tm_fan_in_queue Specifies which of the specified tm_node's > > + * fan-in's weights etc are to be changed. > The > > + * fan-in is indentified by the > > "producer"/parent > > + * tm_queue actually connected to this > fan-in. > > + * @param[in] sched_profile Specifies the scheduler profile that > should > > + * now be used for the WFQ/RR entity within > the > > + * given tm_node. > > + * @return Returns 0 upon success and < 0 upon > failure. > > + */ > > +int odp_tm_queue_sched_config(odp_tm_node_t tm_node, > > + odp_tm_queue_t tm_fan_in_queue, > > + odp_tm_sched_t sched_profile); > > + > > +/** The odp_tm_queue_threshold_config() function is used to dynamically > > set or > > + * change the queue threshold profile associated with this tm_queue. > > + * > > + * @param[in] tm_queue Specifies the tm_queue to be changed. > > + * @param[in] thresholds_profile Specifies the queue threshold profile > > that > > + * should now be used for the given > > tm_queue. > > + * @return Returns 0 upon success and < 0 upon > > failure. > > + */ > > +int odp_tm_queue_threshold_config(odp_tm_queue_t tm_queue, > > + odp_tm_threshold_t thresholds_profile); > > + > > +/** odp_tm_queue_wred_config() function is used to dynamically set or > > change > > + * the WRED profile associated with this tm_queue or tm_queue/pkt_color > > + * combination. > > + * > > + * @param[in] tm_queue Specifies the tm_queue to be changed. > > + * @param[in] pkt_color Specifies the pkt_color that this profile is > > to be > > + * used with. Can also be the special value > > + * ALL_PKT_COLORS. > > + * @param[in] wred_profile Specifies the WRED profile that should now > be > > used > > + * by this tm_queue, when processing pkts of > this > > + * pkt_color. It can be the value > ODP_TM_INVALID > > + * indicating that this tm_queue/pkt_color > > combination > > + * no longer implements WRED. > > + * @return Returns 0 upon success and < 0 upon failure. > > + */ > > +int odp_tm_queue_wred_config(odp_tm_queue_t tm_queue, > > + odp_packet_color_t pkt_color, > > + odp_tm_wred_t wred_profile); > > + > > +/** Topology setting functions */ > > + > > +/** Connects the "output" of the src_tm_node to be a "producer" of the > > given > > + * dst_tm_node. Note that an ODP_TM_ROOT handle passed in for the > > + * dst_tm_node implies connection to the egress/root object of this TM > > system. > > + * > > + * @param[in] src_tm_node odp_tm_node_t handle of the tm_node whose > > output is > > + * to be connected to the fan-in of the next > > tm_node > > + * as represented by the dst_tm_node. > > + * @param[in] dst_tm_node odp_tm_node_t handle of the tm_node object > that > > will > > + * receive all of the pkt_descs from the src > > tm_node > > + * output. If ODP_TM_ROOT, then attachment is > to > > + * the root egress object/spigot. > > + * @return 0 upon success, < 0 on failure. > > + */ > > +int odp_tm_node_connect(odp_tm_node_t src_tm_node, odp_tm_node_t > > dst_tm_node); > > + > > +/** The odp_queue_connect() function connects the indicated tm_queue to > a > > + * parent tm_node or to the egress/root node. The tm_queue will then > > become > > + * one of the dst node's fan-in set. > > + * > > + * @param[in] tm_queue Specifies the tm_queue. > > + * @param[in] dst_tm_node odp_tm_node_t handle of the tm_node object > that > > will > > + * receive all of the pkt_descs from the src > > tm_node > > + * output. If ODP_TM_ROOT, then attachment is > to > > + * the root egress object/spigot. > > + * @return Returns 0 upon success and < 0 upon failure. > > + */ > > +int odp_tm_queue_connect(odp_tm_queue_t tm_queue, odp_tm_node_t > > dst_tm_node); > > + > > +/** Input API */ > > + > > +/** The odp_tm_enq() function is used to add packets to a given TM > system. > > + * Note that the System Metadata associated with the pkt needed by the > TM > > + * system is (a) a drop_eligible bit, (b) a two bit "pkt_color", (c) a > 16- > > bit > > + * pkt_len, and MAYBE? (d) a signed 8-bit shaper_len_adjust. > > + * > > + * If there is a non-zero shaper_len_adjust, then it is added to the > > pkt_len > > + * after any non-zero shaper_len_adjust that is part of the shaper > > profile. > > + * > > + * The pkt_color bits are a result of some earlier > > Metering/Marking/Policing > > + * processing (typically ingress based), and should not be confused with > > the > > + * shaper_color produced from the TM shaper entities within the > tm_inputs > > and > > + * tm_nodes. > > + * > > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the TM > > system). > > + * @param[in] pkt Handle to a packet. > > + * @return Returns 0 upon success, < 0 upon failure. One of > > the > > + * more common failure reasons is WRED dropage. > > + */ > > +int odp_tm_enq(odp_tm_queue_t tm_queue, odp_packet_t pkt); > > + > > +/** The odp_tm_enq_with_cnt() function behaves identically to > > odp_tm_enq(), > > + * except that it also returns (an approximation to?) the current > tm_queue > > + * packet queue count. > > + * > > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the TM > > system). > > + * @param[in] pkt Handle to a packet. > > + * @return Returns the number of packets previously > enqueued > > on > > + * this tm_queue upon success, < 0 upon failure. > > + */ > > +int odp_tm_enq_with_cnt(odp_tm_queue_t tm_queue, odp_packet_t pkt); > > + > > +/** Dynamic state query functions */ > > + > > +/** The following bit mask constants are used to refine the queue query > > + * functions defined below. > > + */ > > +#define ODP_TM_QUERY_PKT_CNT 0x01 /**< The total_pkt_cnt value */ > > +#define ODP_TM_QUERY_BYTE_CNT 0x02 /**< The total_byte_cnt value > */ > > +#define ODP_TM_QUERY_THRESHOLDS 0x04 /**< The thresholds??? */ > > + > > +/** The odp_tm_queue_info_t record type is used to return the various > > counts > > + * as requested by functions like odp_tm_queue_query() and > > + * odp_tm_total_query(). > > + */ > > +typedef struct { > > + /** The total_pkt_cnt field is the total number of packets > > currently > > + * stored/associated with the requested set of tm_queues. Note that > > + * because the packet queues are potentially being manipulated by > > + * multiple cpu's, the values here are only accurate when the tm > > + * system is "stopped" (i.e. the egress spigot is stopped and no > > + * odp_tm_enq calls are taking place). Implementations are free to > > + * batch update these counters - up to a dozen or so packets. > > + */ > > + uint64_t total_pkt_cnt; > > + > > + /** If the requested set of tm_queues has an odp_tm_threshold_t > > + * profile associated with it, then this is the max_pkt_cnt set in > the > > + * profile params. Returning this field is a convenience to the ODP > > + * programmer, enabling them to quickly see how the total_pkt_cnt > > + * compares to the maximum packet count threshold. Note that there > is > > + * no requirement that total_pkt_cnt be <= max_pkt_cnt. > > + */ > > + uint64_t max_pkt_cnt; > > + > > + /** The total_byte_cnt can either be the actual number of bytes > > used > > + * or an approximation of the number of bytes used based upon the > > + * number of fixed sized buffers used multiplied by the buffer size. > > + * In both cases the total_byte_cnt should correspond to the same > set > > + * of packets that were counted above. For instance, if the > > + * total_pkt_cnt is updated in a batch, then the total_byte_cnt > should > > + * also be updated in the same batch. The approx_byte_cnt field > below > > + * indicates whether the total_byte_cnt is buffer count based or > not. > > + * In the case that the number of bytes used by a packet is rounded > up > > + * to a 2, 4, 8, or 16 byte boundary, it is recommended that > > + * approx_byte_cnt be false. It is implementation dependent whether > > + * the byte count of a packet includes the CRC, but it is > recommended > > + * that it not include headroom, preamble or IPG. Of course when > the > > + * buffer counting method is used, it is expected that any headroom > in > > + * the first buffer is implicitly included. Finally in the case of > > + * variable length pkt based buffering, instead of taking the > > + * total_pkt_cnt and multiplying it by the maximum ethernet packet > > + * size, it is recommended that byte_cnt_valid be FALSE - even when > > + * query_flags includes ODP_TM_QUERY_BYTE_CNT. > > + */ > > + uint64_t total_byte_cnt; > > + > > + /** If the requested set of tm_queues has an odp_tm_threshold_t > > + * profile associated with it, then this is the max_byte_cnt set in > > + * the profile params. Returning this field is a convenience to the > > + * ODP programmer, enabling them to quickly see how the > total_byte_cnt > > + * compares to the maximum byte count threshold. Note that there is > > + * no requirement that total_byte_cnt be <= max_byte_cnt. > > + */ > > + uint64_t max_byte_cnt; > > + > > + /** The following boolean values indicate which of the counts > above > > + * are valid. Invalid count values must be 0. > > + */ > > + odp_bool_t total_pkt_cnt_valid; /**< TRUE if total_pkt_cnt is > valid > > */ > > + odp_bool_t max_pkt_cnt_valid; /**< TRUE if max_pkt_cnt is valid > */ > > + odp_bool_t total_byte_cnt_valid; /**< TRUE if total_byte_cnt is > valid > > */ > > + odp_bool_t max_byte_cnt_valid; /**< TRUE if max_byte_cnt is valid > > */ > > + > > + /** The approx_byte_cnt is TRUE if the total_byte_cnt field is > > valid > > + * AND if the buffer counting method is used. > > + */ > > + odp_bool_t approx_byte_cnt; > > +} odp_tm_queue_info_t; > > + > > +/** The odp_tm_queue_query() function can be used to check a single > > tm_queue's > > + * queue utilization. The query_flags indicate whether or not packet > > counts, > > + * byte counts or both are being requested. It is an error to request > > + * neither. The implementation may still return both sets of counts > > + * regardless of query_flags if the cost of returning all the counts is > > + * comparable to the cost of checking the query_flags. > > + * > > + * @param[in] tm_queue Specifies the tm_queue (and indirectly the > > + * TM system). > > + * @param[out] query_flags A set of flag bits indicating which counters > > are > > + * being requested to be returned in the info > > record. > > + * @param[out] info Pointer to an odp_tm_queue_info_t record > where > > the > > + * requested queue info is returned. > > + * @return Returns 0 upon success, < 0 upon failure. > > + */ > > +int odp_tm_queue_query(odp_tm_queue_t tm_queue, > > + uint32_t query_flags, > > + odp_tm_queue_info_t *info); > > + > > +/** The odp_tm_priority_query() function can be used to check the queue > > + * utilization of all tm_queue's with the given priority. The > query_flags > > + * indicate whether or not packet counts, byte counts or both are being > > + * requested. It is an error to request neither. The implementation > may > > + * still return both sets of counts regardless of query_flags if the > cost > > of > > + * returning all the counts is comparable to the cost of checking the > > + * query_flags. > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + * @param[in] priority Supplies the strict priority level used to > > specify > > + * which tm_queues are included in the info > > values. > > + * @param[out] query_flags A set of flag bits indicating which counters > > are > > + * being requested to be returned in the info > > record. > > + * @param[out] info Pointer to an odp_tm_queue_info_t record > where > > the > > + * requested queue info is returned. > > + * @return Returns 0 upon success, < 0 upon failure. > > + */ > > +int odp_tm_priority_query(odp_tm_t odp_tm, uint8_t priority, > > + uint32_t query_flags, odp_tm_queue_info_t *info); > > + > > +/** The odp_tm_total_query() function can be used to check the queue > > + * utilization of all tm_queue's in a single TM system. The query_flags > > + * indicate whether or not packet counts, byte counts or both are being > > + * requested. It is an error to request neither. The implementation > may > > + * still return both sets of counts regardless of query_flags if the > cost > > of > > + * returning all the counts is comparable to the cost of checking the > > + * query_flags. > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + * @param[out] query_flags A set of flag bits indicating which counters > > are > > + * being requested to be returned in the info > > record. > > + * @param[out] info Pointer to an odp_tm_queue_info_t record > where > > the > > + * requested queue info is returned. > > + * @return Returns 0 upon success, < 0 upon failure. > > + */ > > +int odp_tm_total_query(odp_tm_t odp_tm, uint32_t query_flags, > > + odp_tm_queue_info_t *info); > > + > > +/** The odp_tm_priority_threshold_config() function is only used to > > associate > > + * a maximum packet count and/or a maximum byte count with a strict > > priority > > + * level - for the benefit of the odp_tm_priority_query() function. It > > has no > > + * semantic effects other than returning these queue threshold values in > > the > > + * odp_tm_queue_info_t record. > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + * @param[in] priority Supplies the strict priority level > that > > + * the threshold profile params are > > associated > > + * with. > > + * @param[in] thresholds_profile Specifies the queue threshold profile > > that > > + * should now be associated with the > > supplied > > + * strict priority level. > > + * @return Returns 0 upon success and < 0 upon > > failure. > > + */ > > +int odp_tm_priority_threshold_config(odp_tm_t odp_tm, uint8_t priority, > > + odp_tm_threshold_t > thresholds_profile); > > + > > +/** The odp_tm_total_threshold_config() function is only used to > associate > > a > > + * maximum packet count and/or a maximum byte count with a TM system - > for > > the > > + * benefit of the odp_tm_total_query() function. It has no semantic > > effects > > + * other than returning these queue threshold values in the > > + * odp_tm_queue_info_t record. > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + * @param[in] thresholds_profile Specifies the queue threshold profile > > that > > + * should now be used for the entire TM > > + * system. > > + * @return Returns 0 upon success and < 0 upon > > failure. > > + */ > > +int odp_tm_total_threshold_config(odp_tm_t odp_tm, > > + odp_tm_threshold_t thresholds_profile); > > + > > +/** Misc functions */ > > + > > +/** The odp_tm_periodic_update function is a placeholder for any > external > > + * source of periodic events. In some cases the TM system may already > > have an > > + * internal built-in source of periodic events - in which case calling > > this > > + * function has no effect. > > + */ > > +void odp_tm_periodic_update(void); > > + > > +/** The odp_tm_is_idle function is used to determine if the specified > ODP > > + * traffic management system still has "work" to do (i.e. has at least > one > > + * non-empty tm_queue and perhaps some outstanding timers etc). This > > function > > + * can be used by test programs and ODP applications that wish to know > > when > > + * TM system has completed its work - presumably after they have stopped > > + * sending in new pkts. Note that this function should not be called > > often > > + * since for some implementations this call could take a fairly long > time > > + * to execute! > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + * @return Returns 1 if the TM system is idle and 0 > otherwise. > > + */ > > +odp_bool_t odp_tm_is_idle(odp_tm_t odp_tm); > > + > > +/** The odp_tm_stats_print function is used to write implementation- > > defined > > + * information about the specified TM system to the ODP log. The > intended > > use > > + * is for debugging. > > + * > > + * @param[in] odp_tm Specifies the TM system. > > + */ > > +void odp_tm_stats_print(odp_tm_t odp_tm); > > + > > +/** > > + * @} > > + */ > > + > > +#ifdef __cplusplus > > +} > > +#endif > > + > > +#endif > > diff --git a/platform/linux-generic/include/odp/plat/packet_types.h > > b/platform/linux-generic/include/odp/plat/packet_types.h > > index 45cb801..c3be633 100644 > > --- a/platform/linux-generic/include/odp/plat/packet_types.h > > +++ b/platform/linux-generic/include/odp/plat/packet_types.h > > @@ -36,6 +36,17 @@ typedef ODP_HANDLE_T(odp_packet_seg_t); > > > > #define ODP_PACKET_SEG_INVALID _odp_cast_scalar(odp_packet_seg_t, > > 0xffffffff) > > > > +/** odp_packet_color_t assigns names to the various pkt "colors" */ > > +typedef enum { > > + ODP_PACKET_GREEN = 0, > > + ODP_PACKET_YELLOW = 1, > > + ODP_PACKET_RED = 2, > > + ODP_PACKET_ALL_COLORS = 3, > > +} odp_packet_color_t; > > + > > +/** Sets the maximum number of pkt "colors" */ > > +#define ODP_NUM_PACKET_COLORS 3 > > + > > /** Get printable format of odp_packet_t */ > > static inline uint64_t odp_packet_to_u64(odp_packet_t hdl) > > { > > diff --git a/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > > b/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > > new file mode 100644 > > index 0000000..52df64b > > --- /dev/null > > +++ b/platform/linux-generic/include/odp/plat/traffic_mngr_types.h > > @@ -0,0 +1,185 @@ > > +/* Copyright (c) 2015, Linaro Limited > > + * All rights reserved. > > + * > > + * SPDX-License-Identifier: BSD-3-Clause > > + */ > > + > > +/** > > + * @file > > + * > > + * ODP traffic mngr > > + */ > > + > > +#ifndef ODP_TRAFFIC_MNGR_TYPES_H_ > > +#define ODP_TRAFFIC_MNGR_TYPES_H_ > > + > > +#ifdef __cplusplus > > +extern "C" { > > +#endif > > + > > +#include <odp/std_types.h> > > +#include <odp/plat/strong_types.h> > > + > > +/** @addtogroup odp_traffic_mngr > > + * Macros and operations on a TM system. > > + * @{ > > + */ > > + > > +/** The ODP_TM_MAX_NUM_SYSTEMS constant specifies the maximum number of > TM > > + * systems that may be created. On some platforms this might be much > more > > + * limited to as little as one hardware TM system. > > + */ > > +#define ODP_TM_MAX_NUM_SYSTEMS 64 > > + > > +/** The ODP_TM_MAX_PRIORITIES constant specifies the largest range of > > + * priorities that any TM system can support. All strict priority > values > > MUST > > + * in the range 0..ODP_TM_MAX_PRIORITIES-1. > > + */ > > +#define ODP_TM_MAX_PRIORITIES 16 > > + > > +/** The ODP_TM MAX_LEVELS constant specifies the largest range of > > + * tm_node levels that any TM system can support. Hence all tm_node > level > > + * values MUST be in the range 0..ODP_TM_MAX_LEVELS-1. Smaller tm_node > > + * levels are associated with tm_nodes closer to the TM system egress. > > + */ > > +#define ODP_TM_MAX_LEVELS 8 > > + > > +/** > > + * The smallest SCHED weight is 1 (i.e. 0 is not a legal WFQ/WRR value). > > + */ > > +#define ODP_TM_MIN_SCHED_WEIGHT 1 > > + > > +/** The ODP_TM_MAX_SCHED_WEIGHT constant is the largest weight any TM > > system > > + * can support (at least from a configuration standpoint). A given TM > > system > > + * could have a smaller value. > > + */ > > +#define ODP_TM_MAX_SCHED_WEIGHT 255 > > + > > +/** The ODP_TM_MAX_TM_QUEUES constant is the largest number of tm_queues > > + * that can handled by any one TM system. > > + */ > > +#define ODP_TM_MAX_TM_QUEUES (16 * 1024 * 1024) > > + > > +/** The ODP_TM_MAX_NUM_OUTPUTS constant is the largest number of outputs > > that > > + * can be configured for any one TM system. > > + */ > > +#define ODP_TM_MAX_NUM_OUTPUTS 256 > > + > > +/** The ODP_TM_MAX_NUM_TM_NODES constant is the largest number of > tm_nodes > > that > > + * can be in existence for any one TM system. > > + */ > > +#define ODP_TM_MAX_NUM_TM_NODES (1024 * 1024) > > + > > +/** The ODP_TM_MAX_TM_NODE_FANIN constant is the largest number of > fan-in > > + * "inputs" that can be simultaneously connected to a single tm_node. > > + * *TBD* Does this need to be as large as ODP_TM_MAX_TM_QUEUES? *TBD* > > + */ > > +#define ODP_TM_MAX_TM_NODE_FANIN (1024 * 1024) > > + > > +/** The ODP_TM_MIN_SHAPER_BW constant is the smallest amount of > bandwidth > > that > > + * can a shaper's peak or commit rate can be set to. It is in units of > > + * 1000 bytes/second so that it and the ODP_TM_MAX_SHAPER_BW can both > fit > > in > > + * 32 bits. > > + */ > > +#define ODP_TM_MIN_SHAPER_BW 1 > > + > > +/** The ODP_TM_MAX_SHAPER_BW constant is the largest amound of bandwidth > > that > > + * any shaper's peak or commit rate can be set to. It is in units of > > + * 1000 bytes/second so that it and the ODP_TM_MIN_SHAPER_BW can both > fit > > in > > + * 32 bits. > > + */ > > +#define ODP_TM_MAX_SHAPER_BW 12500000 > > + > > +/** The ODP_NUM_SHAPER_COLORS constant just counts the number of > > enumeration > > + * values defined in the odp_tm_shaper_color_t type. > > + */ > > +#define ODP_NUM_SHAPER_COLORS 3 > > + > > +/** The INVALID_PRIORITY constant is used when one needs to indicate an > > + * invalid priority value. > > + */ > > +#define ODP_TM_INVALID_PRIORITY 255 > > + > > +/** The odp_tm_percent_t type is used when specifying fields that are > > + * percentages. It is a fixed point integer whose units are 1/100 of a > > + * percent. Hence 100% is represented as the integer value 10000. Note > > + * that because it is often used as a ratio of the current queue value > and > > + * maximum queue threshold, it can be > 100%, but in any event will > never > > + * be larger than 500% (i.e. it MUST be capped at 50000). > > + */ > > +typedef uint16_t odp_tm_percent_t; > > + > > +/** The odp_tm_handle_t type is a generic type that can stand for any of > > the > > + * other ODP_TM handle types. > > + */ > > +typedef uint64_t odp_tm_handle_t; > > + > > +/** Each odp_tm_t value represents a specific TM system. Almost all > > + * functions in this API require a odp_tm_t value - either directly > > + * as a function parameter or indirectly by having another ODP TM handle > > value > > + * as a function parameter. > > + */ > > +typedef odp_tm_handle_t odp_tm_t; > > + > > +/** Each odp_tm_queue_t value is an opaque ODP handle representing a > > specific > > + * tm_queue within a specific TM system. > > + */ > > +typedef odp_tm_handle_t odp_tm_queue_t; > > + > > +/** Each odp_tm_node_t value is an opaque ODP handle representing a > > specific > > + * tm_node within a specific TM system. > > + */ > > +typedef odp_tm_handle_t odp_tm_node_t; > > + > > +/** Each odp_tm_shaper_t value is an opaque ODP handle representing a > > specific > > + * shaper profile usable across all TM systems described by this API. A > > given > > + * shaper profile can then be attached to any tm_queue or tm_node. > > + */ > > +typedef odp_tm_handle_t odp_tm_shaper_t; > > + > > +/** Each odp_tm_sched_t value is an opaque ODP handle representing a > > specific > > + * tm_node scheduler profile usable across all TM systems described by > > this > > + * API. A given tm_node scheduler profile can then be attached to any > > tm_node. > > + */ > > +typedef odp_tm_handle_t odp_tm_sched_t; > > + > > +/** Each odp_tm_threshold_t value is an opaque ODP handle representing a > > + * specific queue threshold profile usable across all TM systems > described > > by > > + * this API. A given queue threshold profile can then be attached to > any > > + * tm_queue or tm_node. > > + */ > > +typedef odp_tm_handle_t odp_tm_threshold_t; > > + > > +/** Each odp_tm_wred_t value is an opaque ODP handle representing a > > specific > > + * WRED profile usable across all TM systems described by this API. A > > given > > + * WRED profile can then be attached to any tm_queue or tm_node. > > + */ > > +typedef odp_tm_handle_t odp_tm_wred_t; > > + > > +/** The ODP_TM_INVALID constant can be used with any ODP TM handle type > > and > > + * indicates that this value does NOT represent a valid TM object. > > + */ > > +#define ODP_TM_INVALID 0 > > + > > +/** > > + * @def ODP_TM_ROOT > > + * Constant that is used to refer to the egress/root node of the TM > > subsystem's > > + * tree/hierarchy of nodes. > > + */ > > +#define ODP_TM_ROOT 0 > > + > > +/** Get printable format of odp_queue_t */ > > +static inline uint64_t odp_tm_handle_to_u64(odp_tm_handle_t hdl) > > +{ > > + return hdl; > > +} > > + > > +/** > > + * @} > > + */ > > + > > +#ifdef __cplusplus > > +} > > +#endif > > + > > +#endif > > diff --git a/platform/linux-generic/include/odp/traffic_mngr.h > > b/platform/linux-generic/include/odp/traffic_mngr.h > > new file mode 100644 > > index 0000000..3aa6267 > > --- /dev/null > > +++ b/platform/linux-generic/include/odp/traffic_mngr.h > > @@ -0,0 +1,35 @@ > > +/* Copyright (c) 2015, Linaro Limited > > + * All rights reserved. > > + * > > + * SPDX-License-Identifier: BSD-3-Clause > > + */ > > + > > +/** > > + * @file > > + * > > + * ODP Traffic manager > > + */ > > + > > +#ifndef ODP_PLAT_TRAFFIC_MNGR_H_ > > +#define ODP_PLAT_TRAFFIC_MNGR_H_ > > + > > +#ifdef __cplusplus > > +extern "C" { > > +#endif > > + > > +/** @ingroup odp_traffic_mngr > > + * @{ > > + */ > > + > > +/** > > + * @} > > + */ > > + > > +#include <odp/plat/traffic_mngr_types.h> > > +#include <odp/api/traffic_mngr.h> > > + > > +#ifdef __cplusplus > > +} > > +#endif > > + > > +#endif > > diff --git a/platform/linux-generic/include/odp_packet_internal.h > > b/platform/linux-generic/include/odp_packet_internal.h > > index ba2cd7e..d3eaad0 100644 > > --- a/platform/linux-generic/include/odp_packet_internal.h > > +++ b/platform/linux-generic/include/odp_packet_internal.h > > @@ -61,6 +61,9 @@ typedef union { > > uint32_t tcpopt:1; /**< TCP options present */ > > uint32_t sctp:1; /**< SCTP */ > > uint32_t icmp:1; /**< ICMP */ > > + > > + uint32_t color:2; /**< Packet color for traffic mgmt */ > > + uint32_t nodrop:1; /**< Drop eligibility status */ > > }; > > } input_flags_t; > > > > @@ -102,6 +105,8 @@ typedef union { > > uint32_t l3_chksum:1; /**< L3 chksum override */ > > uint32_t l4_chksum_set:1; /**< L3 chksum bit is valid */ > > uint32_t l4_chksum:1; /**< L4 chksum override */ > > + > > + int8_t shaper_len_adj; /**< adjustment for traffic mgr > */ > > }; > > } output_flags_t; > > > > -- > > 2.1.4 > > > > > _______________________________________________ > > lng-odp mailing list > > lng-odp@lists.linaro.org > > https://lists.linaro.org/mailman/listinfo/lng-odp > > >
diff --git a/include/odp.h b/include/odp.h index 825c7e1..f6a6ea9 100644 --- a/include/odp.h +++ b/include/odp.h @@ -56,6 +56,7 @@ extern "C" { #include <odp/thrmask.h> #include <odp/spinlock_recursive.h> #include <odp/rwlock_recursive.h> +#include <odp/traffic_mngr.h> #ifdef __cplusplus } diff --git a/include/odp/api/packet.h b/include/odp/api/packet.h index 5d46b7b..0680b3f 100644 --- a/include/odp/api/packet.h +++ b/include/odp/api/packet.h @@ -48,6 +48,26 @@ extern "C" { * Invalid packet segment */ + /** + * @typedef odp_packet_color_t + * Color of packet for shaper/drop processing + */ + + /** + * @def ODP_PACKET_GREEN + * Packet is green + */ + + /** + * @def ODP_PACKET_YELLOW + * Packet is yellow + */ + + /** + * @def ODP_PACKET_RED + * Packet is red + */ + /* * * Alloc and free @@ -700,6 +720,55 @@ odp_packet_seg_t odp_packet_last_seg(odp_packet_t pkt); */ odp_packet_seg_t odp_packet_next_seg(odp_packet_t pkt, odp_packet_seg_t seg); +/** + * Get packet color + * + * @param pkt Packet handle + * @return packet color + */ +odp_packet_color_t odp_packet_color(odp_packet_t pkt); + +/** + * Set packet color + * + * @param pkt Packet handle + * @param color Color to set + */ +void odp_packet_color_set(odp_packet_t pkt, odp_packet_color_t color); + +/** + * Get drop eligible status + * + * @param pkt Packet handle + * @return Packet drop eligibility status + * @retval 0 Packet is not drop eligible + * @retval 1 Packet is drop + */ +odp_bool_t odp_packet_drop_eligible(odp_packet_t pkt); + +/** + * Set drop eligible status + * + * @param pkt Packet handle + * @param status Drop eligibility status + */ +void odp_packet_drop_eligible_set(odp_packet_t pkt, odp_bool_t status); + +/** + * Get shaper length adjustment + * + * @param pkt Packet handle + * @return Shaper adjustment (-128..127) + */ +int8_t odp_packet_shaper_len_adjust(odp_packet_t pkt); + +/** + * Set shaper length adjustment + * + * @param pkt Packet handle + * @param adj Signed adjustment value + */ +void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, int8_t adj); /* * diff --git a/include/odp/api/traffic_mngr.h b/include/odp/api/traffic_mngr.h new file mode 100644 index 0000000..2459a8b --- /dev/null +++ b/include/odp/api/traffic_mngr.h @@ -0,0 +1,1611 @@ +/** Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_TRAFFIC_MNGR_H_ +#define ODP_TRAFFIC_MNGR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <odp/std_types.h> +#include <odp/packet_io.h> + +/** + * @file + * + */ + +/** @defgroup odp_traffic_mngr ODP TRAFFIC MNGR + * @{ + * + * An API for configuring and using Traffic Management systems + * + * This file forms a simple interface for creating, configuring and using + * Traffic Management (TM) subsystems. By TM subsystem it is meant a general + * packet scheduling system that accepts packets from input queues and applies + * strict priority scheduling, weighted fair queueing scheduling and/or + * bandwidth controls to decide which input packet should be chosen as the + * next output packet and when this output packet can be sent onwards. + * + * A given platform supporting this TM API could support one or more pure + * hardware based packet scheduling systems, one or more pure software + * based systems or one or more hybrid systems - where because of + * hardware constraints some of the packet scheduling is done in hardware + * and some is done in software. In addition, there may also be additional + * API's beyond those described here for (a) controlling advanced capabilities + * supported by specific hardware, software or hybrid subsystems or (b) + * dealing with constraints and limitations of specific implementations. + * The intention here is to be the simplest API that covers the vast majority + * of packet scheduling requirements. + * + * Often a TM subsystem's output(s) will be directly connected + * to a device's physical (or virtual) output interfaces/links, in which case + * sometimes such a system will be called an Egress Packet Scheduler or an + * Output Link Shaper, etc.. While the TM subsystems configured by this API + * can be used in such a way, this API equally well supports the ability to + * have the TM subsystem's outputs connect to other TM subsystem input queues + * or general software queues or even some combination of these three cases. + * + * <H2>TM Algorithms</H2> + * + * The packet scheduling/dropping techniques that can be applied to input + * traffic include any mixture of the following: + * <ol> + * <li> Strict Priority scheduling. + * <li> Weighted Fair Queueing scheduling (WFQ). + * <li> Bandwidth Shaping. + * <li> Weighted Random Early Discard (WRED). + * </ol> + * Note that Bandwidth Shaping is the only feature that can cause packets + * to be "delayed", and Weighted Random Early Discard is the only feature + * (other than input queues becoming full) that can cause packets to be + * dropped. + * + * <H3>Strict Priority Scheduling</H3> + * Strict Priority Scheduling (or just priority for short), is a technique + * where input queues and the packets from them, are assigned a priority + * value in the range 0 .. ODP_TM_MAX_PRIORITIES - 1. At all times packets + * the the smallest priority value will be chosen ahead of packets with a + * numerically larger priority value. This is called strict priority + * scheduling because the algorithm strictly enforces the scheduling of + * higher priority packets over lower priority packets. + * + * <H3>Bandwidth Shaping</H3> + * Bandwidth Shaping (or often just Shaping) is the term used here for the + * idea of controlling packet rates using single rate and/or dual rate token + * bucket algorithms. For single rate shaping a rate (the commit rate) and + * a "burst size" (the maximum commit count) are configured. Then an + * internal signed integer counter called the commitCnt is maintained such + * that if the commitCnt is positive then packets are eligible to be sent. + * When such a packet is actually sent then its commitCnt is decremented + * (usually by its length, but one could decrement by 1 for each packet + * instead). The commitCnt is then incremented periodically based upon the + * configured rate, so that this technique causes the traffic to be limited + * to the commit rate over the long term, while allowing some ability to + * exceed this rate for a very short time (based on the burst size) in order + * to catch up if the traffic input temporarily drops below the commit rate. + * + * Dual Rate Shaping is designed to allow certain traffic flows to fairly + * send more than their assigned commit rate when the scheduler has excess + * capacity. The idea being that it may be better to allow some types of + * traffic to send more than their committed bandwidth rather than letting + * the TM outputs be idle. The configuration of Dual Rate Shaping requires + * additionally a peak rate and a peak burst size. The peak rate must be + * greater than the related comls mit rate, but the burst sizes have no similar + * constraint. Also for every input priority that has Dual Rate shaping + * enabled, there needs to be an additional equal or lower priority (equal or + * higher numeric priority value) assigned. Then if the traffic exceeds its + * commit rate but not its peak rate, the "excess" traffic will be sent at the + * lower priority level - which by the strict priority algorithm should + * cause no degradation of the higher priority traffic, while allowing for + * less idle outputs. + * + * <H3>Weighted Fair Queuing</H3> + * Weighted Fair Queuing (WFQ) is used to arbitrate amongst multiple input + * packets with the same priority. Each input can be assigned a weight in the + * range MIN_WFQ_WEIGHT..MAX_WFQ_WEIGHT (nominally 1..255) that affects the way + * the algorithm chooses the next packet. If all of the weights are equal AND + * all of the input packets are the same length then the algorithm is + * equivalent to a round robin scheduling. If all of the weights are equal + * but the packets have different lengths then the WFQ algorithm will attempt + * to choose the packet such that inputs each get a fair share of the + * bandwidth - in other words it implements a weighted round robin algorithm + * where the weighting is based on frame length. + * + * When the input weights are not all equal and the input packet lengths vary + * then the WFQ algorithm will schedule packets such that the packet with + * the lowest "Virtual Finish Time" is chosen first. An input packet's + * Virtual Finish Time is roughly calculated based on the WFQ object's base + * Virtual Finish Time when the packet becomes the first packet in its queue + * plus its frame length divided by its weight. + * @code + * virtualFinishTime = wfqVirtualTimeBase + (pktLength / wfqWeight) + * @endcode + * In a system running at full capacity with no bandwidth limits - over the + * long term - each input fan-in's average transmit rate will be the same + * fraction of the output bandwidth as the fraction of its weight divided by + * the sum of all of the WFQ fan-in weights. Hence larger WFQ weights result + * in better "service" for a given fan-in. + * @code + * totalWfqWeight = 0; + * for (each fan-in entity - fanIn - feeding this WFQ scheduler) + * totalWfqWeight += fanIn->sfqWeight; + * + * fanIn->avgTransmitRate = avgOutputRate * fanIn->sfqWeight / totalWfqWeight; + * @endcode + * + * <H3>Weighted Random Early Discard</H3> + * The Weighted Random Early Discard (WRED) algorithm deals with the situation + * where an input packet rate exceeds some output rate (including + * the case where Bandwidth Shaping limits some output rates). Without WRED + * enabled and configured, the TM system will just implement a tail dropping + * scheme whereby whichever packet is unlucky enough to arrive when an TM + * input queue is full will be discarded regardless of priority or any other + * consideration. + * WRED allows one to configure the system to use a better/fairer algorithm + * than simple tail dropping. It works by measuring the "fullness" of + * various packet queues and converting this percentage into a probability + * of random packet dropping with the help of some configurable parameters. + * Then a random number is picked and together with the drop probability, + * a decision is made to accept the packet or drop it. + * A basic parameterization of WRED requires three parameters: + * <ol> + * <li> the maximum queue level (which could be either a maximum number of + * packets or a maximum amount of memory (i.e. bytes/buffers) used), + * <li> a starting threshold - which is a number in the range 0..100 + * representing a percentage of the maximum queue level at which the + * drop probability becomes non-zero, + * <li> a drop probability - which is a number in the range 0..100 + * representing a probability (0 means no drop and 100 means + * certain drop) - which is used when the queue is near 100% full. + * </ol> + * + * Note that all packet drops for a TM system only occur when a new packet + * arrives at a given TM system input queue. At that time either the WRED + * algorithm, if enabled for this input queue, or the "input queue full" + * tail drop algorithm will make a drop/no drop decision. After this point, + * any packets not dropped, will at some point be sent out a TM output - + * assuming that the topology is fully connected and enabled. + * + * <H2>Hierarchical Scheduling and tm_nodes</H2> + * This API supports the ability to do Hierarchical Scheduling whereby the + * final scheduling decision is controlled by equal priority schedulers, + * strict priority multiplexers, bandwidth shapers - at multiple levels - all + * forming a tree rooted at a single egress object. In other words, all + * tm_queues and tm_nodes have the property that their logical "output" feeds + * into one fan-in of a subsequent tm_node or egresss object - forming a proper + * tree. See the following link - + * <A HREF="diagram1.svg">Example Tm_node</A> - for an example. + * + * Multi-level/hierarchical scheduling adds both great control and significant + * complexity. Logically, despite the implication of the tm_node tree + * diagrams, there are no queues between the levels of hierarchy. Instead all + * packets are held in their input queue, until such time that the totality of + * all of the tm_nodes in the single path from input queue to output object + * agrees that this packet should be the next to be chosen to leave the TM + * system through the output object "portal". Hence what flows from level to + * level is the "local choice" of what packet/tm_queue should next be + * serviced. + * + * <H3>tm_nodes</H3> + * Tm_nodes are the main "entity"/object that a TM system is composed of. + * Each tm_node is a mini-TM subsystem of its own, but the interconnection + * and interplay of a multi-level "tree" of tm_nodes can allow the user + * to specify some very sophisticated behaviours. + * Each tm_node can contain a set of scheduler (one per strict priority level), + * a strict priority multiplexer, a bandwidth shaper and a WRED component - or + * a subset of these. + * + * In its full generality an tm_node consists of a set of "fan-in" connections + * to preceding tm_queues or tm_nodes. The fan-in for a single tm_node + * can range from 1 to many many thousands. This fan-in is divided first + * into a WFQ scheduler per priority level. So if 4 priority levels are + * implemented by this tm_node, there would be 4 WFQ schedulers - each with + * its own unique fan-in. After the WFQ schedulers a priority chooser comes + * next - where it will always choose the highest priority WFQ output + * available. The output of the priority chooser then feeds a bandwidth + * shaper function which then finally uses the shaper's propagation table + * to determine its output packet and its priority. This output could + * then be remapped via a priority map profile and then becomes one of the + * input fan-in to perhaps another level of tm_nodes, and so on. + * + * During this process it is important to remember that the bandwidth shaping + * function never causes packets to be dropped. Instead all packet drops + * occur because of tm_queue fullness or be running the WRED algorithm + * at the time a new packet attempts to be appended to the end of some + * input queue. + * + * The WRED profile associated with an tm_node considers the entire set of + * tm_queues feeding directly or indirectly into it as its measure of + * queue fullness. + * + * <H3>tm_queues</H3> + * tm_queues are the second major type of "entity"/object that a TM + * system is composed of. All packets MUST first enter the TM system via + * some tm_queue. Then logically, the head packets of all of the tm_queues + * are examined simultaneously by the entire TM system, and ONE tm_queue is + * chosen send its head packet out of the TM system's egress. Abstractly + * packets stay in the tm_queue until they are chosen at which time they are + * instantly transferred from tm_queue to/through the corresponding TM egress. + * It is also important to note that packets in the same tm_queue MUST always + * stay in order. In other words, the second packet in an tm_queue must never + * leave the TM system through a TM egress spigot before the first packet has + * left the system. So tm_queue packet order must always be maintained. + * + * <H3>TM egress</H3> + * Note that TM egress objects are NOT referred to as queues, because in + * many/most cases they don't have multi-packet structure but instead are + * viewed as a port/spigot through which the TM system schedules and finally + * transfers input packets through. + * + * <H2>Ideal versus Actual Behavior</H2> + * It is important to recognize the difference between the "abstract" + * mathematical model of the prescribed behavior and real implementations. + * The model describes the Ideal, but theoretically desired behavior, but such + * an Ideal is generally not practical to implement. Instead, one understands + * that virtually all Real TM systems attempt to approximate the Ideal behavior + * as given by the TM configuration as best as they can - while still + * attaining high packet processing performance. The idea is that instead of + * trying too hard to be "perfect" at the granularity of say microseconds, it + * may be better to instead try to match the long term Ideal behavior over a + * much more reasonable period of time like a millisecond. It is generally + * better to have a stable implementation that when averaged over a period of + * several milliseconds matches the Ideal behavior very closely than to have + * an implementation that is perhaps more accurate over a period of + * microseconds, but whose millisecond averaged behavior drifts away from the + * Ideal case. + * + * <H2>Other TM Concepts</H2> + * + * <H3>Profiles</H3> + * This specification often packages related TM system parameters into + * records/objects called profiles. These profiles can then be associated with + * various entities like tm_nodes and tm_queue's. This way the amount of + * storage associated with setting related parameters can be reduced and + * in addition it is common to re-use the same set of parameter set over + * and over again, and also to be able to change the parameter set once + * and have it affect lots of entities with which it is associated with/applied + * to. + * + * <H3>Absolute Limits versus odp_tm_capability_t</H3> + * This header file defines some constants representing the absolute maximum + * settings for any TM system, though in most cases a TM system can (and + * should) be created/instantiated with smaller values, since lower values + * will often result in faster operation and/or less memory used. + */ + +/** + * @def ODP_TM_MAX_NUM_SYSTEMS + * The maximum number of TM systems that may be created. On some platforms + * this might be much more limited to as little as one hardware TM system. + */ + +/** + * @def ODP_TM_MAX_PRIORITIES + * The largest range of priorities that any TM system can support. All strict + * priority values MUST in the range 0..ODP_TM_MAX_PRIORITIES-1. + */ + +/** + * @def ODP_TM_MAX_LEVELS + * The largest range of tm_node levels that any TM system can support. Hence + * all tm_node level values MUST be in the range 0..ODP_TM_MAX_LEVELS-1. + * Smaller tm_node levels are associated with tm_nodes closer to the TM system + * egress. + */ + +/** + * @def ODP_TM_MIN_SCHED_WEIGHT + * The smallest SCHED weight is 1 (i.e. 0 is not a legal WFQ/WRR value). + */ + +/** + * @def ODP_TM_MAX_SCHED_WEIGHT + * The largest weight any TM system can support (at least from a configuration + * standpoint). A given TM system could have a smaller value. + */ + +/** + * @def ODP_TM_MAX_TM_QUEUES + * The largest number of tm_queues that can handled by any one TM system. + */ + +/** + * @def ODP_TM_MAX_NUM_OUTPUTS + * The largest number of outputs that can be configured for any one TM system. + */ + +/** + * @def ODP_TM_MAX_NUM_TM_NODES + * The largest number of tm_nodes that can be in existence for any one TM + * system. + */ + +/** + * @def ODP_TM_MAX_TM_NODE_FANIN + * The largest number of fan-in "inputs" that can be simultaneously connected + * to a single tm_node. + * @todo Does this need to be as large as ODP_TM_MAX_TM_QUEUES? + */ + +/** + * @def ODP_TM_MIN_SHAPER_BW + * The largest amound of bandwidth that any shaper's peak or commit rate can + * be set to. It is in units of 1000 bytes/second. + */ + +/** + * @def ODP_TM_MAX_SHAPER_BW + * The largest amound of bandwidth that any shaper's peak or commit rate can + * be set to. It is in units of 1000 bytes/second. + */ + +/** + * @def ODP_NUM_SHAPER_COLORS + * The number of enumeration values defined in the odp_tm_shaper_color_t type. + */ + +/** + * @def ODP_TM_INVALID_PRIORITY + * Used to indicate an invalid priority value. + */ + +/** + * @typedef odp_tm_percent_t + * Is used when specifying fields that are percentages. It is a fixed point + * integer whose units are 1/100 of a percent. Hence 100% is represented as + * the integer value 10000. Note that because it is often used as a ratio of + * the current queue value and maximum queue threshold, it can be > 100%, but + * in any event will never be larger than 500% (i.e. it MUST be capped at + * 50000). + */ + +/** + * @typedef odp_tm_t + * Each odp_tm_t value represents a specific TM system. Almost all functions + * in this API require a odp_tm_t value - either directly as a function + * parameter or indirectly by having another ODP TM handle value as a function + * parameter. + */ + +/** + * @typedef odp_tm_queue_t + * Each odp_tm_queue_t value is an opaque ODP handle representing a specific + * tm_queue within a specific TM system. + */ + +/** + * @typedef odp_tm_node_t + * Each odp_tm_queue_t value is an opaque ODP handle representing a specific + * tm node within a specific TM system. + */ + +/** + * @typedef odp_tm_shaper_t + * Each odp_tm_shaper_t value is an opaque ODP handle representing a specific + * shaper profile usable across all TM systems described by this API. A given + * shaper profile can then be attached to any tm_queue or tm_node. + */ + +/** + * @typedef odp_tm_sched_t + * Each odp_tm_sched_t value is an opaque ODP handle representing a specific + * tm_node scheduler profile usable across all TM systems described by this + * API. A given tm_node scheduler profile can then be attached to any + * tm_node. + */ + +/** + * @typedef odp_tm_threshold_t + * Each odp_tm_threshold_t value is an opaque ODP handle representing a + * specific queue threshold profile usable across all TM systems described by + * this API. A given queue threshold profile can then be attached to any + * tm_queue or tm_node. + */ + +/** + * @typedef odp_tm_wred_t + * Each odp_tm_wred_t value is an opaque ODP handle representing a specific + * WRED profile usable across all TM systems described by this API. A given + * WRED profile can then be attached to any tm_queue or tm_node. + */ + +/** + * @def ODP_TM_INVALID + * Constant that can be used with any ODP TM handle type and indicates that + * this value does NOT represent a valid TM object. + */ + +/** + * @def ODP_TM_ROOT + * Constant that is used to refer to the egress/root node of the TM subsystem's + * tree/hierarchy of nodes. + */ + +/** The odp_tm_capability_t type is used to describe the feature set and limits + * of a TM system. It is passed to the odp_tm_create() function indirectly + * by being part of the odp_tm_params_t record. + */ +typedef struct { + /** max_tm_queues specifies the maximum number of tm_queues that can + * be in existence for this TM System. + */ + uint32_t max_tm_queues; + + /** max_fanin_per_level specifies the maximum number of fan_in link + * to any given scheduler (whether weighted or using fair queueing or + * round robin) belonging to tm_nodes at the given level. + */ + uint32_t max_fanin_per_level[ODP_TM_MAX_LEVELS]; + + /** max_priority specifies the maximum number of strict priority + * levels used by any tm_queue or tm_node. Note that any given + * tm_queue or tm_node can use a subset of these levels. max_priority + * must be in the range 0..ODP_TM_MAX_PRIORITIES - 1. Note that lower + * numeric values represent higher (more important or time critical) + * priorities. + */ + uint8_t max_priority; + + /** max_levels specifies that maximum number of levels of hierarchical + * scheduling allowed by this TM System. This is a count of the + * tm_node stages and does not include tm_queues or tm_egress objects. + * Hence any given tm_node will have associated tm_node_level in the + * range 0 to max_levels - 1, where tm_node's at level 0 output's only + * go to egress objects and tm_nodes whose level is max_levels - 1 + * have their fan_in only from tm_queues. + */ + uint8_t max_levels; + + /** tm_queue_shaper_supported indicates that the tm_queues support + * proper TM shaping. Note that TM Shaping is NOT the same thing as + * Ingress Metering/Policing as specified by RFC 2697 (A Single Rate + * Three Color Marker) or RFC 2698 (A Two Rate Three Color Marker). + * These RFC's can be used for a Diffserv traffic conditioner, or + * other ingress policing. They make no mention of and have no + * algorithms for delaying packets - which is what TM shapers are + * expected to do. + */ + odp_bool_t tm_queue_shaper_supported; + + /** tm_node_shaper_supported indicates that the tm_nodes (at least for + * some hierarchical levels) support proper T < M shaping. + */ + odp_bool_t tm_node_shaper_supported; + + /** red_supported indicates that the tm_queues support some form of + * Random Early Discard. + */ + odp_bool_t red_supported; + + /** hierarchical_red_supported indicates that this TM system supports + * some form of RED where the queue fullness of tm_nodes contributes + * to the overall RED DROP/NO-DROP decision. + */ + odp_bool_t hierarchical_red_supported; + + /** weights_supported indicates that the tm_node schedulers (at least + * for some hierarchical levels) can have their different weights for + * their fan-ins. + */ + odp_bool_t weights_supported; + + /** fair_queuing_supported indicates the the tm_node schedulers (at + * least for some hierarchical levels) can implement WFQ or FQ + * scheduling disciplines, otherwise these schedulers can only + * implement WRR or RR algorithms, + */ + odp_bool_t fair_queuing_supported; +} odp_tm_capability_t; + +/** The odp_tm_egress_fcn_t type defines the parameter profile of the egress + * function callback. Using an egress function callback is just one of several + * ways of getting packets out from an egress spigot. + * + */ +typedef void (*odp_tm_egress_fcn_t) (odp_packet_t odp_pkt); + +/** The tm_egress_kind_e enumeration type is used to indicate the kind of + * egress object ("spigot") associated with this TM system. Most of these + * kinds are optional - with ODP_TM_EGRESS_PKT_IO being the only mandatory + * kind. The TM_EGRESS_FN - if implemented - is useful for testing the TM + * subsystem, and users are warned that its performance might be limited. + */ +typedef enum { + ODP_TM_EGRESS_PKT_IO, + ODP_TM_EGRESS_FN, +} odp_tm_egress_kind_t; + +/** The odp_tm_egress_t type is used to describe that type of "egress spigot" + * associated with this TM system. It is passed to the odp_tm_create() + * function indirectly by being part of the odp_tm_params_t record. + */ +typedef struct { + odp_tm_egress_kind_t egress_kind; /**< Union discriminator */ + + union { + odp_pktio_t pktio; + odp_tm_egress_fcn_t egress_fcn; + }; +} odp_tm_egress_t; + +/** The odp_tm_params_t record type is used to hold extra parameters when + * calling the odp_tm_create() function. + * Since it is expected that implementations might augment this record type + * with platform specific additional fields - it is required that + * odp_tm_params_init() be called on variables of this type before any of the + * fields are filled in. + */ +typedef struct { + odp_tm_capability_t capability; /**< capability record */ + odp_tm_egress_t egress; /**< describes the egress "spigot" */ +} odp_tm_params_t; + +/** odp_tm_capability_init() must be called to initialize any + * odp_tm_capability_t record before it is first used or assigned to. + * + * @param[in] capability A pointer to an odp_tm_capability_t record which + * is to be initialized. + */ +void odp_tm_capability_init(odp_tm_capability_t *capability); + +/** odp_tm_params_init() must be called to initialize any + * odp_tm_params_t record before it is first used or assigned to. + * + * @param[in] params A pointer to an odp_tm_params_t record which + * is to be initialized. + */ +void odp_tm_params_init(odp_tm_params_t *params); + +/** Create/instantiate a TM Packet Scheduling system. + * + * @param[in] name The name to be assigned to this TM system. Cannot be + * NULL, and also must be unique amongst all other TM system + * names. + * @param[in] params The params to be used when creating this TM system. + * @return Returns ODP_TM_INVALID upon failure, otherwise the newly + * created TM system's odp_tm_t handle is returned. + */ +odp_tm_t odp_tm_create(const char *name, odp_tm_params_t *params); + +/** Find a pre-existing TM Packet Scheduling system. This function can be + * used either to find a TM system created previously with odp_tm_create OR + * get the odp_tm_t of a built-in TM system - usually based on HW. In this + * later case the format of the name used to refer to a specific built-in + * hardware TM system may be platform dependent, but in any case a name of + * "HW_TM_%u" where the number starts at 1, can be used to find a built-in + * system independently of the best capability match. If name is NULL then + * the existing (built-in or created by odp_tm_create) TM system that best + * matches capability is returned. + * + * @param[in] name If NULL then only uses the capability parameter to + * find a closest match, otherwise if the name is + * matched by an existing TM system it is returned. + * @param[in] capability Used when the name is NULL (in which + * case the closest match is returned) or when the + * name is not-NULL, but doesn't match + * any existing TM system in which case the + * capability is used to find the FIRST + * TM system matching exactly these limits. + * @return If an existing TM system (built-in or previously + * created via odp_tm_create) is found, its + * odp_tm_t value is returned, otherwise + * ODP_TM_INVALID is returned. + */ +odp_tm_t odp_tm_find(const char *name, odp_tm_capability_t *capability); + +/** odp_tm_capability() can be used to query the actual limits of a given TM + * system. This function can be used for both built-in TM systems AND TM + * system's created via odp_tm_create(). + * + * @param[in] odp_tm The odp_tm_t value of the TM system to be + * queried. + * @param[out] capability A pointer to a odp_tm_capability_t record + * where the actual limits used by the TM system are + * copied into. Note that these limits do NOT + * have to match the capability passed in if + * a TM system was created by odp_tm_create, + * but of course these limits in some cases could + * be larger. + * @return Returns 0 upon success, < 0 upon failure (which + * indicates that the odp_tm value did not + * exist). + */ +int odp_tm_capability(odp_tm_t odp_tm, odp_tm_capability_t *capability); + +/** odp_tm_destroy() may be used to destroy TM systems created via + * odp_tm_create(). It generally CANNOT be used to destroy built-in TM + * systems. Also some platforms MAY not support destroying of TM systems + * created via odp_tm_create() under certain conditions. For example a given + * platform may require that the TM system be first "drained" of all of its + * queued packets before it will accept a odp_tm_destroy() call. + * + * In general calling odp_tm_destroy() on an active TM system does not + * guarantee anything about the disposition of any packets queued within the + * TM system, other than EVENTUALLY these packets will be either sent (in ANY + * order) or freed. + * + * @param[in] odp_tm The odp_tm_t value of the TM system to be destroyed (and + * hence destroyed (and hence freed). + * @return 0 upon success, < 0 upon failure. + */ +int odp_tm_destroy(odp_tm_t odp_tm); + +/** Shaper profile types and functions */ + +/** Possible values of running the shaper algorithm. ODP_TM_SHAPER_GREEN + * means that the traffic is within the commit specification (rate and burst + * size), ODP_TM_SHAPER_YELLOW means that the traffic is within the peak + * specification (rate and burst size) and ODP_TM_SHAPER_RED means that the + * traffic is exceeding both its commit and peak specifications. Note that + * packets can also have an assigned <b> packet color</b> of ODP_PACKET_GREEN, + * ODP_PACKET_YELLOW or ODP_PACKET_RED which has a different meaning and + * purpose than the shaper colors. + */ +typedef enum { + ODP_TM_SHAPER_GREEN, ODP_TM_SHAPER_YELLOW, ODP_TM_SHAPER_RED +} odp_tm_shaper_color_t; + +/** The odp_tm_shaper_params_t record type is used to supply the parameters + * associated with a shaper profile. Since it is expected that + * implementations might augment this record type with platform specific + * additional fields - it is required that odp_tm_shaper_params_init() be + * called on variables of this type before any of the fields are filled in. + */ +typedef struct { + /** The committed information rate for this shaper profile. The units + * for this integer are always in bits per second. + */ + uint64_t commit_bps; + + /** The peak information rate for this shaper profile. The units for + * this integer are always in bits per second. + */ + uint64_t peak_bps; + + /** The commit burst tolerance for this shaper profile. The units for + * this field are always bits. This value sets an upper limit for the + * size of the commitCnt. + */ + uint32_t commit_burst; + + /** The peak burst tolerance for this shaper profile. The units for + * this field are always bits. This value sets an upper limit for the + * size of the peakCnt. + */ + uint32_t peak_burst; + + /** The shaper_len_adjust is a value between -128 and 127 which is + * directly added to the frame_len of a packet associated with this + * profile. The frame_len would normally include the outermost + * Ethernet header (DA, SA, ...) through to the outermost Ethernet CRC + * inclusive. Hence this field - when non-zero - will usually be set + * to a value approximating the "time" (in units of bytes) taken by + * the Ethernet preamble and Inter Frame Gap. Traditionally this + * would be the value 20 (8 + 12), but in same cases can be as low as + * 9 (4 + 5). + */ + int8_t shaper_len_adjust; + + /** If dual_rate is TRUE it indicates the desire for the + * implementation to use dual rate shaping for packets associated with + * this profile. The precise semantics of dual rate shaping are + * implementation specific, but in any case require a non-zero set of + * both commit and peak parameters. + */ + odp_bool_t dual_rate; +} odp_tm_shaper_params_t; + +/** odp_tm_shaper_params_init() must be called to initialize any + * odp_tm_shaper_params_t record before it is first used or assigned to. + * + * @param[in] params A pointer to an odp_tm_shaper_params_t record which + * is to be initialized. + */ +void odp_tm_shaper_params_init(odp_tm_shaper_params_t *params); + +/** odp_tm_shaper_create() creates a shaper profile object, which can + * subsequently be attached to any number (including zero) of tm_queues + * or tm_nodes. + * + * @param[in] name Optional name associated with this shaper profile. Can + * be NULL. If non-NULL must be unique amongst the set of + * all other shaper profiles. + * @param[in] params The profile parameters. See comments associated with + * the odp_tm_shaper_params_t for more details. + * @return Returns ODP_TM_INVALID upon failure, or the newly + * allocated odp_tm_shaper_t value representing this + * profile object. + */ +odp_tm_shaper_t odp_tm_shaper_create(const char *name, + odp_tm_shaper_params_t *params); + +/** odp_tm_shaper_params_read() "gets" the current set of values associated + * with the specified shaper profile object, and copies them into the supplied + * record. + * + * @param[in] shaper_profile Specifies the shaper profile object whose + * values are to be read. + * @param[out] params A pointer to an odp_tm_shaper_params_t record + * where the current shaper profile object values + * are copied to. + * @return Returns < 0 upon failure or 0 upon success. + */ +int odp_tm_shaper_params_read(odp_tm_shaper_t shaper_profile, + odp_tm_shaper_params_t *params); + +/** odp_tm_shaper_params_update() "sets" the current set of values associated + * with the specified shaper profile object. In addition, this call has the + * effect that all tm_input's and tm_nodes that are associated (attached?) + * with this shaper profile object will be updated with the new values. + * + * @param[in] shaper_profile Specifies the shaper profile object whose + * values are to be set. + * @param[in] params A pointer to an odp_tm_shaper_params_t record + * where the new shaper profile object values + * are taken from. + * @return Returns < 0 upon failure or 0 upon success. + */ +int odp_tm_shaper_params_update(odp_tm_shaper_t shaper_profile, + odp_tm_shaper_params_t *params); + +/** odp_tm_shaper_lookup() can be used to find the shaper profile object + * created with the specified name. + * + * @param[in] name Name of a previously created shaper profile. Cannot be + * NULL. + * @return Returns ODP_TM_INVALID upon failure, or the shaper + * profile handle created with this name. + */ +odp_tm_shaper_t odp_tm_shaper_lookup(const char *name); + +/** Scheduler Profiles - types and functions */ + +/** The odp_tm_sched_mode_t type is used to control whether a tm_node + * scheduler takes into account packet lengths (by setting the sched_mode to + * ODP_TM_BYTE_BASED_WEIGHTS) or instead treat packets with different lengths + * the same (by setting the sched_mode to ODP_TM_FRAME_BASED_WEIGHTS). + * Normally the sched_mode will be set to ODP_TM_BYTE_BASED_WEIGHTS, otherwise + * the scheduler becomes a weighted round robin scheduler. + */ +typedef enum { + ODP_TM_BYTE_BASED_WEIGHTS, /**< Use the packet length in + scheduler algorithm */ + ODP_TM_FRAME_BASED_WEIGHTS /**< Ignore the packet length */ +} odp_tm_sched_mode_t; + +/** The odp_tm_sched_params_t record type is used to supply the parameters + * associated with a scheduler profile. Since it is expected that + * implementations might augment this record type with platform specific + * additional fields - it is required that odp_tm_sched_params_init() be + * called on variables of this type before any of the fields are filled in. + */ +typedef struct { + /** sched_modes indicates whether weighted scheduling should be used + * or not - on a priority basis. + */ + odp_tm_sched_mode_t sched_modes[ODP_TM_MAX_PRIORITIES]; + + /** In the case that sched_modes for a given strict priority level + * indicates the use of weighted scheduling, this field supplies the + * weighting factors. The weights - when defined - are used such that + * the (adjusted) frame lengths are divided by these 8-bit weights + * (i.e. they are divisors and not multipliers). Consequently a + * weight of 0 (when sched_mode is ODP_TM_BYTE_BASED_WEIGHTS) is + * illegal. + */ + uint8_t sched_weights[ODP_TM_MAX_PRIORITIES]; +} odp_tm_sched_params_t; + +/** odp_tm_sched_params_init() must be called to initialize any + * odp_tm_sched_params_t record before it is first used or assigned to. + * + * @param[in] params A pointer to an odp_tm_sched_params_t record which + * is to be initialized. + */ +void odp_tm_sched_params_init(odp_tm_sched_params_t *params); + +/** odp_tm_sched_create() creates a scheduler profile object, which can + * subsequently be attached to any number (including zero) of tm_nodes. + * + * @param[in] name Optional name associated with this scheduler profile. + * Can be NULL. If non-NULL must be unique amongst the + * set of all other scheduler profiles. + * @param[in] params The profile parameters. See comments associated with + * the odp_tm_sched_params_t for more details. + * @return Returns ODP_TM_INVALID upon failure, or the newly + * allocated odp_tm_sched_t value representing this profile + * object. + */ +odp_tm_sched_t odp_tm_sched_create(const char *name, + odp_tm_sched_params_t *params); + +/** odp_tm_sched_params_read() "gets" the current set of values associated + * with the specified scheduler profile object, and copies them into the + * supplied record. + * + * @param[in] sched_profile Specifies the scheduler profile whose values + * are to be read. + * @param[out] params A pointer to an odp_tm_sched_params_t record + * where the current scheduler profile object + * values are copied to. + * @return Returns < 0 upon failure or 0 upon success. + */ +int odp_tm_sched_params_read(odp_tm_sched_t sched_profile, + odp_tm_sched_params_t *params); + +/** odp_tm_sched_params_update() "sets" the current set of values associated + * with the specified scheduler profile object. In addition, this call has + * the effect that all tm_nodes that are associated (attached?) with this + * Scheduler profile object will be updated with the new values. + * + * @param[in] sched_profile Specifies the Scheduler profile object whose + * values are to be set. + * @param[in] params A pointer to an odp_tm_sched_params_t record + * where the new scheduler profile object values + * are taken from. + * @return Returns < 0 upon failure or 0 upon success. + */ +int odp_tm_sched_params_update(odp_tm_sched_t sched_profile, + odp_tm_sched_params_t *params); + +/** odp_tm_sched_lookup() can be used to find the scheduler profile object + * created with the specified name. + * + * @param[in] name Name of a previously created scheduler profile. Cannot be + * NULL. + * @return Returns ODP_TM_INVALID upon failure, or the scheduler + * profile handle created with this name. + */ +odp_tm_sched_t odp_tm_sched_lookup(const char *name); + +/** Queue Threshold Profiles - types and functions */ + +/** The odp_tm_threshold_params_t record type is used to supply the parameters + * associated with a queue thresholds profile. Since it is expected that + * implementations might augment this record type with platform specific + * additional fields - it is required that odp_tm_threshold_params_init() be + * called on variables of this type before any of the fields are filled in + */ +typedef struct { + uint64_t max_pkts; /**< max pkt cnt for this threshold profile */ + uint64_t max_bytes; /**< max byte cnt for this threshold profile */ + odp_bool_t enable_max_pkts; /**< TRUE if max_pkts is valid */ + odp_bool_t enable_max_bytes; /**< TRUE if max_bytes is valid */ +} odp_tm_threshold_params_t; + +/** odp_tm_threshold_params_init() must be called to initialize any + * odp_tm_threshold_params_t record before it is first used or assigned to. + * + * @param[in] params A pointer to an odp_tm_threshold_params_t record which + * is to be initialized. + */ +void odp_tm_threshold_params_init(odp_tm_threshold_params_t *params); + +/** odp_tm_threshold_create() creates a queue threshold profile object, which + * can subsequently be attached to any number (including zero) of tm_queues or + * tm_nodes. + * + * @param[in] name Optional name associated with this queue threshold + * profile. Can be NULL. If non-NULL must be unique + * amongst the set of all other queue threshold profiles. + * @param[in] params The profile parameters. See comments associated with + * the odp_tm_threshold_params_t for more details. + * @return Returns ODP_TM_INVALID upon failure, or the newly + * allocated odp_tm_threshold_t value representing this + * profile object. + */ +odp_tm_threshold_t odp_tm_threshold_create(const char *name, + odp_tm_threshold_params_t *params); + +/** odp_tm_thresholds_params_read() "gets" the current set of values associated + * with the specified queue thresholds profile object, and copies them into the + * supplied record. + * + * @param[in] threshold_profile Specifies the queue thresholds profile + * object whose values are to be read. + * @param[out] params A pointer to an odp_tm_threshold_params_t + * record where the current queue thresholds + * profile object values are copied to. + * @return Returns < 0 upon failure or 0 upon success. + */ +int odp_tm_thresholds_params_read(odp_tm_threshold_t threshold_profile, + odp_tm_threshold_params_t *params); + +/** odp_tm_thresholds_params_update() "sets" the current set of values + * associated with the specified queue thresholds profile object. In addition, + * this call has the effect that all tm_input's and tm_nodes that are + * associated (attached?) with this queue thresholds profile object will be + * updated with the new values. + * + * @param[in] threshold_profile Specifies the queue thresholds profile + * object whose values are to be set. + * @param[in] params A pointer to an odp_tm_threshold_params_t + * record where the current queue thresholds + * profile object values are taken from. + * @return Returns < 0 upon failure or 0 upon success. + */ +int odp_tm_thresholds_params_update(odp_tm_threshold_t threshold_profile, + odp_tm_threshold_params_t *params); + +/** odp_tm_thresholds_lookup() can be used to find the queue thresholds + * profile object created with the specified name. + * + * @param[in] name Name of a previously created queue thresholds profile. + * Cannot be NULL. + * @return Returns ODP_TM_INVALID upon failure, or the queue + * thresholds profile handle created with this name. + */ +odp_tm_threshold_t odp_tm_thresholds_lookup(const char *name); + +/** WRED Profiles - types and functions */ + +/** The odp_tm_wred_params_t record type is used to supply the parameters + * associated with a Random Early Discard profile. Since it is expected that + * implementations might augment this record type with platform specific + * additional fields - it is required that odp_tm_wred_params_init() be called + * on variables of this type before any of the fields are filled in. + */ +typedef struct { + /** When min_threshold is set to zero then single-slope WRED is + * enabled, as described in the description of med_threshold. + * Otherwise dual-slope WRED is enabled whereby the behavior depends + * on which of the following three cases exists: + * <ol> <li> queue + * fullness < min_threshold. In this case the drop probability is + * zero. + * <li> min_threshold <= queue fullness < med_threshold. In + * this case the drop probability increases linearly from zero until + * it reaches med_drop_prob at a queue fullness equal to + * med_threshold. + * <li> med_threshold <= queue fullness. In this case + * the drop probability increases linearly from med_drop_prob when the + * queue fullness equals med_threshold until it reaches 100% with a + * drop probability of max_drop_prob. </ol> + */ + odp_tm_percent_t min_threshold; + + /** The meaning of med_threshold depends upon whether single-slope or + * dual-slope WRED is being used or not. When min_threshold is 0 then + * single-slope WRED is enabled in which case the med_threshold value + * represents (as a percentage of max queue fullness) the point at + * which the drop probability starts increasing linearly from 0 until + * it becomes equal to max_drop_prob when the queue fullness reaches + * 100%. See min_threshold comments for the case of dual-slope WRED. + */ + odp_tm_percent_t med_threshold; + + /** The med_drop_prob is only used when dual-slope WRED is being used, + * in which case med_drop_prob MUST be < max_drop_prob. See + * min_threshold comments for more details. + */ + odp_tm_percent_t med_drop_prob; + + /** The max_drop_prob equals the drop probability when the queue + * fullness almost equals 100%. Of course once the queue fullness is + * >= 100% of the max queue fullness, the drop probability + * discontinuously becomes 100%. + */ + odp_tm_percent_t max_drop_prob; + + /** When enable_wred is false, all tm_queues and tm_nodes that are + * attached to this profile will not take part in a Random Early + * Discard algorithm. + */ + odp_bool_t enable_wred; + + /** When use_byte_fullness is true then WRED will use queue memory + * usage as the fullness criterion, otherwise when use_byte_fullness + * is false, WRED will use the queue length (i.e. the number of + * packets in the queue) as the fullness criterion. Often will be set + * to true for WRED profiles applied to tm_queues and set to false for + * WRED profiles applied to tm_nodes. + */ + odp_bool_t use_byte_fullness; +} odp_tm_wred_params_t; + +/** odp_tm_wred_params_init() must be called to initialize any + * odp_tm_wred_params_t record before it is first used or assigned to. + * + * @param[in] params A pointer to an odp_tm_wred_params_t record which + * is to be initialized. + */ +void odp_tm_wred_params_init(odp_tm_wred_params_t *params); + +/** odp_tm_wred_create() creates a WRED (Weighted Random Early Discard) + * profile object, which can subsequently be attached to any number (including + * zero) of tm_queues or tm_nodes. + * + * @param[in] name Optional name associated with this WRED profile. Can + * be NULL. If non-NULL must be unique amongst the set of + * all other WRED profiles. + * @param[in] params The profile parameters. See comments associated with the + * odp_tm_wred_params_t for more details. + * @return Returns ODP_TM_INVALID upon failure, or the newly + * allocated odp_tm_wred_t value representing this profile + * object. + */ +odp_tm_wred_t odp_tm_wred_create(const char *name, + odp_tm_wred_params_t *params); + +/** odp_tm_wred_params_read() "gets" the current set of values associated + * with the specified WRED profile object, and copies them into the supplied + * record. + * + * @param[in] wred_profile Specifies the WRED profile object whose + * values are to be read. + * @param[out] params A pointer to an odp_tm_wred_params_t record + * where the current WRED profile object values + * are copied to. + * @return Returns < 0 upon failure or 0 upon success. + */ +int odp_tm_wred_params_read(odp_tm_wred_t wred_profile, + odp_tm_wred_params_t *params); + +/** odp_tm_wred_params_update() "sets" the current set of values associated + * with the specified WRED profile object. In addition, this call has the + * effect that all tm_input's and tm_nodes that are associated (attached?) + * with this WRED profile object will be updated with the new values. + * + * @param[in] wred_profile Specifies the WRED profile object whose + * values are to be set. + * @param[in] params A pointer to an odp_tm_wred_params_t record + * where the new WRED profile object values + * are taken from. + * @return Returns < 0 upon failure or 0 upon success. + */ +int odp_tm_wred_params_update(odp_tm_wred_t wred_profile, + odp_tm_wred_params_t *params); + +/** odp_tm_wred_lookup() can be used to find the WRED profile object created + * with the specified name. + * + * @param[in] name Name of a previously created WRED profile. Cannot be + * NULL. + * @return Returns ODP_TM_INVALID upon failure, or the WRED + * profile handle created with this name. + */ +odp_tm_wred_t odp_tm_wred_lookup(const char *name); + +/** The odp_tm_node_params_t record type is used to hold extra parameters when + * calling the odp_tm_node_create() function. Many of these fields are + * optional EXCEPT for max_fanin and level. Also since it is expected that + * implementations might augment this record type with platform specific + * additional fields - it is required that odp_tm_node_params_init() be called + * on variables of this type before any of the fields are filled in. + */ +typedef struct { + /** The max_fan_in sets tha maximum number of src tm_queues and + * producer tm_nodes that can be simultaneously be connected to this + * tm_node as their destination. + */ + uint32_t max_fanin; + + /**> @todo uint8_t num_priorities; ? */ + + /** The shaper profile to be associated with this tm_node. Can be + * ODP_TM_INVALID and can also be set and changed post-creation via + * odp_tm_node_shaper_config(); + */ + odp_tm_shaper_t shaper_profile; + + /** The threshold profile to be used in setting the max queue fullness + * for WRED and/or tail drop? Can be ODP_TM_INVALID and can also be + * set and changed post-creation via odp_tm_node_threshold_config(). + */ + odp_tm_threshold_t threshold_profile; + + /** The WRED profile(s) to be associated with this tm_node. Any or + * all array elements can be ODP_TM_INVALID and can also be set and + * changed post-creation via odp_tm_node_wred_config(). + */ + odp_tm_wred_t wred_profile[ODP_NUM_PACKET_COLORS]; + + /** The level (or tm_node stage) sets the level for this tm_node It + * must be in range 0..max_levels-1. Note that the tm_node topology + * is constrained such that only tm_node outputs with numerically + * greater levels may be connected to the fan-in of tm_node's with + * numerically smaller levels. + */ + uint8_t level; +} odp_tm_node_params_t; + +/** odp_tm_node_params_init() must be called to initialize any + * odp_tm_node_params_t record before it is first used or assigned to. + * + * @param[in] params A pointer to an odp_tm_node_params_t record which + * is to be initialized. + */ +void odp_tm_node_params_init(odp_tm_node_params_t *params); + +/** Create an tm_node with a specific set of implemented strict priority + * levels as given by the priorities array parameter. The set of priority + * levels does not have to "contiguous", but the "priorities" values for all + * indexes > max_priority MUST be FALSE. Note that the set of implemented + * strict priority levels for an tm_node cannot be changed after tm_node + * creation. The level parameter MUST be in the range 0..max_level - 1. + * + * @param[in] odp_tm Odp_tm is used to identify the TM system into which this + * odp_tm_node object is created. + * @param[in] name Optional name that can be used later later to find this + * same odp_tm_node_t. Can be NULL, otherwise must be + * unique across all odp_tm_node objects. + * @param[in] params A pointer to a record holding (an extensible) set of + * properties/attributes of this tm_node. + * @return Returns ODP_TM_INVALID upon failure, otherwise returns + * a valid odp_tm_node_t handleif successful. + */ +odp_tm_node_t odp_tm_node_create(odp_tm_t odp_tm, const char *name, + odp_tm_node_params_t *params); + +/** The odp_tm_node_shaper_config() function is used to dynamically set or + * change the shaper profile associated with this tm_node. + * + * @param[in] tm_node Specifies the tm_node to be changed. + * @param[in] shaper_profile Specifies the shaper profile that should + * now be used for the shaper entity within the + * given tm_node. Note that it is legal to specify + * ODP_TM_INVALID indicating that this tm_node + * no longer implements a shaper function. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_node_shaper_config(odp_tm_node_t tm_node, + odp_tm_shaper_t shaper_profile); + +/** The odp_tm_node_sched_config() function is used to dynamically set or + * change the scheduler profile associated with a tm_node. + * + * @param[in] tm_node Specifies the tm_node to be changed. + * @param[in] tm_fan_in_node Specifies which of the specified tm_node's + * fan-in's weights etc are to be changed. The + * fan-in is indentified by the "producer"/parent + * tm_node actually connected to this fan-in. + * @param[in] sched_profile Specifies the scheduler profile that should + * now be used for the WFQ/RR entity within the + * given tm_node. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_node_sched_config(odp_tm_node_t tm_node, + odp_tm_node_t tm_fan_in_node, + odp_tm_sched_t sched_profile); + +/** The odp_tm_node_threshold_config() function is used to dynamically set or + * change the queue threshold profile associated with this tm_node. + * + * @param[in] tm_node Specifies the tm_node to be changed. + * @param[in] thresholds_profile Specifies the queue threshold profile that + * should now be used for the given tm_node. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_node_threshold_config(odp_tm_node_t tm_node, + odp_tm_threshold_t thresholds_profile); + +/** The odp_tm_node_wred_config() function is used to dynamically set or + * change the WRED profile associated with this tm_node or tm_node/pkt_color + * combination. + * + * @param[in] tm_node Specifies the tm_node to be changed. + * @param[in] pkt_color Specifies the pkt_color that this profile is to be + * used with. Can also be the special value + * ALL_PKT_COLORS. + * @param[in] wred_profile Specifies the WRED profile that should now be used + * by this tm_queue, when processing pkts of this + * pkt_color. It can be the value ODP_TM_INVALID + * indicating that this tm_queue/pkt_color combination + * no longer implements WRED. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_node_wred_config(odp_tm_node_t tm_node, + odp_packet_color_t pkt_color, + odp_tm_wred_t wred_profile); + +/** odp_tm_node_lookup() can be used to find the tm_node object created with + * the specified name. + * + * @param[in] odp_tm Odp_tm is used to identify the TM system into which this + * odp_tm_node object is created. + * @param[in] name Name of a previously created tm_node. Cannot be + * NULL. + * @return Returns ODP_TM_INVALID upon failure, or the tm_node + * handle created with this name. + */ +odp_tm_node_t odp_tm_node_lookup(odp_tm_t odp_tm, const char *name); + +/** The odp_tm_queue_params_t record type is used to hold extra parameters + * when calling the odp_tm_queue_create() function. Many of these fields are + * optional EXCEPT for priority. Also since it is expected that + * implementations might augment this record type with platform specific + * additional fields - it is required that odp_tm_queue_params_init() be + * called on variables of this type before any of the fields are filled in. + */ +typedef struct { + /** The shaper profile to be associated with this tm_queue. Can be + * ODP_TM_INVALID and can also be set and changed post-creation via + * odp_tm_queue_shaper_config(); + */ + odp_tm_shaper_t shaper_profile; + + /** The threshold profile to be used in setting the max queue fullness + * for WRED and/or tail drop? Can be ODP_TM_INVALID and can also be + * set and changed post-creation via odp_tm_queue_threshold_config(). + */ + odp_tm_threshold_t threshold_profile; + + /** The WRED profile(s) to be associated with this tm_queue. Any or + * all array elements can be ODP_TM_INVALID and can also be set and + * changed post-creation via odp_tm_queue_wred_config(). + */ + odp_tm_wred_t wred_profile[ODP_NUM_PACKET_COLORS]; + + /** The strict priority level assigned to packets in this tm_queue - + * in other words all packets associated with a given tm_queue MUST + * have the same single strict priority level and this level must be + * in the range 0..max_priority. + */ + uint8_t priority; +} odp_tm_queue_params_t; + +/** odp_tm_queue_params_init() must be called to initialize any + * odp_tm_queue_params_t record before it is first used or assigned to. + * + * @param[in] params A pointer to an odp_tm_queue_params_t record which + * is to be initialized. + */ +void odp_tm_queue_params_init(odp_tm_queue_params_t *params); + +/** Create an tm_queue object. One can specify the maximum queue limits + * either as a maximum number of packets in the queue OR as a maximum number + * of bytes in the queue, or if both are specified, then whichever limit is + * hit first. Note that in the case of specifying the maximum queue memory + * size as bytes, the system is free to instead convert this byte value into a + * number of buffers and instead limit the queue memory usage by buffer counts + * versus strictly using byte counts. + * + * @param[in] odp_tm Odp_tm is used to identify the TM system into which this + * odp_tm_queue object is created. + * @param[in] params A pointer to a record holding (an extensible) set of + * properties/attributes of this tm_queue. + * @return Returns ODP_TM_INVALID upon failure, otherwise a valid + * odp_tm_queue_t handle. + */ +odp_tm_queue_t odp_tm_queue_create(odp_tm_t odp_tm, + odp_tm_queue_params_t *params); + +/** The odp_tm_queue_shaper_config() function is used to dynamically set + * or change the shaper profile associated with this tm_queue. + * + * @param[in] tm_queue Specifies the tm_queue to be changed. + * @param[in] shaper_profile Specifies the shaper profile that should now be + * used for shaping the tm_queue's packet stream. + * Note that it is legal to specify ODP_TM_INVALID + * indicating that this tm_queue no longer + * implements a shaper function. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_queue_shaper_config(odp_tm_queue_t tm_queue, + odp_tm_shaper_t shaper_profile); + +/** The odp_tm_queue_sched_config() function is used to dynamically set or + * change the scheduler profile associated with a tm_node. Note that despite + * the name, this function affects a tm_node scheduler - specifically the + * scheduler fan-in when such fan-in comes from an tm_queue. + * + * @param[in] tm_node Specifies the tm_node to be changed. + * @param[in] tm_fan_in_queue Specifies which of the specified tm_node's + * fan-in's weights etc are to be changed. The + * fan-in is indentified by the "producer"/parent + * tm_queue actually connected to this fan-in. + * @param[in] sched_profile Specifies the scheduler profile that should + * now be used for the WFQ/RR entity within the + * given tm_node. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_queue_sched_config(odp_tm_node_t tm_node, + odp_tm_queue_t tm_fan_in_queue, + odp_tm_sched_t sched_profile); + +/** The odp_tm_queue_threshold_config() function is used to dynamically set or + * change the queue threshold profile associated with this tm_queue. + * + * @param[in] tm_queue Specifies the tm_queue to be changed. + * @param[in] thresholds_profile Specifies the queue threshold profile that + * should now be used for the given tm_queue. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_queue_threshold_config(odp_tm_queue_t tm_queue, + odp_tm_threshold_t thresholds_profile); + +/** odp_tm_queue_wred_config() function is used to dynamically set or change + * the WRED profile associated with this tm_queue or tm_queue/pkt_color + * combination. + * + * @param[in] tm_queue Specifies the tm_queue to be changed. + * @param[in] pkt_color Specifies the pkt_color that this profile is to be + * used with. Can also be the special value + * ALL_PKT_COLORS. + * @param[in] wred_profile Specifies the WRED profile that should now be used + * by this tm_queue, when processing pkts of this + * pkt_color. It can be the value ODP_TM_INVALID + * indicating that this tm_queue/pkt_color combination + * no longer implements WRED. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_queue_wred_config(odp_tm_queue_t tm_queue, + odp_packet_color_t pkt_color, + odp_tm_wred_t wred_profile); + +/** Topology setting functions */ + +/** Connects the "output" of the src_tm_node to be a "producer" of the given + * dst_tm_node. Note that an ODP_TM_ROOT handle passed in for the + * dst_tm_node implies connection to the egress/root object of this TM system. + * + * @param[in] src_tm_node odp_tm_node_t handle of the tm_node whose output is + * to be connected to the fan-in of the next tm_node + * as represented by the dst_tm_node. + * @param[in] dst_tm_node odp_tm_node_t handle of the tm_node object that will + * receive all of the pkt_descs from the src tm_node + * output. If ODP_TM_ROOT, then attachment is to + * the root egress object/spigot. + * @return 0 upon success, < 0 on failure. + */ +int odp_tm_node_connect(odp_tm_node_t src_tm_node, odp_tm_node_t dst_tm_node); + +/** The odp_queue_connect() function connects the indicated tm_queue to a + * parent tm_node or to the egress/root node. The tm_queue will then become + * one of the dst node's fan-in set. + * + * @param[in] tm_queue Specifies the tm_queue. + * @param[in] dst_tm_node odp_tm_node_t handle of the tm_node object that will + * receive all of the pkt_descs from the src tm_node + * output. If ODP_TM_ROOT, then attachment is to + * the root egress object/spigot. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_queue_connect(odp_tm_queue_t tm_queue, odp_tm_node_t dst_tm_node); + +/** Input API */ + +/** The odp_tm_enq() function is used to add packets to a given TM system. + * Note that the System Metadata associated with the pkt needed by the TM + * system is (a) a drop_eligible bit, (b) a two bit "pkt_color", (c) a 16-bit + * pkt_len, and MAYBE? (d) a signed 8-bit shaper_len_adjust. + * + * If there is a non-zero shaper_len_adjust, then it is added to the pkt_len + * after any non-zero shaper_len_adjust that is part of the shaper profile. + * + * The pkt_color bits are a result of some earlier Metering/Marking/Policing + * processing (typically ingress based), and should not be confused with the + * shaper_color produced from the TM shaper entities within the tm_inputs and + * tm_nodes. + * + * @param[in] tm_queue Specifies the tm_queue (and indirectly the TM system). + * @param[in] pkt Handle to a packet. + * @return Returns 0 upon success, < 0 upon failure. One of the + * more common failure reasons is WRED dropage. + */ +int odp_tm_enq(odp_tm_queue_t tm_queue, odp_packet_t pkt); + +/** The odp_tm_enq_with_cnt() function behaves identically to odp_tm_enq(), + * except that it also returns (an approximation to?) the current tm_queue + * packet queue count. + * + * @param[in] tm_queue Specifies the tm_queue (and indirectly the TM system). + * @param[in] pkt Handle to a packet. + * @return Returns the number of packets previously enqueued on + * this tm_queue upon success, < 0 upon failure. + */ +int odp_tm_enq_with_cnt(odp_tm_queue_t tm_queue, odp_packet_t pkt); + +/** Dynamic state query functions */ + +/** The following bit mask constants are used to refine the queue query + * functions defined below. + */ +#define ODP_TM_QUERY_PKT_CNT 0x01 /**< The total_pkt_cnt value */ +#define ODP_TM_QUERY_BYTE_CNT 0x02 /**< The total_byte_cnt value */ +#define ODP_TM_QUERY_THRESHOLDS 0x04 /**< The thresholds??? */ + +/** The odp_tm_queue_info_t record type is used to return the various counts + * as requested by functions like odp_tm_queue_query() and + * odp_tm_total_query(). + */ +typedef struct { + /** The total_pkt_cnt field is the total number of packets currently + * stored/associated with the requested set of tm_queues. Note that + * because the packet queues are potentially being manipulated by + * multiple cpu's, the values here are only accurate when the tm + * system is "stopped" (i.e. the egress spigot is stopped and no + * odp_tm_enq calls are taking place). Implementations are free to + * batch update these counters - up to a dozen or so packets. + */ + uint64_t total_pkt_cnt; + + /** If the requested set of tm_queues has an odp_tm_threshold_t + * profile associated with it, then this is the max_pkt_cnt set in the + * profile params. Returning this field is a convenience to the ODP + * programmer, enabling them to quickly see how the total_pkt_cnt + * compares to the maximum packet count threshold. Note that there is + * no requirement that total_pkt_cnt be <= max_pkt_cnt. + */ + uint64_t max_pkt_cnt; + + /** The total_byte_cnt can either be the actual number of bytes used + * or an approximation of the number of bytes used based upon the + * number of fixed sized buffers used multiplied by the buffer size. + * In both cases the total_byte_cnt should correspond to the same set + * of packets that were counted above. For instance, if the + * total_pkt_cnt is updated in a batch, then the total_byte_cnt should + * also be updated in the same batch. The approx_byte_cnt field below + * indicates whether the total_byte_cnt is buffer count based or not. + * In the case that the number of bytes used by a packet is rounded up + * to a 2, 4, 8, or 16 byte boundary, it is recommended that + * approx_byte_cnt be false. It is implementation dependent whether + * the byte count of a packet includes the CRC, but it is recommended + * that it not include headroom, preamble or IPG. Of course when the + * buffer counting method is used, it is expected that any headroom in + * the first buffer is implicitly included. Finally in the case of + * variable length pkt based buffering, instead of taking the + * total_pkt_cnt and multiplying it by the maximum ethernet packet + * size, it is recommended that byte_cnt_valid be FALSE - even when + * query_flags includes ODP_TM_QUERY_BYTE_CNT. + */ + uint64_t total_byte_cnt; + + /** If the requested set of tm_queues has an odp_tm_threshold_t + * profile associated with it, then this is the max_byte_cnt set in + * the profile params. Returning this field is a convenience to the + * ODP programmer, enabling them to quickly see how the total_byte_cnt + * compares to the maximum byte count threshold. Note that there is + * no requirement that total_byte_cnt be <= max_byte_cnt. + */ + uint64_t max_byte_cnt; + + /** The following boolean values indicate which of the counts above + * are valid. Invalid count values must be 0. + */ + odp_bool_t total_pkt_cnt_valid; /**< TRUE if total_pkt_cnt is valid */ + odp_bool_t max_pkt_cnt_valid; /**< TRUE if max_pkt_cnt is valid */ + odp_bool_t total_byte_cnt_valid; /**< TRUE if total_byte_cnt is valid */ + odp_bool_t max_byte_cnt_valid; /**< TRUE if max_byte_cnt is valid */ + + /** The approx_byte_cnt is TRUE if the total_byte_cnt field is valid + * AND if the buffer counting method is used. + */ + odp_bool_t approx_byte_cnt; +} odp_tm_queue_info_t; + +/** The odp_tm_queue_query() function can be used to check a single tm_queue's + * queue utilization. The query_flags indicate whether or not packet counts, + * byte counts or both are being requested. It is an error to request + * neither. The implementation may still return both sets of counts + * regardless of query_flags if the cost of returning all the counts is + * comparable to the cost of checking the query_flags. + * + * @param[in] tm_queue Specifies the tm_queue (and indirectly the + * TM system). + * @param[out] query_flags A set of flag bits indicating which counters are + * being requested to be returned in the info record. + * @param[out] info Pointer to an odp_tm_queue_info_t record where the + * requested queue info is returned. + * @return Returns 0 upon success, < 0 upon failure. + */ +int odp_tm_queue_query(odp_tm_queue_t tm_queue, + uint32_t query_flags, + odp_tm_queue_info_t *info); + +/** The odp_tm_priority_query() function can be used to check the queue + * utilization of all tm_queue's with the given priority. The query_flags + * indicate whether or not packet counts, byte counts or both are being + * requested. It is an error to request neither. The implementation may + * still return both sets of counts regardless of query_flags if the cost of + * returning all the counts is comparable to the cost of checking the + * query_flags. + * + * @param[in] odp_tm Specifies the TM system. + * @param[in] priority Supplies the strict priority level used to specify + * which tm_queues are included in the info values. + * @param[out] query_flags A set of flag bits indicating which counters are + * being requested to be returned in the info record. + * @param[out] info Pointer to an odp_tm_queue_info_t record where the + * requested queue info is returned. + * @return Returns 0 upon success, < 0 upon failure. + */ +int odp_tm_priority_query(odp_tm_t odp_tm, uint8_t priority, + uint32_t query_flags, odp_tm_queue_info_t *info); + +/** The odp_tm_total_query() function can be used to check the queue + * utilization of all tm_queue's in a single TM system. The query_flags + * indicate whether or not packet counts, byte counts or both are being + * requested. It is an error to request neither. The implementation may + * still return both sets of counts regardless of query_flags if the cost of + * returning all the counts is comparable to the cost of checking the + * query_flags. + * + * @param[in] odp_tm Specifies the TM system. + * @param[out] query_flags A set of flag bits indicating which counters are + * being requested to be returned in the info record. + * @param[out] info Pointer to an odp_tm_queue_info_t record where the + * requested queue info is returned. + * @return Returns 0 upon success, < 0 upon failure. + */ +int odp_tm_total_query(odp_tm_t odp_tm, uint32_t query_flags, + odp_tm_queue_info_t *info); + +/** The odp_tm_priority_threshold_config() function is only used to associate + * a maximum packet count and/or a maximum byte count with a strict priority + * level - for the benefit of the odp_tm_priority_query() function. It has no + * semantic effects other than returning these queue threshold values in the + * odp_tm_queue_info_t record. + * + * @param[in] odp_tm Specifies the TM system. + * @param[in] priority Supplies the strict priority level that + * the threshold profile params are associated + * with. + * @param[in] thresholds_profile Specifies the queue threshold profile that + * should now be associated with the supplied + * strict priority level. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_priority_threshold_config(odp_tm_t odp_tm, uint8_t priority, + odp_tm_threshold_t thresholds_profile); + +/** The odp_tm_total_threshold_config() function is only used to associate a + * maximum packet count and/or a maximum byte count with a TM system - for the + * benefit of the odp_tm_total_query() function. It has no semantic effects + * other than returning these queue threshold values in the + * odp_tm_queue_info_t record. + * + * @param[in] odp_tm Specifies the TM system. + * @param[in] thresholds_profile Specifies the queue threshold profile that + * should now be used for the entire TM + * system. + * @return Returns 0 upon success and < 0 upon failure. + */ +int odp_tm_total_threshold_config(odp_tm_t odp_tm, + odp_tm_threshold_t thresholds_profile); + +/** Misc functions */ + +/** The odp_tm_periodic_update function is a placeholder for any external + * source of periodic events. In some cases the TM system may already have an + * internal built-in source of periodic events - in which case calling this + * function has no effect. + */ +void odp_tm_periodic_update(void); + +/** The odp_tm_is_idle function is used to determine if the specified ODP + * traffic management system still has "work" to do (i.e. has at least one + * non-empty tm_queue and perhaps some outstanding timers etc). This function + * can be used by test programs and ODP applications that wish to know when + * TM system has completed its work - presumably after they have stopped + * sending in new pkts. Note that this function should not be called often + * since for some implementations this call could take a fairly long time + * to execute! + * + * @param[in] odp_tm Specifies the TM system. + * @return Returns 1 if the TM system is idle and 0 otherwise. + */ +odp_bool_t odp_tm_is_idle(odp_tm_t odp_tm); + +/** The odp_tm_stats_print function is used to write implementation-defined + * information about the specified TM system to the ODP log. The intended use + * is for debugging. + * + * @param[in] odp_tm Specifies the TM system. + */ +void odp_tm_stats_print(odp_tm_t odp_tm); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/include/odp/plat/packet_types.h b/platform/linux-generic/include/odp/plat/packet_types.h index 45cb801..c3be633 100644 --- a/platform/linux-generic/include/odp/plat/packet_types.h +++ b/platform/linux-generic/include/odp/plat/packet_types.h @@ -36,6 +36,17 @@ typedef ODP_HANDLE_T(odp_packet_seg_t); #define ODP_PACKET_SEG_INVALID _odp_cast_scalar(odp_packet_seg_t, 0xffffffff) +/** odp_packet_color_t assigns names to the various pkt "colors" */ +typedef enum { + ODP_PACKET_GREEN = 0, + ODP_PACKET_YELLOW = 1, + ODP_PACKET_RED = 2, + ODP_PACKET_ALL_COLORS = 3, +} odp_packet_color_t; + +/** Sets the maximum number of pkt "colors" */ +#define ODP_NUM_PACKET_COLORS 3 + /** Get printable format of odp_packet_t */ static inline uint64_t odp_packet_to_u64(odp_packet_t hdl) { diff --git a/platform/linux-generic/include/odp/plat/traffic_mngr_types.h b/platform/linux-generic/include/odp/plat/traffic_mngr_types.h new file mode 100644 index 0000000..52df64b --- /dev/null +++ b/platform/linux-generic/include/odp/plat/traffic_mngr_types.h @@ -0,0 +1,185 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * ODP traffic mngr + */ + +#ifndef ODP_TRAFFIC_MNGR_TYPES_H_ +#define ODP_TRAFFIC_MNGR_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <odp/std_types.h> +#include <odp/plat/strong_types.h> + +/** @addtogroup odp_traffic_mngr + * Macros and operations on a TM system. + * @{ + */ + +/** The ODP_TM_MAX_NUM_SYSTEMS constant specifies the maximum number of TM + * systems that may be created. On some platforms this might be much more + * limited to as little as one hardware TM system. + */ +#define ODP_TM_MAX_NUM_SYSTEMS 64 + +/** The ODP_TM_MAX_PRIORITIES constant specifies the largest range of + * priorities that any TM system can support. All strict priority values MUST + * in the range 0..ODP_TM_MAX_PRIORITIES-1. + */ +#define ODP_TM_MAX_PRIORITIES 16 + +/** The ODP_TM MAX_LEVELS constant specifies the largest range of + * tm_node levels that any TM system can support. Hence all tm_node level + * values MUST be in the range 0..ODP_TM_MAX_LEVELS-1. Smaller tm_node + * levels are associated with tm_nodes closer to the TM system egress. + */ +#define ODP_TM_MAX_LEVELS 8 + +/** + * The smallest SCHED weight is 1 (i.e. 0 is not a legal WFQ/WRR value). + */ +#define ODP_TM_MIN_SCHED_WEIGHT 1 + +/** The ODP_TM_MAX_SCHED_WEIGHT constant is the largest weight any TM system + * can support (at least from a configuration standpoint). A given TM system + * could have a smaller value. + */ +#define ODP_TM_MAX_SCHED_WEIGHT 255 + +/** The ODP_TM_MAX_TM_QUEUES constant is the largest number of tm_queues + * that can handled by any one TM system. + */ +#define ODP_TM_MAX_TM_QUEUES (16 * 1024 * 1024) + +/** The ODP_TM_MAX_NUM_OUTPUTS constant is the largest number of outputs that + * can be configured for any one TM system. + */ +#define ODP_TM_MAX_NUM_OUTPUTS 256 + +/** The ODP_TM_MAX_NUM_TM_NODES constant is the largest number of tm_nodes that + * can be in existence for any one TM system. + */ +#define ODP_TM_MAX_NUM_TM_NODES (1024 * 1024) + +/** The ODP_TM_MAX_TM_NODE_FANIN constant is the largest number of fan-in + * "inputs" that can be simultaneously connected to a single tm_node. + * *TBD* Does this need to be as large as ODP_TM_MAX_TM_QUEUES? *TBD* + */ +#define ODP_TM_MAX_TM_NODE_FANIN (1024 * 1024) + +/** The ODP_TM_MIN_SHAPER_BW constant is the smallest amount of bandwidth that + * can a shaper's peak or commit rate can be set to. It is in units of + * 1000 bytes/second so that it and the ODP_TM_MAX_SHAPER_BW can both fit in + * 32 bits. + */ +#define ODP_TM_MIN_SHAPER_BW 1 + +/** The ODP_TM_MAX_SHAPER_BW constant is the largest amound of bandwidth that + * any shaper's peak or commit rate can be set to. It is in units of + * 1000 bytes/second so that it and the ODP_TM_MIN_SHAPER_BW can both fit in + * 32 bits. + */ +#define ODP_TM_MAX_SHAPER_BW 12500000 + +/** The ODP_NUM_SHAPER_COLORS constant just counts the number of enumeration + * values defined in the odp_tm_shaper_color_t type. + */ +#define ODP_NUM_SHAPER_COLORS 3 + +/** The INVALID_PRIORITY constant is used when one needs to indicate an + * invalid priority value. + */ +#define ODP_TM_INVALID_PRIORITY 255 + +/** The odp_tm_percent_t type is used when specifying fields that are + * percentages. It is a fixed point integer whose units are 1/100 of a + * percent. Hence 100% is represented as the integer value 10000. Note + * that because it is often used as a ratio of the current queue value and + * maximum queue threshold, it can be > 100%, but in any event will never + * be larger than 500% (i.e. it MUST be capped at 50000). + */ +typedef uint16_t odp_tm_percent_t; + +/** The odp_tm_handle_t type is a generic type that can stand for any of the + * other ODP_TM handle types. + */ +typedef uint64_t odp_tm_handle_t; + +/** Each odp_tm_t value represents a specific TM system. Almost all + * functions in this API require a odp_tm_t value - either directly + * as a function parameter or indirectly by having another ODP TM handle value + * as a function parameter. + */ +typedef odp_tm_handle_t odp_tm_t; + +/** Each odp_tm_queue_t value is an opaque ODP handle representing a specific + * tm_queue within a specific TM system. + */ +typedef odp_tm_handle_t odp_tm_queue_t; + +/** Each odp_tm_node_t value is an opaque ODP handle representing a specific + * tm_node within a specific TM system. + */ +typedef odp_tm_handle_t odp_tm_node_t; + +/** Each odp_tm_shaper_t value is an opaque ODP handle representing a specific + * shaper profile usable across all TM systems described by this API. A given + * shaper profile can then be attached to any tm_queue or tm_node. + */ +typedef odp_tm_handle_t odp_tm_shaper_t; + +/** Each odp_tm_sched_t value is an opaque ODP handle representing a specific + * tm_node scheduler profile usable across all TM systems described by this + * API. A given tm_node scheduler profile can then be attached to any tm_node. + */ +typedef odp_tm_handle_t odp_tm_sched_t; + +/** Each odp_tm_threshold_t value is an opaque ODP handle representing a + * specific queue threshold profile usable across all TM systems described by + * this API. A given queue threshold profile can then be attached to any + * tm_queue or tm_node. + */ +typedef odp_tm_handle_t odp_tm_threshold_t; + +/** Each odp_tm_wred_t value is an opaque ODP handle representing a specific + * WRED profile usable across all TM systems described by this API. A given + * WRED profile can then be attached to any tm_queue or tm_node. + */ +typedef odp_tm_handle_t odp_tm_wred_t; + +/** The ODP_TM_INVALID constant can be used with any ODP TM handle type and + * indicates that this value does NOT represent a valid TM object. + */ +#define ODP_TM_INVALID 0 + +/** + * @def ODP_TM_ROOT + * Constant that is used to refer to the egress/root node of the TM subsystem's + * tree/hierarchy of nodes. + */ +#define ODP_TM_ROOT 0 + +/** Get printable format of odp_queue_t */ +static inline uint64_t odp_tm_handle_to_u64(odp_tm_handle_t hdl) +{ + return hdl; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/include/odp/traffic_mngr.h b/platform/linux-generic/include/odp/traffic_mngr.h new file mode 100644 index 0000000..3aa6267 --- /dev/null +++ b/platform/linux-generic/include/odp/traffic_mngr.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * ODP Traffic manager + */ + +#ifndef ODP_PLAT_TRAFFIC_MNGR_H_ +#define ODP_PLAT_TRAFFIC_MNGR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @ingroup odp_traffic_mngr + * @{ + */ + +/** + * @} + */ + +#include <odp/plat/traffic_mngr_types.h> +#include <odp/api/traffic_mngr.h> + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index ba2cd7e..d3eaad0 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -61,6 +61,9 @@ typedef union { uint32_t tcpopt:1; /**< TCP options present */ uint32_t sctp:1; /**< SCTP */ uint32_t icmp:1; /**< ICMP */ + + uint32_t color:2; /**< Packet color for traffic mgmt */ + uint32_t nodrop:1; /**< Drop eligibility status */ }; } input_flags_t; @@ -102,6 +105,8 @@ typedef union { uint32_t l3_chksum:1; /**< L3 chksum override */ uint32_t l4_chksum_set:1; /**< L3 chksum bit is valid */ uint32_t l4_chksum:1; /**< L4 chksum override */ + + int8_t shaper_len_adj; /**< adjustment for traffic mgr */ }; } output_flags_t;