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 */
32int 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
46int 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
81uint32_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
97int 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
128ok:
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 */
137int 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 */
189int 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 */
240int 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 */
279int 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 */
329int 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 */
391int 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 */
446int 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
494int 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