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 (at) 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 */ 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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