diff mbox

[API-NEXT] doc: user-guide documentation for classification

Message ID 1455545574-8393-1-git-send-email-bala.manoharan@linaro.org
State Superseded
Headers show

Commit Message

Balasubramanian Manoharan Feb. 15, 2016, 2:12 p.m. UTC
Adds user-guide documentation for classification module

Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>
---
 doc/users-guide/users-guide-cls.adoc | 220 +++++++++++++++++++++++++++++++++++
 1 file changed, 220 insertions(+)
 create mode 100644 doc/users-guide/users-guide-cls.adoc

Comments

Christophe Milard Feb. 15, 2016, 3:22 p.m. UTC | #1
On 15 February 2016 at 15:12, Balasubramanian Manoharan <
bala.manoharan@linaro.org> wrote:

> Adds user-guide documentation for classification module

>

> Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>

> ---

>  doc/users-guide/users-guide-cls.adoc | 220

> +++++++++++++++++++++++++++++++++++

>  1 file changed, 220 insertions(+)

>  create mode 100644 doc/users-guide/users-guide-cls.adoc

>

> diff --git a/doc/users-guide/users-guide-cls.adoc

> b/doc/users-guide/users-guide-cls.adoc

> new file mode 100644

> index 0000000..3089f86

> --- /dev/null

> +++ b/doc/users-guide/users-guide-cls.adoc

> @@ -0,0 +1,220 @@

> +== Classification \(CLS)

> +

> +ODP is a framework for software-based packet forwarding/filtering

> applications,

> +and the purpose of the Packet Classification API is to enable

> applications to

> +program the platform hardware or software implementation to assist in

> +prioritization, classification and scheduling of each packet, so that the

> +software application can run faster, scale better and adhere to QoS

> +requirements.

> +

> +The following API abstraction are not modelled after any existing product

> +implementation, but is instead defined in terms of what a typical

> data-plane

> +application may require from such a platform, without sacrificing

> simplicity and

> +avoiding ambiguity. Certain terms that are being used within the context

> of

> +existing products in relation to packet parsing and classification, such

> as

> +access lists are avoided such that not to suggest any relationship

> +between the abstraction used within this API and any particular manner in

> which

> +they may be implemented in hardware.

> +

> +=== Functional Description

> +

> +Following is the functionality that is required of the classification

> API, and

> +its underlying implementation. The details and order of the following

> paragraph

> +is informative, and is only intended to help convey the functional scope

> of a

> +classifier aznd provide context for the API. In reality, implementations

> may

>


typo: "and", not aznd


> +execute many of these steps concurrently, or in different order while

> +maintaining the evident dependencies:

> +

> +1. Apply a set of classification rules to the header of an incoming

> packet,

> +identify the header fields, e.g. ,ethertype, IP version, IP protocol,

> transport

> +layer port numbers, IP DiffServ, VLAN id, 802.1p priority.

> +

> +2. Store these fields as packet meta data for application use, and for the

> +remainder of parser operations. The odp_pktio is also stored as one of

> the meta

> +data fields for subsequent use.

> +

> +3. Compute an odp_cos (Class of Service) value from a subset of supported

> fields

> +from 1) above.

> +

> +4. Based on the odp_cos from 3) above, select the odp_queue through which

> the

> +packet is delivered to the application.

> +

> +5. Validate the packet data integrity (checksums, FCS)  and correctness

> (e.g.,

> +length fields) and store the validation result, along with optional error

> layer

> +and type indicator, in packet meta data. Optionally, if a packet fails

> +validation, override the odp_cos selection in step 3 to a class of service

> +designated for errored packets.

> +

> +6. Based on the odp_cos from 3) above, select the odp_buffer_pool that

> should be

> +used to acquire a buffer to store the packet data and meta data.

> +

> +7. Allocate a buffer from odp_buffer_pool selected in 6) above and

> logically[1]

> +store the packet data and meta data to the allocated buffer, or in

> accordance

> +with class-of-service drop policy and subject to pool buffer availability,

> +optionally discard the packet.

> +

> +8. Enqueue the buffer into the odp_queue selected in 4) above.

> +

> +The above is an abstract description of the classifier functionality, and

> may be

> +applied to a variety of applications in many different ways. The ultimate

> +meaning of how this functionality applies to an application also depends

> on

> +other ODP modules, so the above may not complete a full depiction. For

> instance,

> +the exact meaning of priority, which is a per-queue attribute is

> influenced by

> +the ODP scheduler semantics, and the system behavior under stress depends

> on the

> +ODP buffer pool module behavior.

> +

> +For the sole purpose of illustrating the above abstract functionality,

> here is

> +an example of a Layer-2 (IEEE 802.1D)  bridge application: Such a

> forwarding

> +application that also adheres to IEEE 802.1p/q priority, which has 8

> traffic

> +priority levels, might create 8 odp_buffer_pool instances, one for each

> PCP

> +priority level, and 8 odp_queue instances one per priority level. Incoming

> +packets will be inspected for a VLAN header; the PCP field will be

> extracted,

> +and used to select both the pool and the queue. Because each queue will be

> +assigned a priority value, the packets with highest PCP values will be

> scheduled

> +before any packet with a lower PCP value. Also, in a case of congestion,

> buffer

> +pools for lower priority packets will be depleted earlier than the pools

> +containing packets of the high priority, and hence the lower priority

> packets

> +will be dropped (assuming that is the only flow control method that is

> supported

> +in the platform) while higher priority packets will continue to be

> received into

> +buffers and processed.

> +

> +=== Class of Service Creation and Binding

> +

> +To program the classifier, a class-of-service instance must be created,

> which

> +will contain the packet filtering resources that it may require. All

> subsequent

> +calls refer to one or more of these resources.

> +

> +Each class of service instance must be associated with a single queue or

> queue

> +group, which will be the destination of all packets matching that

> particular

> +filter. The queue assignment is implemented as a separate function call

> such

> +that the queue may be modified at any time, without tearing down the

> filters

> +that define the class of service. In other words, it is possible to

> change the

> +destination queue for a class of service defined by its filters quickly

> and

> +dynamically.

> +

> +Optionally, on platforms that support multiple packet buffer pools, each

> class

> +of service may be assigned a different pool such that when buffers are

> exhausted

> +for one class of service, other classes are not negatively impacted and

> continue

> +to be processed.

> +

> +=== Default packet handling

> +

> +There SHOULD be one odp_cos assigned to each port with the

> odp_pktio_default_cos_set()

> +function,  which will function as the default class-of-service for all

> packets

> +received from an ingress port, that do not match any of the filters

> defined

> +subsequently. At minimum this default class-of-service MUST have a queue

> and a

> +buffer pool assigned to it on platforms that support multiple packet

> buffer

> +pools. Multiple odp_pktio instances (i.e., multiple ports) MAY each have

> their

> +own default odp_cos, or MAY share a odp_cos with other ports, based on

> +application requirements.

> +

> +Packet Classification

> +

> +For each odp_pktio port, the API allows the assignment of a

> class-of-service to

> +a packet using one of  three methods:

> +

> +1. The packet may be assigned a specific class-of-service based on its

> Layer-2

> +(802.1P/902.1Q VLAN tag) priority field. Since the standard field defines

> 8

> +discrete priority levels, the API allows to assign an odp_cos to each of

> these

> +priority levels with the odp_cos_with_l2_priority() function.

> +

> +2. Similarly, a class-of-service may be assigned using the Layer-3 (IP

> DiffServ)

> +header field. The application supplies an array of odp_cos values that

> covers

> +the entire range of the standard protocol header field, where array

> elements do

> +not need to contain unique values. There is also a need to specify if

> Layer-3

> +priority takes precedence over Layer-2 priority in a packet with both

> headers

> +present.

> +

> +3. Additionally, the application may also program a number of pattern

> matching

> +rules that assign a class-of-service for packets with header fields

> matching

> +specified values. The field-matching rules take precedence over the

> previously

> +described priority-based assignment of a class-of-service. Using these

> matching

> +rules the application should be able for example to identify all packets

> +containing VoIP traffic based on the protocol being UDP, and a specific

> +destination or source port numbers, and appropriately assign these

> packets an

> +class-of-service that maps to a higher priority queue, assuring voice

> packets a

> +lower and bound latency.

> +

> +Packet meta data Elements

> +

> +Here are the specific information elements that SHOULD be stored within

> the

> +packet meta data structure:

> +

> +* Protocol fields that are decoded and extracted by the parsing phase

> +

> +* The pool identifier that is selected for the packet

> +

> +* The ingress port identifier

> +

> +* The result of packet validation, including an indication of the type of

> error

> +* detected, if any

> +

> +The ODP packet API module SHALL provide accessors for retrieving the

> above meta

> +data fields from the container buffer in an implementation-independent

> manner.

>


why SHOULD and SHALL? This is a user guide, not a ODP requirement spec:
shouldn't it be "ARE" (instead of should) and just "provides" (instead of
shall provide)?

+
> +===  Example configuration

> +

> +CoS configuration can be best illustrated by drawing a tree, where each

> CoS is

> +the vertex, and each link between any two vertices is a PMR. The root

> node for

> +the tree is the default CoS which is attached with the pktio interface.

> All of

> +the CoS vertices can be final for some packets, if these packets do not

> match

> +any of the links.

> +

> +Let us consider the below configuration

> +

> +odp_pktio_default_cos_set(odp_pktio_t pktio, odp_cos_t default_cos);

> +

> +pmr1 = odp_cls_pmr_create(pmr_match1, default_cos,  cos1);

> +pmr2 = odp_cls_pmr_create(pmr_match2, default_cos,  cos2);

> +pmr3 = odp_cls_pmr_create(pmr_match3, default_cos,  cos3);

> +

> +pmr11 = odp_cls_pmr_create(pmr_match11, cos1,  cos11);

> +pmr12 = odp_cls_pmr_create(pmr_match12, cos1,  cos12);

> +

> +pmr21 = odp_cls_pmr_create(pmr_match11, cos2,  cos21);

> +pmr31 = odp_cls_pmr_create(pmr_match11, cos3,  cos31);

> +

> +The above configuration DOES imply order - a packet that matches

> pmr_match1 will

> +then be applied to pmr_match11 and pmr_match12, and as a result could

> terminate

> +with either cost1, cos11, cos12. In this case the packet was subjected to

> two

> +match attempts in total.

> +

> +The remaining two lines illustrate how a packet that matches pmr_match11

> could

> +end up wth either cos11, cos21 or cos31, depending on wether it matches

>


typos: "with" and "whether"


> +pmr_march1, pmr_march2 or pmr_match3.

>


isn't it  " depending on whether it matches pmr_march1 only, pmr_march1 and
pmr_march2, or pmr_march1 and pmr_match3" ?
I mean pmr_march2 and  pmr_march3 are only appliied if the packet matched
pmr_march1 first, right?

+
> +Here is a practical example:

> +

> +Let's look at DNS packets, these are identified by using UDP port 53, but

> each

> +UDP packet may run atop of IPv4 or IPv6, and in turn an IP packet might be

> +received as either multicast or unicast,

> +

> +Very simply, we can create these PMRs:

> +

> +PMR-L2 = match all multicast/broadcast packets based on DMAC address

> PMR_L3_IP4

> += match all IPv4 packets PMR_L3_IP6 = match all IPv6 packets PMR_L4_UDP =

> match

> +all UDP packets PMR_L4_53 = match all packets with dest port = 53.

> +

> +odp_cls_pmr_create(PMR_L2, port_cos, port_cos_mc);

> +odp_cls_pmr_create(PMR_L3_IP4, port_cos, port_cos_ip4_uc);

> +odp_cls_pmr_create(PMR_L3_IP6, port_cos, port_cos_ip6_uc);

> +

> +odp_cls_pmr_create(PMR_L3_IP4, port_cos_mc, port_cos_ip4_mc);

> +odp_cls_pmr_create(PMR_L3_IP6, port_cos_mc, port_cos_ip6_mc);

> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip4_uc, cos_udp4_uc);

> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip4_mc, cos_udp4_mc);

> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip6_uc, cos_udp6_uc);

> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip6_mc, cos_udp6_mc);

> +

> +odp_cls_pmr_create(PMR_L4_53, cos_udp4_uc, dns4_uc);

> +odp_cls_pmr_create(PMR_L4_53, cos_udp4_mc, dns4_mc);

> +odp_cls_pmr_create(PMR_L4_53, cos_udp6_uc, dns6_uc);

> +odp_cls_pmr_create(PMR_L4_53, cos_udp6_mc, dns6_mc);

>


In the previous section, the root of the tree seemed to be "default_cos".
now it seems to be "default_cos". what is port_cos here?

Thanks,
Christophe.

> +

> +In this case, a packet may change CoS between 0 and 5 times, meaning that

> up to

> +5 PMRs may be applied in series, and the order

> +

> +Another interesting point is that an implementation will probably impose

> on a

> +limit of how many PMRs can be applied to a packet in series, so in the

> above

> +example, if an implementation limit on the number of consecutive

> classification

> +steps is 4, then all the DNS packets may only reach cos_udp?_?c set of

> vertices.

> --

> 1.9.1

>

> _______________________________________________

> lng-odp mailing list

> lng-odp@lists.linaro.org

> https://lists.linaro.org/mailman/listinfo/lng-odp

>
Balasubramanian Manoharan Feb. 16, 2016, 5:52 a.m. UTC | #2
Hi,

On 15 February 2016 at 20:52, Christophe Milard <
christophe.milard@linaro.org> wrote:

>

>

> On 15 February 2016 at 15:12, Balasubramanian Manoharan <

> bala.manoharan@linaro.org> wrote:

>

>> Adds user-guide documentation for classification module

>>

>> Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>

>> ---

>>  doc/users-guide/users-guide-cls.adoc | 220

>> +++++++++++++++++++++++++++++++++++

>>  1 file changed, 220 insertions(+)

>>  create mode 100644 doc/users-guide/users-guide-cls.adoc

>>

>> diff --git a/doc/users-guide/users-guide-cls.adoc

>> b/doc/users-guide/users-guide-cls.adoc

>> new file mode 100644

>> index 0000000..3089f86

>> --- /dev/null

>> +++ b/doc/users-guide/users-guide-cls.adoc

>> @@ -0,0 +1,220 @@

>> +== Classification \(CLS)

>> +

>> +ODP is a framework for software-based packet forwarding/filtering

>> applications,

>> +and the purpose of the Packet Classification API is to enable

>> applications to

>> +program the platform hardware or software implementation to assist in

>> +prioritization, classification and scheduling of each packet, so that the

>> +software application can run faster, scale better and adhere to QoS

>> +requirements.

>> +

>> +The following API abstraction are not modelled after any existing product

>> +implementation, but is instead defined in terms of what a typical

>> data-plane

>> +application may require from such a platform, without sacrificing

>> simplicity and

>> +avoiding ambiguity. Certain terms that are being used within the context

>> of

>> +existing products in relation to packet parsing and classification, such

>> as

>> +access lists are avoided such that not to suggest any relationship

>> +between the abstraction used within this API and any particular manner

>> in which

>> +they may be implemented in hardware.

>> +

>> +=== Functional Description

>> +

>> +Following is the functionality that is required of the classification

>> API, and

>> +its underlying implementation. The details and order of the following

>> paragraph

>> +is informative, and is only intended to help convey the functional scope

>> of a

>> +classifier aznd provide context for the API. In reality, implementations

>> may

>>

>

> typo: "and", not aznd

>


Good catch :)

>

>

>> +execute many of these steps concurrently, or in different order while

>> +maintaining the evident dependencies:

>> +

>> +1. Apply a set of classification rules to the header of an incoming

>> packet,

>> +identify the header fields, e.g. ,ethertype, IP version, IP protocol,

>> transport

>> +layer port numbers, IP DiffServ, VLAN id, 802.1p priority.

>> +

>> +2. Store these fields as packet meta data for application use, and for

>> the

>> +remainder of parser operations. The odp_pktio is also stored as one of

>> the meta

>> +data fields for subsequent use.

>> +

>> +3. Compute an odp_cos (Class of Service) value from a subset of

>> supported fields

>> +from 1) above.

>> +

>> +4. Based on the odp_cos from 3) above, select the odp_queue through

>> which the

>> +packet is delivered to the application.

>> +

>> +5. Validate the packet data integrity (checksums, FCS)  and correctness

>> (e.g.,

>> +length fields) and store the validation result, along with optional

>> error layer

>> +and type indicator, in packet meta data. Optionally, if a packet fails

>> +validation, override the odp_cos selection in step 3 to a class of

>> service

>> +designated for errored packets.

>> +

>> +6. Based on the odp_cos from 3) above, select the odp_buffer_pool that

>> should be

>> +used to acquire a buffer to store the packet data and meta data.

>> +

>> +7. Allocate a buffer from odp_buffer_pool selected in 6) above and

>> logically[1]

>> +store the packet data and meta data to the allocated buffer, or in

>> accordance

>> +with class-of-service drop policy and subject to pool buffer

>> availability,

>> +optionally discard the packet.

>> +

>> +8. Enqueue the buffer into the odp_queue selected in 4) above.

>> +

>> +The above is an abstract description of the classifier functionality,

>> and may be

>> +applied to a variety of applications in many different ways. The ultimate

>> +meaning of how this functionality applies to an application also depends

>> on

>> +other ODP modules, so the above may not complete a full depiction. For

>> instance,

>> +the exact meaning of priority, which is a per-queue attribute is

>> influenced by

>> +the ODP scheduler semantics, and the system behavior under stress

>> depends on the

>> +ODP buffer pool module behavior.

>> +

>> +For the sole purpose of illustrating the above abstract functionality,

>> here is

>> +an example of a Layer-2 (IEEE 802.1D)  bridge application: Such a

>> forwarding

>> +application that also adheres to IEEE 802.1p/q priority, which has 8

>> traffic

>> +priority levels, might create 8 odp_buffer_pool instances, one for each

>> PCP

>> +priority level, and 8 odp_queue instances one per priority level.

>> Incoming

>> +packets will be inspected for a VLAN header; the PCP field will be

>> extracted,

>> +and used to select both the pool and the queue. Because each queue will

>> be

>> +assigned a priority value, the packets with highest PCP values will be

>> scheduled

>> +before any packet with a lower PCP value. Also, in a case of congestion,

>> buffer

>> +pools for lower priority packets will be depleted earlier than the pools

>> +containing packets of the high priority, and hence the lower priority

>> packets

>> +will be dropped (assuming that is the only flow control method that is

>> supported

>> +in the platform) while higher priority packets will continue to be

>> received into

>> +buffers and processed.

>> +

>> +=== Class of Service Creation and Binding

>> +

>> +To program the classifier, a class-of-service instance must be created,

>> which

>> +will contain the packet filtering resources that it may require. All

>> subsequent

>> +calls refer to one or more of these resources.

>> +

>> +Each class of service instance must be associated with a single queue or

>> queue

>> +group, which will be the destination of all packets matching that

>> particular

>> +filter. The queue assignment is implemented as a separate function call

>> such

>> +that the queue may be modified at any time, without tearing down the

>> filters

>> +that define the class of service. In other words, it is possible to

>> change the

>> +destination queue for a class of service defined by its filters quickly

>> and

>> +dynamically.

>> +

>> +Optionally, on platforms that support multiple packet buffer pools, each

>> class

>> +of service may be assigned a different pool such that when buffers are

>> exhausted

>> +for one class of service, other classes are not negatively impacted and

>> continue

>> +to be processed.

>> +

>> +=== Default packet handling

>> +

>> +There SHOULD be one odp_cos assigned to each port with the

>> odp_pktio_default_cos_set()

>> +function,  which will function as the default class-of-service for all

>> packets

>> +received from an ingress port, that do not match any of the filters

>> defined

>> +subsequently. At minimum this default class-of-service MUST have a queue

>> and a

>> +buffer pool assigned to it on platforms that support multiple packet

>> buffer

>> +pools. Multiple odp_pktio instances (i.e., multiple ports) MAY each have

>> their

>> +own default odp_cos, or MAY share a odp_cos with other ports, based on

>> +application requirements.

>> +

>> +Packet Classification

>> +

>> +For each odp_pktio port, the API allows the assignment of a

>> class-of-service to

>> +a packet using one of  three methods:

>> +

>> +1. The packet may be assigned a specific class-of-service based on its

>> Layer-2

>> +(802.1P/902.1Q VLAN tag) priority field. Since the standard field

>> defines 8

>> +discrete priority levels, the API allows to assign an odp_cos to each of

>> these

>> +priority levels with the odp_cos_with_l2_priority() function.

>> +

>> +2. Similarly, a class-of-service may be assigned using the Layer-3 (IP

>> DiffServ)

>> +header field. The application supplies an array of odp_cos values that

>> covers

>> +the entire range of the standard protocol header field, where array

>> elements do

>> +not need to contain unique values. There is also a need to specify if

>> Layer-3

>> +priority takes precedence over Layer-2 priority in a packet with both

>> headers

>> +present.

>> +

>> +3. Additionally, the application may also program a number of pattern

>> matching

>> +rules that assign a class-of-service for packets with header fields

>> matching

>> +specified values. The field-matching rules take precedence over the

>> previously

>> +described priority-based assignment of a class-of-service. Using these

>> matching

>> +rules the application should be able for example to identify all packets

>> +containing VoIP traffic based on the protocol being UDP, and a specific

>> +destination or source port numbers, and appropriately assign these

>> packets an

>> +class-of-service that maps to a higher priority queue, assuring voice

>> packets a

>> +lower and bound latency.

>> +

>> +Packet meta data Elements

>> +

>> +Here are the specific information elements that SHOULD be stored within

>> the

>> +packet meta data structure:

>> +

>> +* Protocol fields that are decoded and extracted by the parsing phase

>> +

>> +* The pool identifier that is selected for the packet

>> +

>> +* The ingress port identifier

>> +

>> +* The result of packet validation, including an indication of the type

>> of error

>> +* detected, if any

>> +

>> +The ODP packet API module SHALL provide accessors for retrieving the

>> above meta

>> +data fields from the container buffer in an implementation-independent

>> manner.

>>

>

> why SHOULD and SHALL? This is a user guide, not a ODP requirement spec:

> shouldn't it be "ARE" (instead of should) and just "provides" (instead of

> shall provide)?

>


Okay.

>

> +

>> +===  Example configuration

>> +

>> +CoS configuration can be best illustrated by drawing a tree, where each

>> CoS is

>> +the vertex, and each link between any two vertices is a PMR. The root

>> node for

>> +the tree is the default CoS which is attached with the pktio interface.

>> All of

>> +the CoS vertices can be final for some packets, if these packets do not

>> match

>> +any of the links.

>> +

>> +Let us consider the below configuration

>> +

>> +odp_pktio_default_cos_set(odp_pktio_t pktio, odp_cos_t default_cos);

>> +

>> +pmr1 = odp_cls_pmr_create(pmr_match1, default_cos,  cos1);

>> +pmr2 = odp_cls_pmr_create(pmr_match2, default_cos,  cos2);

>> +pmr3 = odp_cls_pmr_create(pmr_match3, default_cos,  cos3);

>> +

>> +pmr11 = odp_cls_pmr_create(pmr_match11, cos1,  cos11);

>> +pmr12 = odp_cls_pmr_create(pmr_match12, cos1,  cos12);

>> +

>> +pmr21 = odp_cls_pmr_create(pmr_match11, cos2,  cos21);

>> +pmr31 = odp_cls_pmr_create(pmr_match11, cos3,  cos31);

>> +

>> +The above configuration DOES imply order - a packet that matches

>> pmr_match1 will

>> +then be applied to pmr_match11 and pmr_match12, and as a result could

>> terminate

>> +with either cost1, cos11, cos12. In this case the packet was subjected

>> to two

>> +match attempts in total.

>> +

>> +The remaining two lines illustrate how a packet that matches pmr_match11

>> could

>> +end up wth either cos11, cos21 or cos31, depending on wether it matches

>>

>

> typos: "with" and "whether"

>

>

>> +pmr_march1, pmr_march2 or pmr_match3.

>>

>

> isn't it  " depending on whether it matches pmr_march1 only, pmr_march1

> and pmr_march2, or pmr_march1 and pmr_match3" ?

> I mean pmr_march2 and  pmr_march3 are only appliied if the packet matched

> pmr_march1 first, right?

>


Actually No. pmr_match1, pmr_match2 and pmr_match3 are all applied on
default_cos and hence all the three PMRs are in the same level and the
classification API does not dictate any priority between PMRs on the same
level. The order in which PMRs on the same level will be verified is
implementation dependent. The responsibility lies in the application to
make sure there is no ambiguity in classification configuration. I believe
the example configuration below with practical configuration explains the
use case in detail.

 Also please note that the order of PMR matching can be implemented using
PMR chaining i.e in the above example pmr_match11 will only be applied
depending on whether the packet succeeded pmr_match1, pmr_match2 or
pmr_match3.

>

> +

>> +Here is a practical example:

>> +

>> +Let's look at DNS packets, these are identified by using UDP port 53,

>> but each

>> +UDP packet may run atop of IPv4 or IPv6, and in turn an IP packet might

>> be

>> +received as either multicast or unicast,

>> +

>> +Very simply, we can create these PMRs:

>> +

>> +PMR-L2 = match all multicast/broadcast packets based on DMAC address

>> PMR_L3_IP4

>> += match all IPv4 packets PMR_L3_IP6 = match all IPv6 packets PMR_L4_UDP

>> = match

>> +all UDP packets PMR_L4_53 = match all packets with dest port = 53.

>> +

>> +odp_cls_pmr_create(PMR_L2, port_cos, port_cos_mc);

>> +odp_cls_pmr_create(PMR_L3_IP4, port_cos, port_cos_ip4_uc);

>> +odp_cls_pmr_create(PMR_L3_IP6, port_cos, port_cos_ip6_uc);

>> +

>> +odp_cls_pmr_create(PMR_L3_IP4, port_cos_mc, port_cos_ip4_mc);

>> +odp_cls_pmr_create(PMR_L3_IP6, port_cos_mc, port_cos_ip6_mc);

>> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip4_uc, cos_udp4_uc);

>> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip4_mc, cos_udp4_mc);

>> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip6_uc, cos_udp6_uc);

>> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip6_mc, cos_udp6_mc);

>> +

>> +odp_cls_pmr_create(PMR_L4_53, cos_udp4_uc, dns4_uc);

>> +odp_cls_pmr_create(PMR_L4_53, cos_udp4_mc, dns4_mc);

>> +odp_cls_pmr_create(PMR_L4_53, cos_udp6_uc, dns6_uc);

>> +odp_cls_pmr_create(PMR_L4_53, cos_udp6_mc, dns6_mc);

>>

>

> In the previous section, the root of the tree seemed to be "default_cos".

> now it seems to be "default_cos". what is port_cos here?

>


Yes. port_cos and default_cos are the same. I will change everything to
"default_cos" since I believe it is more easier to understand.

Regards,
Bala

>

> Thanks,

> Christophe.

>

>> +

>> +In this case, a packet may change CoS between 0 and 5 times, meaning

>> that up to

>> +5 PMRs may be applied in series, and the order

>> +

>> +Another interesting point is that an implementation will probably impose

>> on a

>> +limit of how many PMRs can be applied to a packet in series, so in the

>> above

>> +example, if an implementation limit on the number of consecutive

>> classification

>> +steps is 4, then all the DNS packets may only reach cos_udp?_?c set of

>> vertices.

>> --

>> 1.9.1

>>

>> _______________________________________________

>> lng-odp mailing list

>> lng-odp@lists.linaro.org

>> https://lists.linaro.org/mailman/listinfo/lng-odp

>>

>

>
Christophe Milard Feb. 16, 2016, 7:06 a.m. UTC | #3
On 16 February 2016 at 06:52, Bala Manoharan <bala.manoharan@linaro.org>
wrote:

> Hi,

>

> On 15 February 2016 at 20:52, Christophe Milard <

> christophe.milard@linaro.org> wrote:

>

>>

>>

>> On 15 February 2016 at 15:12, Balasubramanian Manoharan <

>> bala.manoharan@linaro.org> wrote:

>>

>>> Adds user-guide documentation for classification module

>>>

>>> Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>

>>> ---

>>>  doc/users-guide/users-guide-cls.adoc | 220

>>> +++++++++++++++++++++++++++++++++++

>>>  1 file changed, 220 insertions(+)

>>>  create mode 100644 doc/users-guide/users-guide-cls.adoc

>>>

>>> diff --git a/doc/users-guide/users-guide-cls.adoc

>>> b/doc/users-guide/users-guide-cls.adoc

>>> new file mode 100644

>>> index 0000000..3089f86

>>> --- /dev/null

>>> +++ b/doc/users-guide/users-guide-cls.adoc

>>> @@ -0,0 +1,220 @@

>>> +== Classification \(CLS)

>>> +

>>> +ODP is a framework for software-based packet forwarding/filtering

>>> applications,

>>> +and the purpose of the Packet Classification API is to enable

>>> applications to

>>> +program the platform hardware or software implementation to assist in

>>> +prioritization, classification and scheduling of each packet, so that

>>> the

>>> +software application can run faster, scale better and adhere to QoS

>>> +requirements.

>>> +

>>> +The following API abstraction are not modelled after any existing

>>> product

>>> +implementation, but is instead defined in terms of what a typical

>>> data-plane

>>> +application may require from such a platform, without sacrificing

>>> simplicity and

>>> +avoiding ambiguity. Certain terms that are being used within the

>>> context of

>>> +existing products in relation to packet parsing and classification,

>>> such as

>>> +access lists are avoided such that not to suggest any relationship

>>> +between the abstraction used within this API and any particular manner

>>> in which

>>> +they may be implemented in hardware.

>>> +

>>> +=== Functional Description

>>> +

>>> +Following is the functionality that is required of the classification

>>> API, and

>>> +its underlying implementation. The details and order of the following

>>> paragraph

>>> +is informative, and is only intended to help convey the functional

>>> scope of a

>>> +classifier aznd provide context for the API. In reality,

>>> implementations may

>>>

>>

>> typo: "and", not aznd

>>

>

> Good catch :)

>

>>

>>

>>> +execute many of these steps concurrently, or in different order while

>>> +maintaining the evident dependencies:

>>> +

>>> +1. Apply a set of classification rules to the header of an incoming

>>> packet,

>>> +identify the header fields, e.g. ,ethertype, IP version, IP protocol,

>>> transport

>>> +layer port numbers, IP DiffServ, VLAN id, 802.1p priority.

>>> +

>>> +2. Store these fields as packet meta data for application use, and for

>>> the

>>> +remainder of parser operations. The odp_pktio is also stored as one of

>>> the meta

>>> +data fields for subsequent use.

>>> +

>>> +3. Compute an odp_cos (Class of Service) value from a subset of

>>> supported fields

>>> +from 1) above.

>>> +

>>> +4. Based on the odp_cos from 3) above, select the odp_queue through

>>> which the

>>> +packet is delivered to the application.

>>> +

>>> +5. Validate the packet data integrity (checksums, FCS)  and correctness

>>> (e.g.,

>>> +length fields) and store the validation result, along with optional

>>> error layer

>>> +and type indicator, in packet meta data. Optionally, if a packet fails

>>> +validation, override the odp_cos selection in step 3 to a class of

>>> service

>>> +designated for errored packets.

>>> +

>>> +6. Based on the odp_cos from 3) above, select the odp_buffer_pool that

>>> should be

>>> +used to acquire a buffer to store the packet data and meta data.

>>> +

>>> +7. Allocate a buffer from odp_buffer_pool selected in 6) above and

>>> logically[1]

>>> +store the packet data and meta data to the allocated buffer, or in

>>> accordance

>>> +with class-of-service drop policy and subject to pool buffer

>>> availability,

>>> +optionally discard the packet.

>>> +

>>> +8. Enqueue the buffer into the odp_queue selected in 4) above.

>>> +

>>> +The above is an abstract description of the classifier functionality,

>>> and may be

>>> +applied to a variety of applications in many different ways. The

>>> ultimate

>>> +meaning of how this functionality applies to an application also

>>> depends on

>>> +other ODP modules, so the above may not complete a full depiction. For

>>> instance,

>>> +the exact meaning of priority, which is a per-queue attribute is

>>> influenced by

>>> +the ODP scheduler semantics, and the system behavior under stress

>>> depends on the

>>> +ODP buffer pool module behavior.

>>> +

>>> +For the sole purpose of illustrating the above abstract functionality,

>>> here is

>>> +an example of a Layer-2 (IEEE 802.1D)  bridge application: Such a

>>> forwarding

>>> +application that also adheres to IEEE 802.1p/q priority, which has 8

>>> traffic

>>> +priority levels, might create 8 odp_buffer_pool instances, one for each

>>> PCP

>>> +priority level, and 8 odp_queue instances one per priority level.

>>> Incoming

>>> +packets will be inspected for a VLAN header; the PCP field will be

>>> extracted,

>>> +and used to select both the pool and the queue. Because each queue will

>>> be

>>> +assigned a priority value, the packets with highest PCP values will be

>>> scheduled

>>> +before any packet with a lower PCP value. Also, in a case of

>>> congestion, buffer

>>> +pools for lower priority packets will be depleted earlier than the pools

>>> +containing packets of the high priority, and hence the lower priority

>>> packets

>>> +will be dropped (assuming that is the only flow control method that is

>>> supported

>>> +in the platform) while higher priority packets will continue to be

>>> received into

>>> +buffers and processed.

>>> +

>>> +=== Class of Service Creation and Binding

>>> +

>>> +To program the classifier, a class-of-service instance must be created,

>>> which

>>> +will contain the packet filtering resources that it may require. All

>>> subsequent

>>> +calls refer to one or more of these resources.

>>> +

>>> +Each class of service instance must be associated with a single queue

>>> or queue

>>> +group, which will be the destination of all packets matching that

>>> particular

>>> +filter. The queue assignment is implemented as a separate function call

>>> such

>>> +that the queue may be modified at any time, without tearing down the

>>> filters

>>> +that define the class of service. In other words, it is possible to

>>> change the

>>> +destination queue for a class of service defined by its filters quickly

>>> and

>>> +dynamically.

>>> +

>>> +Optionally, on platforms that support multiple packet buffer pools,

>>> each class

>>> +of service may be assigned a different pool such that when buffers are

>>> exhausted

>>> +for one class of service, other classes are not negatively impacted and

>>> continue

>>> +to be processed.

>>> +

>>> +=== Default packet handling

>>> +

>>> +There SHOULD be one odp_cos assigned to each port with the

>>> odp_pktio_default_cos_set()

>>> +function,  which will function as the default class-of-service for all

>>> packets

>>> +received from an ingress port, that do not match any of the filters

>>> defined

>>> +subsequently. At minimum this default class-of-service MUST have a

>>> queue and a

>>> +buffer pool assigned to it on platforms that support multiple packet

>>> buffer

>>> +pools. Multiple odp_pktio instances (i.e., multiple ports) MAY each

>>> have their

>>> +own default odp_cos, or MAY share a odp_cos with other ports, based on

>>> +application requirements.

>>> +

>>> +Packet Classification

>>> +

>>> +For each odp_pktio port, the API allows the assignment of a

>>> class-of-service to

>>> +a packet using one of  three methods:

>>> +

>>> +1. The packet may be assigned a specific class-of-service based on its

>>> Layer-2

>>> +(802.1P/902.1Q VLAN tag) priority field. Since the standard field

>>> defines 8

>>> +discrete priority levels, the API allows to assign an odp_cos to each

>>> of these

>>> +priority levels with the odp_cos_with_l2_priority() function.

>>> +

>>> +2. Similarly, a class-of-service may be assigned using the Layer-3 (IP

>>> DiffServ)

>>> +header field. The application supplies an array of odp_cos values that

>>> covers

>>> +the entire range of the standard protocol header field, where array

>>> elements do

>>> +not need to contain unique values. There is also a need to specify if

>>> Layer-3

>>> +priority takes precedence over Layer-2 priority in a packet with both

>>> headers

>>> +present.

>>> +

>>> +3. Additionally, the application may also program a number of pattern

>>> matching

>>> +rules that assign a class-of-service for packets with header fields

>>> matching

>>> +specified values. The field-matching rules take precedence over the

>>> previously

>>> +described priority-based assignment of a class-of-service. Using these

>>> matching

>>> +rules the application should be able for example to identify all packets

>>> +containing VoIP traffic based on the protocol being UDP, and a specific

>>> +destination or source port numbers, and appropriately assign these

>>> packets an

>>> +class-of-service that maps to a higher priority queue, assuring voice

>>> packets a

>>> +lower and bound latency.

>>> +

>>> +Packet meta data Elements

>>> +

>>> +Here are the specific information elements that SHOULD be stored within

>>> the

>>> +packet meta data structure:

>>> +

>>> +* Protocol fields that are decoded and extracted by the parsing phase

>>> +

>>> +* The pool identifier that is selected for the packet

>>> +

>>> +* The ingress port identifier

>>> +

>>> +* The result of packet validation, including an indication of the type

>>> of error

>>> +* detected, if any

>>> +

>>> +The ODP packet API module SHALL provide accessors for retrieving the

>>> above meta

>>> +data fields from the container buffer in an implementation-independent

>>> manner.

>>>

>>

>> why SHOULD and SHALL? This is a user guide, not a ODP requirement spec:

>> shouldn't it be "ARE" (instead of should) and just "provides" (instead of

>> shall provide)?

>>

>

> Okay.

>

>>

>> +

>>> +===  Example configuration

>>> +

>>> +CoS configuration can be best illustrated by drawing a tree, where each

>>> CoS is

>>> +the vertex, and each link between any two vertices is a PMR. The root

>>> node for

>>> +the tree is the default CoS which is attached with the pktio

>>> interface.  All of

>>> +the CoS vertices can be final for some packets, if these packets do not

>>> match

>>> +any of the links.

>>> +

>>> +Let us consider the below configuration

>>> +

>>> +odp_pktio_default_cos_set(odp_pktio_t pktio, odp_cos_t default_cos);

>>> +

>>> +pmr1 = odp_cls_pmr_create(pmr_match1, default_cos,  cos1);

>>> +pmr2 = odp_cls_pmr_create(pmr_match2, default_cos,  cos2);

>>> +pmr3 = odp_cls_pmr_create(pmr_match3, default_cos,  cos3);

>>> +

>>> +pmr11 = odp_cls_pmr_create(pmr_match11, cos1,  cos11);

>>> +pmr12 = odp_cls_pmr_create(pmr_match12, cos1,  cos12);

>>> +

>>> +pmr21 = odp_cls_pmr_create(pmr_match11, cos2,  cos21);

>>> +pmr31 = odp_cls_pmr_create(pmr_match11, cos3,  cos31);

>>> +

>>> +The above configuration DOES imply order - a packet that matches

>>> pmr_match1 will

>>> +then be applied to pmr_match11 and pmr_match12, and as a result could

>>> terminate

>>> +with either cost1, cos11, cos12. In this case the packet was subjected

>>> to two

>>> +match attempts in total.

>>> +

>>> +The remaining two lines illustrate how a packet that matches

>>> pmr_match11 could

>>> +end up wth either cos11, cos21 or cos31, depending on wether it matches

>>>

>>

>> typos: "with" and "whether"

>>

>>

>>> +pmr_march1, pmr_march2 or pmr_match3.

>>>

>>

>> isn't it  " depending on whether it matches pmr_march1 only, pmr_march1

>> and pmr_march2, or pmr_march1 and pmr_match3" ?

>> I mean pmr_march2 and  pmr_march3 are only appliied if the packet matched

>> pmr_march1 first, right?

>>

>

> Actually No. pmr_match1, pmr_match2 and pmr_match3 are all applied on

> default_cos and hence all the three PMRs are in the same level and the

> classification API does not dictate any priority between PMRs on the same

> level. The order in which PMRs on the same level will be verified is

> implementation dependent. The responsibility lies in the application to

> make sure there is no ambiguity in classification configuration. I believe

> the example configuration below with practical configuration explains the

> use case in detail.

>

>  Also please note that the order of PMR matching can be implemented using

> PMR chaining i.e in the above example pmr_match11 will only be applied

> depending on whether the packet succeeded pmr_match1, pmr_match2 or

> pmr_match3.

>


Ok. Actually your answer make more sense than my comment! :-). Many thanks
for the clarifications.
I would not mind a code example in this doc, but I guess that can come
later.
cheers,

Christophe

>

>> +

>>> +Here is a practical example:

>>> +

>>> +Let's look at DNS packets, these are identified by using UDP port 53,

>>> but each

>>> +UDP packet may run atop of IPv4 or IPv6, and in turn an IP packet might

>>> be

>>> +received as either multicast or unicast,

>>> +

>>> +Very simply, we can create these PMRs:

>>> +

>>> +PMR-L2 = match all multicast/broadcast packets based on DMAC address

>>> PMR_L3_IP4

>>> += match all IPv4 packets PMR_L3_IP6 = match all IPv6 packets PMR_L4_UDP

>>> = match

>>> +all UDP packets PMR_L4_53 = match all packets with dest port = 53.

>>> +

>>> +odp_cls_pmr_create(PMR_L2, port_cos, port_cos_mc);

>>> +odp_cls_pmr_create(PMR_L3_IP4, port_cos, port_cos_ip4_uc);

>>> +odp_cls_pmr_create(PMR_L3_IP6, port_cos, port_cos_ip6_uc);

>>> +

>>> +odp_cls_pmr_create(PMR_L3_IP4, port_cos_mc, port_cos_ip4_mc);

>>> +odp_cls_pmr_create(PMR_L3_IP6, port_cos_mc, port_cos_ip6_mc);

>>> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip4_uc, cos_udp4_uc);

>>> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip4_mc, cos_udp4_mc);

>>> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip6_uc, cos_udp6_uc);

>>> +odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip6_mc, cos_udp6_mc);

>>> +

>>> +odp_cls_pmr_create(PMR_L4_53, cos_udp4_uc, dns4_uc);

>>> +odp_cls_pmr_create(PMR_L4_53, cos_udp4_mc, dns4_mc);

>>> +odp_cls_pmr_create(PMR_L4_53, cos_udp6_uc, dns6_uc);

>>> +odp_cls_pmr_create(PMR_L4_53, cos_udp6_mc, dns6_mc);

>>>

>>

>> In the previous section, the root of the tree seemed to be "default_cos".

>> now it seems to be "default_cos". what is port_cos here?

>>

>

> Yes. port_cos and default_cos are the same. I will change everything to

> "default_cos" since I believe it is more easier to understand.

>

> Regards,

> Bala

>

>>

>> Thanks,

>> Christophe.

>>

>>> +

>>> +In this case, a packet may change CoS between 0 and 5 times, meaning

>>> that up to

>>> +5 PMRs may be applied in series, and the order

>>> +

>>> +Another interesting point is that an implementation will probably

>>> impose on a

>>> +limit of how many PMRs can be applied to a packet in series, so in the

>>> above

>>> +example, if an implementation limit on the number of consecutive

>>> classification

>>> +steps is 4, then all the DNS packets may only reach cos_udp?_?c set of

>>> vertices.

>>> --

>>> 1.9.1

>>>

>>> _______________________________________________

>>> lng-odp mailing list

>>> lng-odp@lists.linaro.org

>>> https://lists.linaro.org/mailman/listinfo/lng-odp

>>>

>>

>>

>
diff mbox

Patch

diff --git a/doc/users-guide/users-guide-cls.adoc b/doc/users-guide/users-guide-cls.adoc
new file mode 100644
index 0000000..3089f86
--- /dev/null
+++ b/doc/users-guide/users-guide-cls.adoc
@@ -0,0 +1,220 @@ 
+== Classification \(CLS)
+
+ODP is a framework for software-based packet forwarding/filtering applications,
+and the purpose of the Packet Classification API is to enable applications to
+program the platform hardware or software implementation to assist in
+prioritization, classification and scheduling of each packet, so that the
+software application can run faster, scale better and adhere to QoS
+requirements.
+
+The following API abstraction are not modelled after any existing product
+implementation, but is instead defined in terms of what a typical data-plane
+application may require from such a platform, without sacrificing simplicity and
+avoiding ambiguity. Certain terms that are being used within the context of
+existing products in relation to packet parsing and classification, such as
+access lists are avoided such that not to suggest any relationship
+between the abstraction used within this API and any particular manner in which
+they may be implemented in hardware.
+
+=== Functional Description
+
+Following is the functionality that is required of the classification API, and
+its underlying implementation. The details and order of the following paragraph
+is informative, and is only intended to help convey the functional scope of a
+classifier aznd provide context for the API. In reality, implementations may
+execute many of these steps concurrently, or in different order while
+maintaining the evident dependencies:
+
+1. Apply a set of classification rules to the header of an incoming packet,
+identify the header fields, e.g. ,ethertype, IP version, IP protocol, transport
+layer port numbers, IP DiffServ, VLAN id, 802.1p priority.
+
+2. Store these fields as packet meta data for application use, and for the
+remainder of parser operations. The odp_pktio is also stored as one of the meta
+data fields for subsequent use.
+
+3. Compute an odp_cos (Class of Service) value from a subset of supported fields
+from 1) above.
+
+4. Based on the odp_cos from 3) above, select the odp_queue through which the
+packet is delivered to the application.
+
+5. Validate the packet data integrity (checksums, FCS)  and correctness (e.g.,
+length fields) and store the validation result, along with optional error layer
+and type indicator, in packet meta data. Optionally, if a packet fails
+validation, override the odp_cos selection in step 3 to a class of service
+designated for errored packets.
+
+6. Based on the odp_cos from 3) above, select the odp_buffer_pool that should be
+used to acquire a buffer to store the packet data and meta data.
+
+7. Allocate a buffer from odp_buffer_pool selected in 6) above and logically[1]
+store the packet data and meta data to the allocated buffer, or in accordance
+with class-of-service drop policy and subject to pool buffer availability,
+optionally discard the packet.
+
+8. Enqueue the buffer into the odp_queue selected in 4) above.
+
+The above is an abstract description of the classifier functionality, and may be
+applied to a variety of applications in many different ways. The ultimate
+meaning of how this functionality applies to an application also depends on
+other ODP modules, so the above may not complete a full depiction. For instance,
+the exact meaning of priority, which is a per-queue attribute is influenced by
+the ODP scheduler semantics, and the system behavior under stress depends on the
+ODP buffer pool module behavior.
+
+For the sole purpose of illustrating the above abstract functionality, here is
+an example of a Layer-2 (IEEE 802.1D)  bridge application: Such a forwarding
+application that also adheres to IEEE 802.1p/q priority, which has 8 traffic
+priority levels, might create 8 odp_buffer_pool instances, one for each PCP
+priority level, and 8 odp_queue instances one per priority level. Incoming
+packets will be inspected for a VLAN header; the PCP field will be extracted,
+and used to select both the pool and the queue. Because each queue will be
+assigned a priority value, the packets with highest PCP values will be scheduled
+before any packet with a lower PCP value. Also, in a case of congestion, buffer
+pools for lower priority packets will be depleted earlier than the pools
+containing packets of the high priority, and hence the lower priority packets
+will be dropped (assuming that is the only flow control method that is supported
+in the platform) while higher priority packets will continue to be received into
+buffers and processed.
+
+=== Class of Service Creation and Binding
+
+To program the classifier, a class-of-service instance must be created, which
+will contain the packet filtering resources that it may require. All subsequent
+calls refer to one or more of these resources.
+
+Each class of service instance must be associated with a single queue or queue
+group, which will be the destination of all packets matching that particular
+filter. The queue assignment is implemented as a separate function call such
+that the queue may be modified at any time, without tearing down the filters
+that define the class of service. In other words, it is possible to change the
+destination queue for a class of service defined by its filters quickly and
+dynamically.
+
+Optionally, on platforms that support multiple packet buffer pools, each class
+of service may be assigned a different pool such that when buffers are exhausted
+for one class of service, other classes are not negatively impacted and continue
+to be processed.
+
+=== Default packet handling
+
+There SHOULD be one odp_cos assigned to each port with the  odp_pktio_default_cos_set()
+function,  which will function as the default class-of-service for all packets
+received from an ingress port, that do not match any of the filters defined
+subsequently. At minimum this default class-of-service MUST have a queue and a
+buffer pool assigned to it on platforms that support multiple packet buffer
+pools. Multiple odp_pktio instances (i.e., multiple ports) MAY each have their
+own default odp_cos, or MAY share a odp_cos with other ports, based on
+application requirements.
+
+Packet Classification
+
+For each odp_pktio port, the API allows the assignment of a class-of-service to
+a packet using one of  three methods:
+
+1. The packet may be assigned a specific class-of-service based on its Layer-2
+(802.1P/902.1Q VLAN tag) priority field. Since the standard field defines 8
+discrete priority levels, the API allows to assign an odp_cos to each of these
+priority levels with the odp_cos_with_l2_priority() function.
+
+2. Similarly, a class-of-service may be assigned using the Layer-3 (IP DiffServ)
+header field. The application supplies an array of odp_cos values that covers
+the entire range of the standard protocol header field, where array elements do
+not need to contain unique values. There is also a need to specify if Layer-3
+priority takes precedence over Layer-2 priority in a packet with both headers
+present.
+
+3. Additionally, the application may also program a number of pattern matching
+rules that assign a class-of-service for packets with header fields matching
+specified values. The field-matching rules take precedence over the previously
+described priority-based assignment of a class-of-service. Using these matching
+rules the application should be able for example to identify all packets
+containing VoIP traffic based on the protocol being UDP, and a specific
+destination or source port numbers, and appropriately assign these packets an
+class-of-service that maps to a higher priority queue, assuring voice packets a
+lower and bound latency.
+
+Packet meta data Elements
+
+Here are the specific information elements that SHOULD be stored within the
+packet meta data structure:
+
+* Protocol fields that are decoded and extracted by the parsing phase
+
+* The pool identifier that is selected for the packet
+
+* The ingress port identifier
+
+* The result of packet validation, including an indication of the type of error
+* detected, if any
+
+The ODP packet API module SHALL provide accessors for retrieving the above meta
+data fields from the container buffer in an implementation-independent manner.
+
+===  Example configuration
+
+CoS configuration can be best illustrated by drawing a tree, where each CoS is
+the vertex, and each link between any two vertices is a PMR. The root node for
+the tree is the default CoS which is attached with the pktio interface.  All of
+the CoS vertices can be final for some packets, if these packets do not match
+any of the links.
+
+Let us consider the below configuration
+
+odp_pktio_default_cos_set(odp_pktio_t pktio, odp_cos_t default_cos);
+
+pmr1 = odp_cls_pmr_create(pmr_match1, default_cos,  cos1);
+pmr2 = odp_cls_pmr_create(pmr_match2, default_cos,  cos2);
+pmr3 = odp_cls_pmr_create(pmr_match3, default_cos,  cos3);
+
+pmr11 = odp_cls_pmr_create(pmr_match11, cos1,  cos11);
+pmr12 = odp_cls_pmr_create(pmr_match12, cos1,  cos12);
+
+pmr21 = odp_cls_pmr_create(pmr_match11, cos2,  cos21);
+pmr31 = odp_cls_pmr_create(pmr_match11, cos3,  cos31);
+
+The above configuration DOES imply order - a packet that matches pmr_match1 will
+then be applied to pmr_match11 and pmr_match12, and as a result could terminate
+with either cost1, cos11, cos12. In this case the packet was subjected to two
+match attempts in total.
+
+The remaining two lines illustrate how a packet that matches pmr_match11 could
+end up wth either cos11, cos21 or cos31, depending on wether it matches
+pmr_march1, pmr_march2 or pmr_match3.
+
+Here is a practical example:
+
+Let's look at DNS packets, these are identified by using UDP port 53, but each
+UDP packet may run atop of IPv4 or IPv6, and in turn an IP packet might be
+received as either multicast or unicast,
+
+Very simply, we can create these PMRs:
+
+PMR-L2 = match all multicast/broadcast packets based on DMAC address PMR_L3_IP4
+= match all IPv4 packets PMR_L3_IP6 = match all IPv6 packets PMR_L4_UDP = match
+all UDP packets PMR_L4_53 = match all packets with dest port = 53.
+
+odp_cls_pmr_create(PMR_L2, port_cos, port_cos_mc);
+odp_cls_pmr_create(PMR_L3_IP4, port_cos, port_cos_ip4_uc);
+odp_cls_pmr_create(PMR_L3_IP6, port_cos, port_cos_ip6_uc);
+
+odp_cls_pmr_create(PMR_L3_IP4, port_cos_mc, port_cos_ip4_mc);
+odp_cls_pmr_create(PMR_L3_IP6, port_cos_mc, port_cos_ip6_mc);
+odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip4_uc, cos_udp4_uc);
+odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip4_mc, cos_udp4_mc);
+odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip6_uc, cos_udp6_uc);
+odp_cls_pmr_create(PMR_L4_UDP, port_cos_ip6_mc, cos_udp6_mc);
+
+odp_cls_pmr_create(PMR_L4_53, cos_udp4_uc, dns4_uc);
+odp_cls_pmr_create(PMR_L4_53, cos_udp4_mc, dns4_mc);
+odp_cls_pmr_create(PMR_L4_53, cos_udp6_uc, dns6_uc);
+odp_cls_pmr_create(PMR_L4_53, cos_udp6_mc, dns6_mc);
+
+In this case, a packet may change CoS between 0 and 5 times, meaning that up to
+5 PMRs may be applied in series, and the order
+
+Another interesting point is that an implementation will probably impose on a
+limit of how many PMRs can be applied to a packet in series, so in the above
+example, if an implementation limit on the number of consecutive classification
+steps is 4, then all the DNS packets may only reach cos_udp?_?c set of vertices.