aboutsummaryrefslogtreecommitdiff
path: root/doc/users-guide/users-guide-cls.adoc
blob: 41badebed9f096ce42fd74e6ed05ceb366944c28 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
== 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 modeled 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 and 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 is a `odp_cos_t` 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.

=== Error packet handling

Error class of service is assigned to an ingress port using the function
`odp_pktio_error_cos_set()`. All the packets received with error from this
specific ingress port are assigned to this error class-of-service.
At minimum this error class-of-service must have a queue and a buffer pool
assigned to it. Multiple pktio instances (_i.e.,_ multiple ports) may each have
their own error class of service, or may share an error CoS with other ports,
based on application requirements.

=== Packet dropping

Each class of service has a `drop_policy` configured during creation. The
valid value are ODP_COS_DROP_POOL and ODP_COS_DROP_NEVER. If the `drop_policy`
is set to ODP_COS_DROP_POOL then the packets assigned to the CoS follows the
drop policy of the associated pool _i.e.,_ depending on the Random Early Discard
or any other configuration of the pool the packet might get dropped. If the
`drop_policy` is set to ODP_COS_DROP_NEVER then the Random Early Discard of the
pool is ignored.

During creation of the class of service if the pool or queue is set as INVALID
using ODP_POOL_INVALID or ODP_QUEUE_INVALID field then any packet assigned to the specific CoS are dropped.

=== Packet Classification

For each odp_pktio port, the API allows the assignment of a class-of-service to
a packet. Application can program a number of pattern matching rules that
assign a class-of-service for packets with header fields matching specified
values. 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 a 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 are 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 provides 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 link PMRs.

.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 with either cos11, cos21 or cos31, depending on whether it matches
pmr_march1, pmr_march2 or pmr_match3.

=== 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 +

[source,c]
----
odp_cls_pmr_create(PMR_L2, default_cos, default_cos_mc);
odp_cls_pmr_create(PMR_L3_IP4, default_cos, default_cos_ip4_uc);
odp_cls_pmr_create(PMR_L3_IP6, default_cos, default_cos_ip6_uc);

odp_cls_pmr_create(PMR_L3_IP4, default_cos_mc, default_cos_ip4_mc);
odp_cls_pmr_create(PMR_L3_IP6, default_cos_mc, default_cos_ip6_mc);
odp_cls_pmr_create(PMR_L4_UDP, default_cos_ip4_uc, cos_udp4_uc);
odp_cls_pmr_create(PMR_L4_UDP, default_cos_ip4_mc, cos_udp4_mc);
odp_cls_pmr_create(PMR_L4_UDP, default_cos_ip6_uc, cos_udp6_uc);
odp_cls_pmr_create(PMR_L4_UDP, default_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.