1 /*
2 * test/test-complex-HTB-with-hash-filters.c Add HTB qdisc, HTB classes and creates some hash filters
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
7 * of the License.
8 *
9 * Copyright (c) 2011 Adrian Ban <adrian.ban@mantech.ro>
10 */
11
12 #include <netlink/route/link.h>
13 #include <netlink/route/tc.h>
14 #include <netlink/route/qdisc.h>
15 #include <netlink/route/qdisc/htb.h>
16 #include <netlink/route/qdisc/sfq.h>
17 #include <netlink/route/cls/u32.h>
18 #include <netlink/route/classifier.h>
19 #include <netlink/route/class.h>
20 #include <linux/if_ether.h>
21 #include <linux/pkt_cls.h>
22
23 #include <netlink/attr.h>
24 //#include "include/rtnl_u32.h"
25
26 #include <stdio.h>
27 #include <string.h>
28 //#include "include/rtnl_u32_addon.h"
29
30 #include <linux/netlink.h>
31
32 #define TC_HANDLE(maj, min) (TC_H_MAJ((maj) << 16) | TC_H_MIN(min))
33
34 /* some functions are copied from iproute-tc tool */
get_u32(__u32 * val,const char * arg,int base)35 static int get_u32(__u32 *val, const char *arg, int base)
36 {
37 unsigned long res;
38 char *ptr;
39
40 if (!arg || !*arg)
41 return -1;
42 res = strtoul(arg, &ptr, base);
43 if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
44 return -1;
45 *val = res;
46 return 0;
47 }
48
get_u32_handle(__u32 * handle,const char * str)49 static int get_u32_handle(__u32 *handle, const char *str)
50 {
51 __u32 htid=0, hash=0, nodeid=0;
52 char *tmp = strchr(str, ':');
53
54 if (tmp == NULL) {
55 if (memcmp("0x", str, 2) == 0)
56 return get_u32(handle, str, 16);
57 return -1;
58 }
59 htid = strtoul(str, &tmp, 16);
60 if (tmp == str && *str != ':' && *str != 0)
61 return -1;
62 if (htid>=0x1000)
63 return -1;
64 if (*tmp) {
65 str = tmp+1;
66 hash = strtoul(str, &tmp, 16);
67 if (tmp == str && *str != ':' && *str != 0)
68 return -1;
69 if (hash>=0x100)
70 return -1;
71 if (*tmp) {
72 str = tmp+1;
73 nodeid = strtoul(str, &tmp, 16);
74 if (tmp == str && *str != 0)
75 return -1;
76 if (nodeid>=0x1000)
77 return -1;
78 }
79 }
80 *handle = (htid<<20)|(hash<<12)|nodeid;
81 return 0;
82 }
83
get_u32_parse_handle(const char * cHandle)84 static uint32_t get_u32_parse_handle(const char *cHandle)
85 {
86 uint32_t handle=0;
87
88 if(get_u32_handle(&handle, cHandle)) {
89 printf ("Illegal \"ht\"\n");
90 return -1;
91 }
92
93 if (handle && TC_U32_NODE(handle)) {
94 printf("\"link\" must be a hash table.\n");
95 return -1;
96 }
97 return handle;
98 }
99
get_tc_classid(__u32 * h,const char * str)100 static int get_tc_classid(__u32 *h, const char *str)
101 {
102 __u32 maj, min;
103 char *p;
104
105 maj = TC_H_ROOT;
106 if (strcmp(str, "root") == 0)
107 goto ok;
108 maj = TC_H_UNSPEC;
109 if (strcmp(str, "none") == 0)
110 goto ok;
111 maj = strtoul(str, &p, 16);
112 if (p == str) {
113 maj = 0;
114 if (*p != ':')
115 return -1;
116 }
117 if (*p == ':') {
118 if (maj >= (1<<16))
119 return -1;
120 maj <<= 16;
121 str = p+1;
122 min = strtoul(str, &p, 16);
123 if (*p != 0)
124 return -1;
125 if (min >= (1<<16))
126 return -1;
127 maj |= min;
128 } else if (*p != 0)
129 return -1;
130
131 ok:
132 *h = maj;
133 return 0;
134 }
135
136 /*
137 * Function that adds a new filter and attach it to a hash table
138 *
139 */
u32_add_filter_on_ht(struct nl_sock * sock,struct rtnl_link * rtnlLink,uint32_t prio,uint32_t keyval,uint32_t keymask,int keyoff,int keyoffmask,uint32_t htid,uint32_t classid)140 static int u32_add_filter_on_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio,
141 uint32_t keyval, uint32_t keymask, int keyoff, int keyoffmask,
142 uint32_t htid, uint32_t classid
143 )
144 {
145 struct rtnl_cls *cls;
146 int err;
147
148 //printf("Key Val : 0x%x\n", keyval);
149 //printf("Key Mask : 0x%x\n", keymask);
150
151 cls=rtnl_cls_alloc();
152 if (!(cls)) {
153 printf("Can not allocate classifier\n");
154 nl_socket_free(sock);
155 exit(1);
156 }
157
158 rtnl_tc_set_link(TC_CAST(cls), rtnlLink);
159
160 if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) {
161 printf("Can not set classifier as u32\n");
162 return 1;
163 }
164
165 rtnl_cls_set_prio(cls, prio);
166 rtnl_cls_set_protocol(cls, ETH_P_IP);
167
168 rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0));
169
170 rtnl_u32_set_hashtable(cls, htid);
171
172 rtnl_u32_add_key_uint32(cls, keyval, keymask, keyoff, keyoffmask); /* 10.0.0.0/8 */
173
174 rtnl_u32_set_classid(cls, classid);
175
176 rtnl_u32_set_cls_terminal(cls);
177
178 if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) {
179 printf("Can not add classifier: %s\n", nl_geterror(err));
180 return -1;
181 }
182 rtnl_cls_put(cls);
183 return 0;
184
185 }
186
187 /*
188 * Function that adds a new filter and attach it to a hash table
189 * and set next hash table link with hash mask
190 *
191 */
u32_add_filter_on_ht_with_hashmask(struct nl_sock * sock,struct rtnl_link * rtnlLink,uint32_t prio,uint32_t keyval,uint32_t keymask,int keyoff,int keyoffmask,uint32_t htid,uint32_t htlink,uint32_t hmask,uint32_t hoffset)192 static int u32_add_filter_on_ht_with_hashmask(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio,
193 uint32_t keyval, uint32_t keymask, int keyoff, int keyoffmask,
194 uint32_t htid, uint32_t htlink, uint32_t hmask, uint32_t hoffset
195 )
196 {
197 struct rtnl_cls *cls;
198 int err;
199
200 //printf("Key Val : 0x%x\n", keyval);
201 //printf("Key Mask : 0x%x\n", keymask);
202
203 cls=rtnl_cls_alloc();
204 if (!(cls)) {
205 printf("Can not allocate classifier\n");
206 nl_socket_free(sock);
207 exit(1);
208 }
209
210 rtnl_tc_set_link(TC_CAST(cls), rtnlLink);
211
212 if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) {
213 printf("Can not set classifier as u32\n");
214 return 1;
215 }
216
217 rtnl_cls_set_prio(cls, prio);
218 rtnl_cls_set_protocol(cls, ETH_P_IP);
219
220 rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0));
221
222 if (htid)
223 rtnl_u32_set_hashtable(cls, htid);
224
225 rtnl_u32_add_key_uint32(cls, keyval, keymask, keyoff, keyoffmask);
226
227 rtnl_u32_set_hashmask(cls, hmask, hoffset);
228
229 rtnl_u32_set_link(cls, htlink);
230
231
232 if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) {
233 printf("Can not add classifier: %s\n", nl_geterror(err));
234 return -1;
235 }
236 rtnl_cls_put(cls);
237 return 0;
238 }
239
240 /*
241 * function that creates a new hash table
242 */
u32_add_ht(struct nl_sock * sock,struct rtnl_link * rtnlLink,uint32_t prio,uint32_t htid,uint32_t divisor)243 static int u32_add_ht(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t prio, uint32_t htid, uint32_t divisor)
244 {
245
246 int err;
247 struct rtnl_cls *cls;
248
249 cls=rtnl_cls_alloc();
250 if (!(cls)) {
251 printf("Can not allocate classifier\n");
252 nl_socket_free(sock);
253 exit(1);
254 }
255
256 rtnl_tc_set_link(TC_CAST(cls), rtnlLink);
257
258 if ((err = rtnl_tc_set_kind(TC_CAST(cls), "u32"))) {
259 printf("Can not set classifier as u32\n");
260 return 1;
261 }
262
263 rtnl_cls_set_prio(cls, prio);
264 rtnl_cls_set_protocol(cls, ETH_P_IP);
265 rtnl_tc_set_parent(TC_CAST(cls), TC_HANDLE(1, 0));
266
267 rtnl_u32_set_handle(cls, htid, 0x0, 0x0);
268 //printf("htid: 0x%X\n", htid);
269 rtnl_u32_set_divisor(cls, divisor);
270
271 if ((err = rtnl_cls_add(sock, cls, NLM_F_CREATE))) {
272 printf("Can not add classifier: %s\n", nl_geterror(err));
273 return -1;
274 }
275 rtnl_cls_put(cls);
276 return 0;
277 }
278
279 /*
280 * function that adds a new HTB qdisc and set the default class for unclassified traffic
281 */
qdisc_add_HTB(struct nl_sock * sock,struct rtnl_link * rtnlLink,uint32_t defaultClass)282 static int qdisc_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink, uint32_t defaultClass)
283 {
284
285 struct rtnl_qdisc *qdisc;
286 int err;
287
288 /* Allocation of a qdisc object */
289 if (!(qdisc = rtnl_qdisc_alloc())) {
290 printf("Can not allocate Qdisc\n");
291 return -1;
292 }
293
294 //rtnl_tc_set_ifindex(TC_CAST(qdisc), master_index);
295 rtnl_tc_set_link(TC_CAST(qdisc), rtnlLink);
296 rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT);
297
298 //delete the qdisc
299 //printf("Delete current qdisc\n");
300 rtnl_qdisc_delete(sock, qdisc);
301 //rtnl_qdisc_put(qdisc);
302
303 //add a HTB qdisc
304 //printf("Add a new HTB qdisc\n");
305 rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(1,0));
306
307 if ((err = rtnl_tc_set_kind(TC_CAST(qdisc), "htb"))) {
308 printf("Can not allocate HTB\n");
309 return -1;
310 }
311
312 /* Set default class for unclassified traffic */
313 //printf("Set default class for unclassified traffic\n");
314 rtnl_htb_set_defcls(qdisc, TC_HANDLE(1, defaultClass));
315 rtnl_htb_set_rate2quantum(qdisc, 1);
316
317 /* Submit request to kernel and wait for response */
318 if ((err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE))) {
319 printf("Can not allocate HTB Qdisc\n");
320 return -1;
321 }
322
323 /* Return the qdisc object to free memory resources */
324 rtnl_qdisc_put(qdisc);
325
326 return 0;
327 }
328
329 /*
330 * function that adds a new HTB class and set its parameters
331 */
class_add_HTB(struct nl_sock * sock,struct rtnl_link * rtnlLink,uint32_t parentMaj,uint32_t parentMin,uint32_t childMaj,uint32_t childMin,uint64_t rate,uint64_t ceil,uint32_t burst,uint32_t cburst,uint32_t prio)332 static int class_add_HTB(struct nl_sock *sock, struct rtnl_link *rtnlLink,
333 uint32_t parentMaj, uint32_t parentMin,
334 uint32_t childMaj, uint32_t childMin,
335 uint64_t rate, uint64_t ceil,
336 uint32_t burst, uint32_t cburst,
337 uint32_t prio
338 )
339 {
340 int err;
341 struct rtnl_class *class;
342 //struct rtnl_class *class = (struct rtnl_class *) tc;
343
344 //create a HTB class
345 //class = (struct rtnl_class *)rtnl_class_alloc();
346 if (!(class = rtnl_class_alloc())) {
347 printf("Can not allocate class object\n");
348 return 1;
349 }
350 //
351 rtnl_tc_set_link(TC_CAST(class), rtnlLink);
352 //add a HTB qdisc
353 //printf("Add a new HTB class with 0x%X:0x%X on parent 0x%X:0x%X\n", childMaj, childMin, parentMaj, parentMin);
354 rtnl_tc_set_parent(TC_CAST(class), TC_HANDLE(parentMaj, parentMin));
355 rtnl_tc_set_handle(TC_CAST(class), TC_HANDLE(childMaj, childMin));
356
357 if ((err = rtnl_tc_set_kind(TC_CAST(class), "htb"))) {
358 printf("Can not set HTB to class\n");
359 return 1;
360 }
361
362 //printf("set HTB class prio to %u\n", prio);
363 rtnl_htb_set_prio((struct rtnl_class *)class, prio);
364
365 if (rate) {
366 //rate=rate/8;
367 rtnl_htb_set_rate(class, rate);
368 }
369 if (ceil) {
370 //ceil=ceil/8;
371 rtnl_htb_set_ceil(class, ceil);
372 }
373
374 if (burst) {
375 //printf ("Class HTB: set rate burst: %u\n", burst);
376 rtnl_htb_set_rbuffer(class, burst);
377 }
378 if (cburst) {
379 //printf ("Class HTB: set rate cburst: %u\n", cburst);
380 rtnl_htb_set_cbuffer(class, cburst);
381 }
382 /* Submit request to kernel and wait for response */
383 if ((err = rtnl_class_add(sock, class, NLM_F_CREATE))) {
384 printf("Can not allocate HTB Qdisc\n");
385 return 1;
386 }
387 rtnl_class_put(class);
388 return 0;
389 }
390
391 /*
392 * function that adds a HTB root class and set its parameters
393 */
class_add_HTB_root(struct nl_sock * sock,struct rtnl_link * rtnlLink,uint64_t rate,uint64_t ceil,uint32_t burst,uint32_t cburst)394 static int class_add_HTB_root(struct nl_sock *sock, struct rtnl_link *rtnlLink,
395 uint64_t rate, uint64_t ceil,
396 uint32_t burst, uint32_t cburst
397 )
398 {
399 int err;
400 struct rtnl_class *class;
401
402 //create a HTB class
403 class = (struct rtnl_class *)rtnl_class_alloc();
404 //class = rtnl_class_alloc();
405 if (!class) {
406 printf("Can not allocate class object\n");
407 return 1;
408 }
409 //
410 rtnl_tc_set_link(TC_CAST(class), rtnlLink);
411 rtnl_tc_set_parent(TC_CAST(class), TC_H_ROOT);
412 //add a HTB class
413 //printf("Add a new HTB ROOT class\n");
414 rtnl_tc_set_handle(TC_CAST(class), 1);
415
416 if ((err = rtnl_tc_set_kind(TC_CAST(class), "htb"))) {
417 printf("Can not set HTB to class\n");
418 return 1;
419 }
420
421 if (rate) {
422 //rate=rate/8;
423 rtnl_htb_set_rate(class, rate);
424 }
425 if (ceil) {
426 //ceil=ceil/8;
427 rtnl_htb_set_ceil(class, ceil);
428 }
429
430 if (burst) {
431 rtnl_htb_set_rbuffer(class, burst);
432 }
433 if (cburst) {
434 rtnl_htb_set_cbuffer(class, cburst);
435 }
436
437 /* Submit request to kernel and wait for response */
438 if ((err = rtnl_class_add(sock, class, NLM_F_CREATE))) {
439 printf("Can not allocate HTB Qdisc\n");
440 return 1;
441 }
442 rtnl_class_put(class);
443 return 0;
444 }
445
446 /*
447 * function that adds a new SFQ qdisc as a leaf for a HTB class
448 */
qdisc_add_SFQ_leaf(struct nl_sock * sock,struct rtnl_link * rtnlLink,uint32_t parentMaj,uint32_t parentMin,int quantum,int limit,int perturb)449 static int qdisc_add_SFQ_leaf(struct nl_sock *sock, struct rtnl_link *rtnlLink,
450 uint32_t parentMaj, uint32_t parentMin,
451 int quantum, int limit, int perturb
452 )
453 {
454 int err;
455 struct rtnl_qdisc *qdisc;
456
457 if (!(qdisc = rtnl_qdisc_alloc())) {
458 printf("Can not allocate qdisc object\n");
459 return 1;
460 }
461 rtnl_tc_set_link(TC_CAST(qdisc), rtnlLink);
462 rtnl_tc_set_parent(TC_CAST(qdisc), TC_HANDLE(parentMaj, parentMin));
463
464 rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(parentMin,0));
465
466 if ((err = rtnl_tc_set_kind(TC_CAST(qdisc), "sfq"))) {
467 printf("Can not set SQF class\n");
468 return 1;
469 }
470
471 if(quantum) {
472 rtnl_sfq_set_quantum(qdisc, quantum);
473 } else {
474 rtnl_sfq_set_quantum(qdisc, 16000); // tc default value
475 }
476 if(limit) {
477 rtnl_sfq_set_limit(qdisc, limit); // default is 127
478 }
479 if(perturb) {
480 rtnl_sfq_set_perturb(qdisc, perturb); // default never perturb the hash
481 }
482
483 /* Submit request to kernel and wait for response */
484 if ((err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE))) {
485 printf("Can not allocate SFQ qdisc\n");
486 return -1;
487 }
488
489 /* Return the qdisc object to free memory resources */
490 rtnl_qdisc_put(qdisc);
491 return 0;
492 }
493
494
495
496
main()497 int main() {
498
499 struct nl_sock *sock;
500 struct rtnl_link *link;
501
502 //struct rtnl_qdisc *qdisc;
503 //struct rtnl_class *class;
504 //struct rtnl_cls *cls;
505
506 uint32_t ht, htlink, htid, direction, classid;
507 //uint32_t hash, hashmask, nodeid, divisor, handle;
508 //struct rtnl_u32 *f_u32;
509 char chashlink[16]="";
510
511 //uint64_t drops, qlen;
512
513 //int master_index;
514 int err;
515
516 //uint64_t rate=0, ceil=0;
517
518 struct nl_cache *link_cache;
519
520 uint32_t i;
521
522 if (!(sock = nl_socket_alloc())) {
523 printf("Unable to allocate netlink socket\n");
524 exit(1);
525 }
526
527 if ((err = nl_connect(sock, NETLINK_ROUTE)) < 0 ) {
528 printf("Nu s-a putut conecta la NETLINK!\n");
529 nl_socket_free(sock);
530 exit(1);
531 }
532
533
534 if ((err = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache)) < 0) {
535 printf("Unable to allocate link cache: %s\n",
536 nl_geterror(err));
537 nl_socket_free(sock);
538 exit(1);
539 }
540
541 /* lookup interface index of eth0 */
542 if (!(link = rtnl_link_get_by_name(link_cache, "imq0"))) {
543 /* error */
544 printf("Interface not found\n");
545 nl_socket_free(sock);
546 exit(1);
547 }
548
549 err=qdisc_add_HTB(sock, link, 0xffff);
550 //drops = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_DROPS);
551
552 //printf("Add ROOT HTB class\n");
553 err=class_add_HTB_root(sock, link, 12500000, 12500000, 25000, 25000);
554 err=class_add_HTB(sock, link, 1, 0, 1, 0xffff, 1250000, 12500000, 25000, 25000, 5);
555 err=qdisc_add_SFQ_leaf(sock, link, 1, 0xffff, 16000, 0, 10);
556 err=class_add_HTB(sock, link, 1, 1, 1, 0x5, 2000000, 2000000, 25000, 25000, 5);
557 err=qdisc_add_SFQ_leaf(sock, link, 1, 0x5, 16000, 0, 10);
558 err=class_add_HTB(sock, link, 1, 1, 1, 0x6, 1000000, 1000000, 25000, 25000, 5);
559 err=qdisc_add_SFQ_leaf(sock, link, 1, 0x6, 16000, 0, 10);
560 //err=class_add_HTB(sock, link, 1, 0, 1, 0x7, 1024000, 100000000, 5);
561 //err=class_add_HTB(sock, link, 1, 0, 1, 0x8, 2048000, 100000000, 5);
562 //err=class_add_HTB(sock, link, 1, 0, 1, 0x9, 4096000, 100000000, 5);
563 //err=class_add_HTB(sock, link, 1, 0, 1, 0xa, 8192000, 100000000, 5);
564
565 //printf("Add main hash table\n");
566
567 /* create u32 first hash filter table
568 *
569 */
570 /* formula calcul handle:
571 * uint32_t handle = (htid << 20) | (hash << 12) | nodeid;
572 */
573
574 /*
575 * Upper limit of number of hash tables: 4096 (0xFFF)
576 * Number of hashes in a table: 256 values (0xFF)
577 *
578 */
579
580 /* using 256 values for hash table
581 * each entry in hash table match a byte from IP address specified later by a hash key
582 */
583
584 for (i = 1; i <= 0xf; i++)
585 u32_add_ht(sock, link, 1, i, 256);
586
587 /*
588 * attach a u32 filter to the first hash
589 * that redirects all traffic and make a hash key
590 * from the fist byte of the IP address
591 *
592 */
593
594 //divisor=0x0; // unused here
595 //handle = 0x0; // unused here
596 //hash = 0x0; // unused here
597 //htid = 0x0; // unused here
598 //nodeid = 0x0; // unused here
599
600 // direction = 12 -> source IP
601 // direction = 16 -> destination IP
602 direction = 16;
603
604 /*
605 * which hash table will use
606 * in our case is hash table no 1 defined previous
607 *
608 * There are 2 posibilities to set the the hash table:
609 * 1. Using function get_u32_handle and sent a string in
610 * format 10: where 10 is number of the hash table
611 * 2. Create your own value in format: 0xa00000
612 *
613 */
614 strcpy(chashlink, "1:");
615 //printf("Hash Link: %s\n", chashlink);
616 //chashlink=malloc(sizeof(char) *
617 htlink = 0x0; // is used by get_u32_handle to return the correct value of hash table (link)
618
619 if(get_u32_handle(&htlink, chashlink)) {
620 printf ("Illegal \"link\"");
621 nl_socket_free(sock);
622 exit(1);
623 }
624 //printf ("hash link : 0x%X\n", htlink);
625 //printf ("hash link test : %u\n", (htlink && TC_U32_NODE(htlink)));
626
627 if (htlink && TC_U32_NODE(htlink)) {
628 printf("\"link\" must be a hash table.\n");
629 nl_socket_free(sock);
630 exit(1);
631 }
632 /* the hash mask will hit the hash table (link) no 1: in our case
633 */
634
635 /* set the hash key mask */
636 //hashmask = 0xFF000000UL; // the mask that is used to match the hash in specific table, in our case for example 1:a with mean the first byte which is 10 in hash table 1
637
638 /* Here we add a hash filter which match the first byte (see the hashmask value)
639 * of the source IP (offset 12 in the packet header)
640 * You can use also offset 16 to match the destination IP
641 */
642
643 /*
644 * Also we need a filter to match our rule
645 * This mean that we will put a 0.0.0.0/0 filter in our first rule
646 * that match the offset 12 (source IP)
647 * Also you can put offset 16 to match the destination IP
648 */
649
650 u32_add_filter_on_ht_with_hashmask(sock, link, 1,
651 0x0, 0x0, direction, 0,
652 0, htlink, 0xff000000, direction);
653
654 /*
655 * For each first byte that we need to match we will create a new hash table
656 * For example: you have those clases: 10.0.0.0/24 and 172.16.0.0/23
657 * For byte 10 and byte 172 will create a separate hash table that will match the second
658 * byte from each class.
659 *
660 */
661
662
663 // Create a new hash table with prio 1, id 2 and 256 entries
664 // u32_CreateNewHashTable(sock, link, 1, 2, 256);
665 // Create a new hash table with prio 1, id 3 and 256 entries
666 // u32_CreateNewHashTable(sock, link, 1, 3, 256);
667 // u32_CreateNewHashTable(sock, link, 1, 4, 256);
668 // u32_CreateNewHashTable(sock, link, 1, 5, 256);
669
670 /*
671 * Now we will create other filter under (ATENTION) our first hash table (link) 1:
672 * Previous rule redirects the trafic according the hash mask to hash table (link) no 1:
673 * Here we will match the hash tables from 1:0 to 1:ff. Under each hash table we will attach
674 * other rules that matches next byte from IP source/destination IP and we will repeat the
675 * previous steps.
676 *
677 */
678
679
680 // /8 check
681
682 // 10.0.0.0/8
683 ht=get_u32_parse_handle("1:a:");
684 htid = (ht&0xFFFFF000);
685 htlink=get_u32_parse_handle("2:");
686
687 u32_add_filter_on_ht_with_hashmask(sock, link, 1,
688 0x0a000000, 0xff000000, direction, 0,
689 htid, htlink, 0x00ff0000, direction);
690
691 // 172.0.0.0/8
692 ht=get_u32_parse_handle("1:ac:");
693 htid = (ht&0xFFFFF000);
694 htlink=get_u32_parse_handle("3:");
695
696 u32_add_filter_on_ht_with_hashmask(sock, link, 1,
697 0xac000000, 0xff000000, direction, 0,
698 htid, htlink, 0x00ff0000, direction);
699
700
701 // /16 check
702 // 10.0.0.0/16
703 ht=get_u32_parse_handle("2:0:");
704 htid = (ht&0xFFFFF000);
705 htlink=get_u32_parse_handle("4:");
706
707 u32_add_filter_on_ht_with_hashmask(sock, link, 1,
708 0x0a000000, 0xffff0000, direction, 0,
709 htid, htlink, 0x0000ff00, direction);
710
711 // 172.17.0.0/16
712 ht=get_u32_parse_handle("3:11:");
713 htid = (ht&0xFFFFF000);
714 htlink=get_u32_parse_handle("5:");
715
716 u32_add_filter_on_ht_with_hashmask(sock, link, 1,
717 0xac110000, 0xffff0000, direction, 0,
718 htid, htlink, 0x0000ff00, direction);
719
720 // /24 check
721 // 10.0.9.0/24
722 ht=get_u32_parse_handle("4:9:");
723 htid = (ht&0xFFFFF000);
724 htlink=get_u32_parse_handle("6:");
725
726 u32_add_filter_on_ht_with_hashmask(sock, link, 1,
727 0x0a000900, 0xffffff00, direction, 0,
728 htid, htlink, 0x000000ff, direction);
729
730 // 172.17.2.0/16
731 ht=get_u32_parse_handle("5:2:");
732 htid = (ht&0xFFFFF000);
733 htlink=get_u32_parse_handle("7:");
734
735 u32_add_filter_on_ht_with_hashmask(sock, link, 1,
736 0xac110200, 0xffffff00, direction, 0,
737 htid, htlink, 0x000000ff, direction);
738
739
740 // final filters
741 // 10.0.9.20
742 ht=get_u32_parse_handle("6:14:");
743 htid = (ht&0xFFFFF000);
744
745 err = get_tc_classid(&classid, "1:5");
746
747 u32_add_filter_on_ht(sock, link, 1,
748 0x0a000914, 0xffffffff, direction, 0,
749 htid, classid);
750
751 // 172.17.2.120
752 ht=get_u32_parse_handle("7:78:");
753 htid = (ht&0xFFFFF000);
754
755 err = get_tc_classid(&classid, "1:6");
756
757 u32_add_filter_on_ht(sock, link, 1,
758 0xac110278, 0xffffffff, direction, 0,
759 htid, classid);
760
761
762
763 nl_socket_free(sock);
764 return 0;
765 }
766