Hashing Filters
Hashing Filters
Why hashing?
1 computer IP = 1 "tc filter" rule OK for few tens of rules, slow for hundreds or thousands of rules! We can create new tc filter hashtables to optimize the rules matching. This way we can match (e.g.) 65535 IP addresses in only 2 or 3 steps. Using this technique, we can move the bottleneck from U32 filter to other parts of Linux kernel.
1 2
3 4
Dequeue
pfifo is default qdisc for HTB classes. It is invisible for tc commands. Class (its qdisc) does not enqueue packets until some filter or qdisc parameter default instructs to do so
Dequeue
class 1:1
...
class 1:$COUNT
...
Dequeue Qdisc pfifo Qdisc pfifo Qdisc 1:1 Class classidpfifo Qdisc 1:1 Class classidpfifo Class classid 1:1 Class classid 1:$COUNT
Filter $COUNT
Enqueue operation:
In general, within classful qdisc, the packet enqueue point is searched by traversing the class hierarchy from the qdisc root and consulting filters attached to each class. The CBQ qdisc is an example of this approach. However: within HTB qdisc, the class hierarchy is not used during the enqueue operation !!! The reason is that HTB does not allow filters to be attached to the classes the filters can be attached only to the qdisc root (=the HTB qdisc) In shallow class trees (e.g., depth=2), attaching filters to individual classes brings almost no performance improvement the only approach for good performance is using the U32 filter hash tables attached to the root qdisc. Therefore, we do not have to think about the class hierarchy function during the enqueue operation
Dequeue operation
The class hierarchy plays its main role in the dequeue() operation:
The dequeue() operation is called by kernel on the root qdisc, which calls dequeue() on all its children classes, each child then calls dequeue on all its children until all leafs are reached. the classes share the bandwidth (in HTB, bandwidth is represented by tokens) in a way that e.g. they can borrow unused bandwidth (tokens) from their siblings (=classes with the same parent in the class hierarchy)
This is not used here in our example, we have default=0 (1:0 is non-existent class)
class 1:1
De qu eu e
Dequeue
Enqueue
Enqueue
class 1:2
class 1:3
class 1:4
...
class
1:$COUNT Dequeue
...
Filter $COUNT
Note: the filters can instruct packets to enqueue into any class, not just into leaf classes as shown in this simple example!
Intel Celeron, 2.5 GHz, i865, 2x INTEL PRO/1000 GT (PCI 32bit, 33/66MHz) Linux 2.6.17
Througput vs. number of rules: throughput drops down from 400 rules
Zvislost routovacho vkonu na potu QoS pravidel (OS:Debian, HW: Router A)
110
CPU load during max. throughput vs. number of rules: 600 rules=100% CPU load
Zvislost vyten CPU na potu QoS pravidel (OS:Debian, HW: Router A)
400 390 Routovac vkon (Mbps) 380 370 360 350 340 330 320 310 300 0 200 400 600 800 1000 Poet QoS pravidel (Testovan parametr: Destination IP) Vyten CPU (%)
100 90 80 70 60 50 40 30 0 200 400 600 800 Poet QoS pravidel (Testovan parametr: Destination IP)
Intel Celeron, 2.5 GHz, i865, 2x INTEL PRO/1000 GT (PCI 32bit, 33/66MHz) Mikrotik 2.9.27 (Linux 2.4??) Througput vs. number of rules: CPU load vs. number of rules:
Zvislost routovacho vkonu na potu QoS pravidel (OS:Mikrotik, HW: Router A)
110
400 380 Routovac vkon (Mbps) 360 340 320 300 280 260 240 220 200 0 100 200 300 400 500 600 700 800 Poet QoS pravidel (Testovan parametr: Destination IP) 50 0 200 400 600 800 Poet QoS pravidel (Testovan parametr: Destination IP) Vyten CPU (%) 90 80 70 60 100
Routerboard RB532 Mikrotik 2.9.27 Router througput vs. number of rules: (notice the strange peak...)
Zvislost routovacho vkonu na potu QoS pravidel (OS:Mikrotik, HW: Router C)
30
25
20
15
10
5 0 50 100 150 200 Poet QoS pravidel (Testovan parametr: Destination IP)
Each filter priority creates an individual chain of rules. The chains are matched sequentially (highest priority chain first, lowest priority chain as the last one)
U32 is one of the few filters available in tc (the others are fw, rsvp, route and tcindex). U32 is the most advanced one and has very few documentation available, so it is worthy to dig deep inside Key handle range is 0 - 0xF FFFF #define TC_U32_KEY(h) ((h)&0xFFFFF) Hash table ID range is 0x000 00000 0xFFF 00000, from user point of view 0-0xFFF (=we can create 4095 hash tables) #define TC_U32_HTID(h) ((h)&0xFFF00000) #define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20)
Structures in net/sched/cls_u32.c
struct tcf_proto
struct tc_u_hnode *root
struct tc_u_hnode
struct tc_u_hnode *next; u32 handle, prio; struct tc_u_common *tp_c; int refcnt; unsigned divisor; struct tc_u_knode *ht[1];
References:
2.http://dcn.ssu.ac.kr/~softgear/prog_sw_report_summer_9
6.http://feela.network.cz/ltc.html
The tc filter uses default hash table with ID=800, which has 256 buckets A hash function is used to map a packet on to an index (0-255) into the hash table:
Packet hashing_function() Default tc filter hash table Bucket 0 Bucket 1 Bucket 2 Bucket 253 Bucket 254 Bucket 255
Unfortunatelly, we can't make the hash table bigger. But we can create new hashtables !!!
References