Having discussed about the various operations that can be performed on filters, let us now discuss the different types of filters supported. Filters can be classified into generic filters and specific filters based on the scope of the packets their instances can classify.
Generic filters need only one instance of the filter per queuing discipline to classify packets for all classes. The route classifier is an example of a generic classifier. The route_classify function in net/sched/cls_api.c takes the class ID from the packet, where it was stored by another entity in the protocol stack. As far as the route classifier is concerned, this entity is the routing functionality in net/ipv4/route.c. The rt_set_nexthop function in this file, which is used to set the next hop for a particular destination address, also sets the class ID for the packets sent to this destination. This can be set from the user space using the ip tool, which will be discussed later in this document. Generic filters are explained in Figure 6.
Specific filters need one or more instances of a filter or its internal elements per class to identify packets belonging to this class. Multiple instances of a filter (or its elements) on the same filter list (which may potentially map to the same class) are distinguished based on the internal IDs. Since the specific filters have at-least one instance of the filter per class, they can store the internal ID of the class in the tcf_proto structure, thereby ensuring a fast lookup of the class. It is here that the specific filters score over the generic filters. In the case of generic filters, the tcf_result is returned with the class field (that is, the internal class ID) set to zero. The queuing discipline is responsible for doing another lookup to determine the class ID (as shown in Figure 6). Specific filters are described in Figure 7.
This concludes the details involved in the implementation of filters. Before discussing the user level tools available to make use of the kernel features, let us take a brief look at the interface between the kernel and the user space.