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