-
Notifications
You must be signed in to change notification settings - Fork 707
VPP Introduction_To_N_tuple_Classifiers
- 1 The VPP Classifier Theory of Operation
- 2 Basic operation
- 3 Creating a classifier table
- 4 Creating a classifier session
A classifier is basically a collection of rules. At a certain level, the VPP classifier is just a dumb robot with a fairly simple control-plane API. Given an incoming packet, it searches an ordered list of (mask, match) tables. If the classifier finds a matching entry, it takes the indicated action. If not, it takes a last-resort action.
There is certain simplicity to that, and yet with some investment of time to learn how to program it effectively, you can create some powerful results in performance and scale.
We use the MMX-unit to match or hash 16 octets at a time. For hardware backward compatibility, the code does not [currently] use 256-bit(32-octet) vector instructions.
Effective use of the classifier centers around building table lists which "hit" as soon as practicable. In many cases, established sessions hit in the first table. In this mode of operation, the classifier easily processes multiple MPPS / core - even with millions of sessions in the data base. Searching 357 tables on a regular basis will neatly solve the halting problem.
The classifier mask-and-match operation proceeds as follows. Given a starting classifier table index, lay hands on the indicated mask vector. When building tables, we arrange for the mask to obey mmx-unit (16-octet) alignment.
We know that the first octet of packet data starts on a cache-line boundary. Further, it's reasonably likely that folks won't want to use the generalized classifier on the L2 header; preferring to decode the Ethertype manually. That scheme makes it easy to select among ip4 / ip6 / MPLS, etc. classifier table sets.
A no-vlan-tag L2 header is 14 octets long. A typical ipv4 header begins with the octets 0x4500: version=4, header_length=5, DSCP=0, ECN=0. If one doesn't intend to classify on (DSCP, ECN) - the typical case - we program the classifier to skip the first 16-octet vector.
To classify untagged ipv4 packets on source address, we program the classifier to skip one vector, and mask-and-match one vector.
The basic match-and-match operation looks like this:
switch (t->match_n_vectors)
{
case 1:
result = (data[0 + t->skip_n_vectors] & mask[0]) ^ key[0];
break;
case 2:
result = (data[0 + t->skip_n_vectors] & mask[0]) ^ key[0];
result |= (data[1 + t->skip_n_vectors] & mask[1]) ^ key[1];
break;
<etc>
}
result_mask = u32x4_zero_byte_mask (result);
if (result_mask == 0xffff)
return (v);
Net of setup, it costs a couple of clock cycles to mask-and-match 16 octets.
At the risk of belaboring an obvious point, the control-plane must pay attention to detail. When skipping one (or more) vectors, masks and matches must reflect that decision. See .../vnet/vnet/classify/vnet_classify.c:unformat_classify_[mask|match]. Note that vec_validate (xxx, 13) creates a 14-element vector.
To create a new classifier table via the control-plane API, send a "classify_add_del_table" message. The underlying action routine, vnet_classify_add_del_table(...), is located in .../vnet/vnet/classify/vnet_classify.c, and has the following prototype:
int vnet_classify_add_del_table (vnet_classify_main_t * cm,
u8 * mask,
u32 nbuckets,
u32 memory_size,
u32 skip,
u32 match,
u32 next_table_index,
u32 miss_next_index,
u32 * table_index,
int is_add)
Pass cm = &vnet_classify_main if calling this routine directly. Mask, skip(_n_vectors) and match(_n_vectors) are as described above. Mask need not be aligned, but it must be match*16 octets in length. To avoid having your head explode, be absolutely certain that only the bits you intend to match on are set.
The classifier uses thread-safe, no-reader-locking-required bounded-index extensible hashing. Nbuckets is the [fixed] size of the hash bucket vector. The algorithm works in constant time regardless of hash collisions, but wastes space when the bucket array is too small. A good rule of thumb: let nbuckets = approximate number of entries expected.
At a signficant cost in complexity, it would be possible to resize the bucket array dynamically. We have no plans to implement that function.
Each classifier table has its own clib mheap memory allocation arena. To pick the memory_size parameter, note that each classifier table entry needs 16*(1 + match_n_vectors) bytes. Within reason, aim a bit high. Clib mheap memory uses o/s level virtual memory - not wired or hugetlb memory - so it's best not to scrimp on size.
The "next_table_index" parameter is as described: the pool index in vnet_classify_main.tables of the next table to search. Code ~0 to indicate the end of the table list. 0 is a valid table index!
We often create classification tables in reverse order - last-table-searched to first-table-searched - so we can easily set this parameter. Of course, one can manually adjust the data structure after-the-fact.
Specific classifier client nodes - for example, .../vnet/vnet/classify/ip_classify.c - interpret the "miss_next_index" parameter as a vpp graph-node next index. When packet classification fails to produce a match, ip_classify_inline sends packets to the indicated disposition. A classifier application might program this parameter to send packets which don't match an existing session to a "first-sign-of-life, create-new-session" node.
Finally, the is_add parameter indicates whether to add or delete the indicated table. The delete case implicitly terminates all sessions with extreme prejudice by freeing the specified clib mheap.
To create a new classifier session via the control-plane API, send a "classify_add_del_session" message. The underlying action routine, vnet_classify_add_del_session(...), is located in .../vnet/vnet/classify/vnet_classify.c, and has the following prototype:
int vnet_classify_add_del_session (vnet_classify_main_t * cm,
u32 table_index,
u8 * match,
u32 hit_next_index,
u32 opaque_index,
i32 advance,
int is_add)
Pass cm = &vnet_classify_main if calling this routine directly. Table index specifies the table which receives the new session / contains the session to delete depending on is_add.
Match is the key for the indicated session. It need not be aligned, but it must be table->match_n_vectors*16 octets in length. As a courtesy, vnet_classify_add_del_session applies the table's mask to the stored key-value. In this way, one can create a session by passing unmasked (packet_data + offset) as the "match" parameter, and end up with unconfusing session keys.
Specific classifier client nodes - for example, .../vnet/vnet/classify/ip_classify.c - interpret the per-session hit_next_index parameter as a vpp graph-node next index. When packet classification produces a match, ip_classify_inline sends packets to the indicated disposition.
ip4/6_classify place the per-session opaque_index parameter into vnet_buffer(b)->l2_classify.opaque_index; a slight misnomer, but anyhow classifier applications can send session-hit packets to specific graph nodes, with useful values in buffer metadata. Depending on the required semantics, we send known-session traffic to a certain node, with e.g. a session pool index in buffer metadata. It's totally up to the control-plane and the specific use-case.
Finally, nodes such as ip4/6-classify apply the advance parameter as a [signed!] argument to vlib_buffer_advance(...); to "consume" a networking layer. Example: if we classify incoming tunneled IP packets by (inner) source/dest address and source/dest port, we might choose to decapsulate and reencapsulate the inner packet. In such a case, program the advance parameter to perform the tunnel decapsulation, and program next_index to send traffic to a node which uses the opaque_index to output traffic on a specific tunnel interface.
- VPP 2022 Make Test Use Case Poll
- VPP-AArch64
- VPP-ABF
- VPP Alternative Builds
- VPP API Concepts
- VPP API Versioning
- VPP-ApiChangeProcess
- VPP-ArtifactVersioning
- VPP-BIER
- VPP-Bihash
- VPP-BugReports
- VPP Build System Deep Dive
- VPP Build, Install, And Test Images
- VPP-BuildArtifactRetentionPolicy
- VPP-c2cpel
- VPP Code Walkthrough VoD
- VPP Code Walkthrough VoD Topic Index
- VPP Code Walkthrough VoDs
- VPP-CodeStyleConventions
- VPP-CodingTips
- VPP Command Line Arguments
- VPP Command Line Interface CLI Guide
- VPP-CommitMessages
- VPP-Committers-SMEs
- VPP-CommitterTasks-ApiFreeze
- VPP CommitterTasks Compare API Changes
- VPP-CommitterTasks-CutPointRelease
- VPP-CommitterTasks-CutRelease
- VPP-CommitterTasks-FinalReleaseCandidate
- VPP-CommitterTasks-PullThrottleBranch
- VPP-CommitterTasks-ReleasePlan
- VPP Configuration Tool
- VPP Configure An LW46 MAP E Terminator
- VPP Configure VPP As A Router Between Namespaces
- VPP Configure VPP TAP Interfaces For Container Routing
- VPP-CoreFileMismatch
- VPP-cpel
- VPP-cpeldump
- VPP-CurrentData
- VPP-DHCPKit
- VPP-DHCPv6
- VPP-DistributedOwnership
- VPP-Documentation
- VPP DPOs And Feature Arcs
- VPP EC2 Instance With SRIOV
- VPP-elog
- VPP-FAQ
- VPP Feature Arcs
- VPP-Features
- VPP-Features-IPv6
- VPP-FIB
- VPP-g2
- VPP Getting VPP 16.06
- VPP Getting VPP Release Binaries
- VPP-HA
- VPP-HostStack
- VPP-HostStack-BuiltinEchoClientServer
- VPP-HostStack-EchoClientServer
- VPP-HostStack-ExternalEchoClientServer
- VPP HostStack Hs Test
- VPP-HostStack-LDP-iperf
- VPP-HostStack-LDP-nginx
- VPP-HostStack-LDP-sshd
- VPP-HostStack-nginx
- VPP-HostStack-SessionLayerArchitecture
- VPP-HostStack-TestHttpServer
- VPP-HostStack-TestProxy
- VPP-HostStack-TLS
- VPP-HostStack-VCL
- VPP-HostStack-VclEchoClientServer
- VPP-Hotplug
- VPP How To Add A Tunnel Encapsulation
- VPP How To Build The Sample Plugin
- VPP How To Connect A PCI Interface To VPP
- VPP How To Create A VPP Binary Control Plane API
- VPP How To Deploy VPP In EC2 Instance And Use It To Connect Two Different VPCs
- VPP How To Optimize Performance %28System Tuning%29
- VPP How To Use The API Trace Tools
- VPP How To Use The C API
- VPP How To Use The Packet Generator And Packet Tracer
- VPP-Howtos
- VPP-index
- VPP Installing VPP Binaries From Packages
- VPP Interconnecting vRouters With VPP
- VPP Introduction To IP Adjacency
- VPP Introduction To N Tuple Classifiers
- VPP IP Adjacency Introduction
- VPP-IPFIX
- VPP-IPSec
- VPP IPSec And IKEv2
- VPP IPv6 SR VIRL Topology File
- VPP Java API
- VPP Java API Plugin Support
- VPP Jira Workflow
- VPP-Macswapplugin
- VPP-MakeTestFramework
- VPP-Meeting
- VPP-MFIB
- VPP Missing Prefetches
- VPP Modifying The Packet Processing Directed Graph
- VPP MPLS FIB
- VPP-NAT
- VPP Nataas Test
- VPP-OVN
- VPP Per Feature Notes
- VPP Performance Analysis Tools
- VPP-perftop
- VPP Progressive VPP Tutorial
- VPP Project Meeting Minutes
- VPP Pulling, Building, Running, Hacking And Pushing VPP Code
- VPP Pure L3 Between Namespaces With 32s
- VPP Pure L3 Container Networking
- VPP Pushing And Testing A Tag
- VPP Python API
- VPP-PythonVersionPolicy
- VPP-QuickTrexSetup
- VPP Random Hints And Kinks For KVM Usage
- VPP Release Plans Release Plan 16.09
- VPP Release Plans Release Plan 17.01
- VPP Release Plans Release Plan 17.04
- VPP Release Plans Release Plan 17.07
- VPP Release Plans Release Plan 17.10
- VPP Release Plans Release Plan 18.01
- VPP Release Plans Release Plan 18.04
- VPP Release Plans Release Plan 18.07
- VPP Release Plans Release Plan 18.10
- VPP Release Plans Release Plan 19.01
- VPP Release Plans Release Plan 19.04
- VPP Release Plans Release Plan 19.08
- VPP Release Plans Release Plan 20.01
- VPP Release Plans Release Plan 20.05
- VPP Release Plans Release Plan 20.09
- VPP Release Plans Release Plan 21.01
- VPP Release Plans Release Plan 21.06
- VPP Release Plans Release Plan 21.10
- VPP Release Plans Release Plan 22.02
- VPP Release Plans Release Plan 22.06
- VPP Release Plans Release Plan 22.10
- VPP Release Plans Release Plan 23.02
- VPP Release Plans Release Plan 23.06
- VPP Release Plans Release Plan 23.10
- VPP Release Plans Release Plan 24.02
- VPP Release Plans Release Plan 24.06
- VPP Release Plans Release Plan 24.10
- VPP Release Plans Release Plan 25.02
- VPP Release Plans Release Plan 25.06
- VPP Release Plans Release Plan 25.10
- VPP Release Plans Release Plan 26.02
- VPP Release Plans Release Plan 26.06
- VPP-RM
- VPP-SecurityGroups
- VPP Segment Routing For IPv6
- VPP Segment Routing For MPLS
- VPP Setting Up Your Dev Environment
- VPP-SNAT
- VPP Software Architecture
- VPP STN Testing
- VPP The VPP API
- VPP Training Events
- VPP-Troubleshooting
- VPP-Troubleshooting-BuildIssues
- VPP-Troubleshooting-Vagrant
- VPP Tutorial DPDK And MacSwap
- VPP Tutorial Routing And Switching
- VPP-Tutorials
- VPP Use VPP To Chain VMs Using Vhost User Interface
- VPP Use VPP To Connect VMs Using Vhost User Interface
- VPP Using mTCP User Mode TCP Stack With VPP
- VPP Using VPP As A VXLAN Tunnel Terminator
- VPP Using VPP In A Multi Thread Model
- VPP-VOM
- VPP VPP BFD Nexus
- VPP VPP Home Gateway
- VPP VPP WIKI DEPRECATED CONTENT
- VPP-VPPCommunicationsLibrary
- VPP-VPPConfig
- VPP What Is ODP4VPP
- VPP What Is VPP
- VPP Working Environments
- VPP Working With The 16.06 Throttle Branch