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