1 /* $NetBSD: qop_cdnr.c,v 1.3 2001/08/16 07:48:13 itojun Exp $ */
2 /* $KAME: qop_cdnr.c,v 1.9 2001/08/16 10:39:14 kjc Exp $ */
4 * Copyright (C) 1999-2000
5 * Sony Computer Science Laboratories, Inc. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <sys/sockio.h>
32 #include <sys/ioctl.h>
33 #include <sys/fcntl.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
48 #include <altq/altq.h>
49 #include <altq/altq_cdnr.h>
53 * diffserve traffic conditioner support
55 * we use the existing qop interface to support conditioner.
58 static struct ifinfo
*cdnr_ifname2ifinfo(const char *);
59 static int cdnr_attach(struct ifinfo
*);
60 static int cdnr_detach(struct ifinfo
*);
61 static int cdnr_enable(struct ifinfo
*);
62 static int cdnr_disable(struct ifinfo
*);
63 static int cdnr_add_class(struct classinfo
*);
64 static int cdnr_modify_class(struct classinfo
*, void *);
65 static int cdnr_delete_class(struct classinfo
*);
66 static int cdnr_add_filter(struct fltrinfo
*);
67 static int cdnr_delete_filter(struct fltrinfo
*);
68 static int verify_tbprofile(struct tb_profile
*, const char *);
70 #define CDNR_DEVICE "/dev/altq/cdnr"
72 static int cdnr_fd
= -1;
73 static int cdnr_refcount
= 0;
75 static struct qdisc_ops cdnr_qdisc
= {
91 cdnr_name2handle(const char *ifname
, const char *cdnr_name
)
93 struct ifinfo
*ifinfo
;
94 struct classinfo
*clinfo
;
96 if ((ifinfo
= cdnr_ifname2ifinfo(ifname
)) == NULL
)
97 return (CDNR_NULL_HANDLE
);
99 if ((clinfo
= clname2clinfo(ifinfo
, cdnr_name
)) == NULL
)
100 return (CDNR_NULL_HANDLE
);
102 return (clinfo
->handle
);
105 static struct ifinfo
*
106 cdnr_ifname2ifinfo(const char *ifname
)
108 struct ifinfo
*ifinfo
;
109 char input_ifname
[64];
112 * search for an existing input interface
114 if ((ifinfo
= input_ifname2ifinfo(ifname
)) != NULL
)
118 * if there is a corresponding output interface,
119 * create an input interface by prepending "_" to
122 if ((ifinfo
= ifname2ifinfo(ifname
)) == NULL
)
125 input_ifname
[0] = '_';
126 strlcpy(input_ifname
+1, ifname
, sizeof(input_ifname
)-1);
127 if (qop_add_if(&ifinfo
, input_ifname
, 0, &cdnr_qdisc
, NULL
) != 0) {
129 "cdnr_ifname2ifinfo: can't add a input interface %s",
137 qcmd_cdnr_add_element(struct tc_action
*rp
, const char *ifname
,
138 const char *cdnr_name
, struct tc_action
*action
)
140 struct ifinfo
*ifinfo
;
141 struct classinfo
*clinfo
;
144 if ((ifinfo
= cdnr_ifname2ifinfo(ifname
)) == NULL
)
145 return (QOPERR_BADIF
);
147 if ((error
= qop_cdnr_add_element(&clinfo
, cdnr_name
, ifinfo
,
149 LOG(LOG_ERR
, errno
, "%s: add element failed!",
155 rp
->tca_code
= TCACODE_HANDLE
;
156 rp
->tca_handle
= clinfo
->handle
;
162 qcmd_cdnr_add_tbmeter(struct tc_action
*rp
, const char *ifname
,
163 const char *cdnr_name
,
164 struct tb_profile
*profile
,
165 struct tc_action
*in_action
,
166 struct tc_action
*out_action
)
168 struct ifinfo
*ifinfo
;
169 struct classinfo
*clinfo
;
172 if ((ifinfo
= cdnr_ifname2ifinfo(ifname
)) == NULL
)
173 return (QOPERR_BADIF
);
175 verify_tbprofile(profile
, cdnr_name
);
177 if ((error
= qop_cdnr_add_tbmeter(&clinfo
, cdnr_name
, ifinfo
,
178 profile
, in_action
, out_action
)) != 0) {
179 LOG(LOG_ERR
, errno
, "%s: add tbmeter failed!",
185 rp
->tca_code
= TCACODE_HANDLE
;
186 rp
->tca_handle
= clinfo
->handle
;
192 qcmd_cdnr_add_trtcm(struct tc_action
*rp
, const char *ifname
,
193 const char *cdnr_name
,
194 struct tb_profile
*cmtd_profile
,
195 struct tb_profile
*peak_profile
,
196 struct tc_action
*green_action
,
197 struct tc_action
*yellow_action
,
198 struct tc_action
*red_action
, int coloraware
)
200 struct ifinfo
*ifinfo
;
201 struct classinfo
*clinfo
;
204 if ((ifinfo
= cdnr_ifname2ifinfo(ifname
)) == NULL
)
205 return (QOPERR_BADIF
);
207 verify_tbprofile(cmtd_profile
, cdnr_name
);
208 verify_tbprofile(peak_profile
, cdnr_name
);
210 if ((error
= qop_cdnr_add_trtcm(&clinfo
, cdnr_name
, ifinfo
,
211 cmtd_profile
, peak_profile
,
212 green_action
, yellow_action
, red_action
,
214 LOG(LOG_ERR
, errno
, "%s: add trtcm failed!",
220 rp
->tca_code
= TCACODE_HANDLE
;
221 rp
->tca_handle
= clinfo
->handle
;
227 qcmd_cdnr_add_tswtcm(struct tc_action
*rp
, const char *ifname
,
228 const char *cdnr_name
, const u_int32_t cmtd_rate
,
229 const u_int32_t peak_rate
, const u_int32_t avg_interval
,
230 struct tc_action
*green_action
,
231 struct tc_action
*yellow_action
,
232 struct tc_action
*red_action
)
234 struct ifinfo
*ifinfo
;
235 struct classinfo
*clinfo
;
238 if ((ifinfo
= cdnr_ifname2ifinfo(ifname
)) == NULL
)
239 return (QOPERR_BADIF
);
241 if (cmtd_rate
> peak_rate
) {
243 "add tswtcm: cmtd_rate larger than peak_rate!");
244 return (QOPERR_INVAL
);
247 if ((error
= qop_cdnr_add_tswtcm(&clinfo
, cdnr_name
, ifinfo
,
248 cmtd_rate
, peak_rate
, avg_interval
,
249 green_action
, yellow_action
,
251 LOG(LOG_ERR
, errno
, "%s: add tswtcm failed!",
257 rp
->tca_code
= TCACODE_HANDLE
;
258 rp
->tca_handle
= clinfo
->handle
;
264 qcmd_cdnr_delete(const char *ifname
, const char *cdnr_name
)
266 struct ifinfo
*ifinfo
;
267 struct classinfo
*clinfo
;
269 if ((ifinfo
= cdnr_ifname2ifinfo(ifname
)) == NULL
)
270 return (QOPERR_BADIF
);
272 if ((clinfo
= clname2clinfo(ifinfo
, cdnr_name
)) == NULL
)
273 return (QOPERR_BADCLASS
);
275 return qop_delete_cdnr(clinfo
);
280 * class structure is used to hold conditioners.
282 * conditioners has dependencies in the reverse order; parent nodes
283 * refere to child nodes, and thus, a child is created first and
284 * parents should be removed first.
285 * qop_add_cdnr() and qop_delete_cdnr() are wrapper functions
286 * of qop_add_class() and qop_delete_class(), and takes care
288 * 1. when adding a conditioner, it is created as a child of a
289 * dummy root class. then, the child conditioners are made
291 * 2. when deleting a conditioner, its child conditioners are made
292 * as children of the dummy root class. then, the conditioner
297 qop_add_cdnr(struct classinfo
**rp
, const char *cdnr_name
,
298 struct ifinfo
*ifinfo
, struct classinfo
**childlist
,
301 struct classinfo
*clinfo
, *root
, *cl
, *prev
;
305 * if there is no root cdnr, create one.
307 if ((root
= get_rootclass(ifinfo
)) == NULL
) {
308 if ((error
= qop_add_class(&root
, "cdnr_root",
309 ifinfo
, NULL
, NULL
)) != 0) {
311 "cdnr: %s: can't create dummy root cdnr on %s!",
312 qoperror(error
), ifinfo
->ifname
);
313 return (QOPERR_CLASS
);
318 * create a class as a child of a root class.
320 if ((error
= qop_add_class(&clinfo
, cdnr_name
,
321 ifinfo
, root
, cdnr_private
)) != 0)
326 for (cl
= *childlist
; cl
!= NULL
; cl
= *++childlist
) {
327 if (cl
->parent
!= root
) {
329 * this conditioner already has a non-root parent.
330 * we can't track down a multi-parent node by a
331 * tree structure; leave it as it is.
332 * (we need a mechanism similar to a symbolic link
337 /* remove this child from the root */
338 if (root
->child
== cl
)
339 root
->child
= cl
->sibling
;
340 else for (prev
= root
->child
;
341 prev
->sibling
!= NULL
; prev
= prev
->sibling
)
342 if (prev
->sibling
== cl
) {
343 prev
->sibling
= cl
->sibling
;
348 cl
->sibling
= clinfo
->child
;
359 qop_delete_cdnr(struct classinfo
*clinfo
)
361 struct classinfo
*cl
, *root
;
364 if ((root
= get_rootclass(clinfo
->ifinfo
)) == NULL
) {
365 LOG(LOG_ERR
, 0, "qop_delete_cdnr: no root cdnr!");
366 return (QOPERR_CLASS
);
369 if (clinfo
->parent
!= root
)
370 return (QOPERR_CLASS_PERM
);
372 if ((cl
= clinfo
->child
) != NULL
) {
373 /* change child's parent to root, find the last child */
374 while (cl
->sibling
!= NULL
) {
380 /* move children to siblings */
381 cl
->sibling
= clinfo
->sibling
;
382 clinfo
->sibling
= cl
;
383 clinfo
->child
= NULL
;
386 error
= qop_delete_class(clinfo
);
389 /* ick! restore the class tree */
391 clinfo
->child
= clinfo
->sibling
;
392 clinfo
->sibling
= cl
->sibling
;
394 /* restore parent field */
395 for (cl
= clinfo
->child
; cl
!= NULL
; cl
= cl
->sibling
)
403 qop_cdnr_add_element(struct classinfo
**rp
, const char *cdnr_name
,
404 struct ifinfo
*ifinfo
, struct tc_action
*action
)
406 struct classinfo
*clinfo
, *clist
[2];
407 struct cdnrinfo
*cdnrinfo
= NULL
;
410 if (action
->tca_code
== TCACODE_HANDLE
) {
411 clinfo
= clhandle2clinfo(ifinfo
, action
->tca_handle
);
413 return (QOPERR_BADCLASS
);
418 * if the conditioner referred to doesn't have a name,
419 * this is called just to add a name to it.
420 * we can simply add the name to the existing conditioner
423 if (cdnr_name
!= NULL
&&
424 strcmp(clinfo
->clname
, "(null)") == 0) {
425 free(clinfo
->clname
);
426 clinfo
->clname
= strdup(cdnr_name
);
435 if ((cdnrinfo
= calloc(1, sizeof(*cdnrinfo
))) == NULL
)
436 return (QOPERR_NOMEM
);
438 cdnrinfo
->tce_type
= TCETYPE_ELEMENT
;
439 cdnrinfo
->tce_un
.element
.action
= *action
;
441 if ((error
= qop_add_cdnr(&clinfo
, cdnr_name
, ifinfo
, clist
,
450 if (cdnrinfo
!= NULL
)
456 qop_cdnr_add_tbmeter(struct classinfo
**rp
, const char *cdnr_name
,
457 struct ifinfo
*ifinfo
,
458 struct tb_profile
*profile
,
459 struct tc_action
*in_action
,
460 struct tc_action
*out_action
)
462 struct classinfo
*clinfo
, *clist
[3];
463 struct cdnrinfo
*cdnrinfo
= NULL
;
467 if (in_action
->tca_code
== TCACODE_HANDLE
) {
468 clist
[n
] = clhandle2clinfo(ifinfo
, in_action
->tca_handle
);
469 if (clist
[n
] == NULL
)
470 return (QOPERR_BADCLASS
);
473 if (out_action
->tca_code
== TCACODE_HANDLE
) {
474 clist
[n
] = clhandle2clinfo(ifinfo
, out_action
->tca_handle
);
475 if (clist
[n
] == NULL
)
476 return (QOPERR_BADCLASS
);
481 if ((cdnrinfo
= calloc(1, sizeof(*cdnrinfo
))) == NULL
)
482 return (QOPERR_NOMEM
);
484 cdnrinfo
->tce_type
= TCETYPE_TBMETER
;
485 cdnrinfo
->tce_un
.tbmeter
.profile
= *profile
;
486 cdnrinfo
->tce_un
.tbmeter
.in_action
= *in_action
;
487 cdnrinfo
->tce_un
.tbmeter
.out_action
= *out_action
;
489 if ((error
= qop_add_cdnr(&clinfo
, cdnr_name
, ifinfo
, clist
,
498 if (cdnrinfo
!= NULL
)
504 qop_cdnr_modify_tbmeter(struct classinfo
*clinfo
, struct tb_profile
*profile
)
506 struct cdnrinfo
*cdnrinfo
= clinfo
->private;
508 if (cdnrinfo
->tce_type
!= TCETYPE_TBMETER
)
509 return (QOPERR_CLASS_INVAL
);
510 cdnrinfo
->tce_un
.tbmeter
.profile
= *profile
;
512 return qop_modify_class(clinfo
, NULL
);
516 qop_cdnr_add_trtcm(struct classinfo
**rp
, const char *cdnr_name
,
517 struct ifinfo
*ifinfo
,
518 struct tb_profile
*cmtd_profile
,
519 struct tb_profile
*peak_profile
,
520 struct tc_action
*green_action
,
521 struct tc_action
*yellow_action
,
522 struct tc_action
*red_action
, int coloraware
)
524 struct classinfo
*clinfo
, *clist
[4];
525 struct cdnrinfo
*cdnrinfo
= NULL
;
529 if (green_action
->tca_code
== TCACODE_HANDLE
) {
530 clist
[n
] = clhandle2clinfo(ifinfo
, green_action
->tca_handle
);
531 if (clist
[n
] == NULL
)
532 return (QOPERR_BADCLASS
);
535 if (yellow_action
->tca_code
== TCACODE_HANDLE
) {
536 clist
[n
] = clhandle2clinfo(ifinfo
, yellow_action
->tca_handle
);
537 if (clist
[n
] == NULL
)
538 return (QOPERR_BADCLASS
);
541 if (red_action
->tca_code
== TCACODE_HANDLE
) {
542 clist
[n
] = clhandle2clinfo(ifinfo
, yellow_action
->tca_handle
);
543 if (clist
[n
] == NULL
)
544 return (QOPERR_BADCLASS
);
549 if ((cdnrinfo
= calloc(1, sizeof(*cdnrinfo
))) == NULL
)
550 return (QOPERR_NOMEM
);
552 cdnrinfo
->tce_type
= TCETYPE_TRTCM
;
553 cdnrinfo
->tce_un
.trtcm
.cmtd_profile
= *cmtd_profile
;
554 cdnrinfo
->tce_un
.trtcm
.peak_profile
= *peak_profile
;
555 cdnrinfo
->tce_un
.trtcm
.green_action
= *green_action
;
556 cdnrinfo
->tce_un
.trtcm
.yellow_action
= *yellow_action
;
557 cdnrinfo
->tce_un
.trtcm
.red_action
= *red_action
;
558 cdnrinfo
->tce_un
.trtcm
.coloraware
= coloraware
;
560 if ((error
= qop_add_cdnr(&clinfo
, cdnr_name
, ifinfo
, clist
,
569 if (cdnrinfo
!= NULL
)
575 qop_cdnr_modify_trtcm(struct classinfo
*clinfo
,
576 struct tb_profile
*cmtd_profile
,
577 struct tb_profile
*peak_profile
, int coloraware
)
579 struct cdnrinfo
*cdnrinfo
= clinfo
->private;
581 if (cdnrinfo
->tce_type
!= TCETYPE_TRTCM
)
582 return (QOPERR_CLASS_INVAL
);
583 cdnrinfo
->tce_un
.trtcm
.cmtd_profile
= *cmtd_profile
;
584 cdnrinfo
->tce_un
.trtcm
.peak_profile
= *peak_profile
;
585 cdnrinfo
->tce_un
.trtcm
.coloraware
= coloraware
;
587 return qop_modify_class(clinfo
, NULL
);
591 qop_cdnr_add_tswtcm(struct classinfo
**rp
, const char *cdnr_name
,
592 struct ifinfo
*ifinfo
, const u_int32_t cmtd_rate
,
593 const u_int32_t peak_rate
, const u_int32_t avg_interval
,
594 struct tc_action
*green_action
,
595 struct tc_action
*yellow_action
,
596 struct tc_action
*red_action
)
598 struct classinfo
*clinfo
, *clist
[4];
599 struct cdnrinfo
*cdnrinfo
= NULL
;
603 if (green_action
->tca_code
== TCACODE_HANDLE
) {
604 clist
[n
] = clhandle2clinfo(ifinfo
, green_action
->tca_handle
);
605 if (clist
[n
] == NULL
)
606 return (QOPERR_BADCLASS
);
609 if (yellow_action
->tca_code
== TCACODE_HANDLE
) {
610 clist
[n
] = clhandle2clinfo(ifinfo
, yellow_action
->tca_handle
);
611 if (clist
[n
] == NULL
)
612 return (QOPERR_BADCLASS
);
615 if (red_action
->tca_code
== TCACODE_HANDLE
) {
616 clist
[n
] = clhandle2clinfo(ifinfo
, yellow_action
->tca_handle
);
617 if (clist
[n
] == NULL
)
618 return (QOPERR_BADCLASS
);
623 if ((cdnrinfo
= calloc(1, sizeof(*cdnrinfo
))) == NULL
)
624 return (QOPERR_NOMEM
);
626 cdnrinfo
->tce_type
= TCETYPE_TSWTCM
;
627 cdnrinfo
->tce_un
.tswtcm
.cmtd_rate
= cmtd_rate
;
628 cdnrinfo
->tce_un
.tswtcm
.peak_rate
= peak_rate
;
629 cdnrinfo
->tce_un
.tswtcm
.avg_interval
= avg_interval
;
630 cdnrinfo
->tce_un
.tswtcm
.green_action
= *green_action
;
631 cdnrinfo
->tce_un
.tswtcm
.yellow_action
= *yellow_action
;
632 cdnrinfo
->tce_un
.tswtcm
.red_action
= *red_action
;
634 if ((error
= qop_add_cdnr(&clinfo
, cdnr_name
, ifinfo
, clist
,
643 if (cdnrinfo
!= NULL
)
649 qop_cdnr_modify_tswtcm(struct classinfo
*clinfo
, const u_int32_t cmtd_rate
,
650 const u_int32_t peak_rate
, const u_int32_t avg_interval
)
652 struct cdnrinfo
*cdnrinfo
= clinfo
->private;
654 if (cdnrinfo
->tce_type
!= TCETYPE_TSWTCM
)
655 return (QOPERR_CLASS_INVAL
);
656 cdnrinfo
->tce_un
.tswtcm
.cmtd_rate
= cmtd_rate
;
657 cdnrinfo
->tce_un
.tswtcm
.peak_rate
= peak_rate
;
658 cdnrinfo
->tce_un
.tswtcm
.avg_interval
= avg_interval
;
660 return qop_modify_class(clinfo
, NULL
);
664 * system call interfaces for qdisc_ops
667 cdnr_attach(struct ifinfo
*ifinfo
)
669 struct cdnr_interface iface
;
672 (cdnr_fd
= open(CDNR_DEVICE
, O_RDWR
)) < 0 &&
673 (cdnr_fd
= open_module(CDNR_DEVICE
, O_RDWR
)) < 0) {
674 LOG(LOG_ERR
, errno
, "CDNR open");
675 return (QOPERR_SYSCALL
);
679 memset(&iface
, 0, sizeof(iface
));
680 strncpy(iface
.cdnr_ifname
, ifinfo
->ifname
+1, IFNAMSIZ
);
682 if (ioctl(cdnr_fd
, CDNR_IF_ATTACH
, &iface
) < 0)
683 return (QOPERR_SYSCALL
);
685 LOG(LOG_INFO
, 0, "conditioner attached to %s", iface
.cdnr_ifname
);
691 cdnr_detach(struct ifinfo
*ifinfo
)
693 struct cdnr_interface iface
;
695 memset(&iface
, 0, sizeof(iface
));
696 strncpy(iface
.cdnr_ifname
, ifinfo
->ifname
+1, IFNAMSIZ
);
698 if (ioctl(cdnr_fd
, CDNR_IF_DETACH
, &iface
) < 0)
699 return (QOPERR_SYSCALL
);
701 if (--cdnr_refcount
== 0) {
709 cdnr_enable(struct ifinfo
*ifinfo
)
711 struct cdnr_interface iface
;
713 memset(&iface
, 0, sizeof(iface
));
714 strncpy(iface
.cdnr_ifname
, ifinfo
->ifname
+1, IFNAMSIZ
);
716 if (ioctl(cdnr_fd
, CDNR_ENABLE
, &iface
) < 0)
717 return (QOPERR_SYSCALL
);
722 cdnr_disable(struct ifinfo
*ifinfo
)
724 struct cdnr_interface iface
;
726 memset(&iface
, 0, sizeof(iface
));
727 strncpy(iface
.cdnr_ifname
, ifinfo
->ifname
+1, IFNAMSIZ
);
729 if (ioctl(cdnr_fd
, CDNR_DISABLE
, &iface
) < 0)
730 return (QOPERR_SYSCALL
);
735 cdnr_add_class(struct classinfo
*clinfo
)
737 struct cdnr_add_element element_add
;
738 struct cdnr_add_tbmeter tbmeter_add
;
739 struct cdnr_add_trtcm trtcm_add
;
740 struct cdnr_add_tswtcm tswtcm_add
;
741 struct cdnrinfo
*cdnrinfo
;
743 cdnrinfo
= clinfo
->private;
745 /* root class is a dummy class */
746 if (clinfo
->parent
== NULL
) {
751 switch (cdnrinfo
->tce_type
) {
752 case TCETYPE_ELEMENT
:
753 memset(&element_add
, 0, sizeof(element_add
));
754 strncpy(element_add
.iface
.cdnr_ifname
,
755 clinfo
->ifinfo
->ifname
+1, IFNAMSIZ
);
756 element_add
.action
= cdnrinfo
->tce_un
.element
.action
;
757 if (ioctl(cdnr_fd
, CDNR_ADD_ELEM
, &element_add
) < 0) {
758 clinfo
->handle
= CDNR_NULL_HANDLE
;
759 return (QOPERR_SYSCALL
);
761 clinfo
->handle
= element_add
.cdnr_handle
;
764 case TCETYPE_TBMETER
:
765 memset(&tbmeter_add
, 0, sizeof(tbmeter_add
));
766 strncpy(tbmeter_add
.iface
.cdnr_ifname
,
767 clinfo
->ifinfo
->ifname
+1, IFNAMSIZ
);
768 tbmeter_add
.profile
= cdnrinfo
->tce_un
.tbmeter
.profile
;
769 tbmeter_add
.in_action
= cdnrinfo
->tce_un
.tbmeter
.in_action
;
770 tbmeter_add
.out_action
= cdnrinfo
->tce_un
.tbmeter
.out_action
;
771 if (ioctl(cdnr_fd
, CDNR_ADD_TBM
, &tbmeter_add
) < 0) {
772 clinfo
->handle
= CDNR_NULL_HANDLE
;
773 return (QOPERR_SYSCALL
);
775 clinfo
->handle
= tbmeter_add
.cdnr_handle
;
779 memset(&trtcm_add
, 0, sizeof(trtcm_add
));
780 strncpy(trtcm_add
.iface
.cdnr_ifname
,
781 clinfo
->ifinfo
->ifname
+1, IFNAMSIZ
);
782 trtcm_add
.cmtd_profile
= cdnrinfo
->tce_un
.trtcm
.cmtd_profile
;
783 trtcm_add
.peak_profile
= cdnrinfo
->tce_un
.trtcm
.peak_profile
;
784 trtcm_add
.green_action
= cdnrinfo
->tce_un
.trtcm
.green_action
;
785 trtcm_add
.yellow_action
= cdnrinfo
->tce_un
.trtcm
.yellow_action
;
786 trtcm_add
.red_action
= cdnrinfo
->tce_un
.trtcm
.red_action
;
787 trtcm_add
.coloraware
= cdnrinfo
->tce_un
.trtcm
.coloraware
;
788 if (ioctl(cdnr_fd
, CDNR_ADD_TCM
, &trtcm_add
) < 0) {
789 clinfo
->handle
= CDNR_NULL_HANDLE
;
790 return (QOPERR_SYSCALL
);
792 clinfo
->handle
= trtcm_add
.cdnr_handle
;
796 memset(&tswtcm_add
, 0, sizeof(tswtcm_add
));
797 strncpy(tswtcm_add
.iface
.cdnr_ifname
,
798 clinfo
->ifinfo
->ifname
+1, IFNAMSIZ
);
799 tswtcm_add
.cmtd_rate
= cdnrinfo
->tce_un
.tswtcm
.cmtd_rate
;
800 tswtcm_add
.peak_rate
= cdnrinfo
->tce_un
.tswtcm
.peak_rate
;
801 tswtcm_add
.avg_interval
= cdnrinfo
->tce_un
.tswtcm
.avg_interval
;
802 tswtcm_add
.green_action
= cdnrinfo
->tce_un
.tswtcm
.green_action
;
803 tswtcm_add
.yellow_action
= cdnrinfo
->tce_un
.tswtcm
.yellow_action
;
804 tswtcm_add
.red_action
= cdnrinfo
->tce_un
.tswtcm
.red_action
;
805 if (ioctl(cdnr_fd
, CDNR_ADD_TSW
, &tswtcm_add
) < 0) {
806 clinfo
->handle
= CDNR_NULL_HANDLE
;
807 return (QOPERR_SYSCALL
);
809 clinfo
->handle
= tswtcm_add
.cdnr_handle
;
813 return (QOPERR_CLASS_INVAL
);
819 cdnr_modify_class(struct classinfo
*clinfo
, void *arg
)
821 struct cdnr_modify_tbmeter tbmeter_modify
;
822 struct cdnr_modify_trtcm trtcm_modify
;
823 struct cdnr_modify_tswtcm tswtcm_modify
;
824 struct cdnrinfo
*cdnrinfo
;
826 cdnrinfo
= clinfo
->private;
828 switch (cdnrinfo
->tce_type
) {
829 case TCETYPE_TBMETER
:
830 memset(&tbmeter_modify
, 0, sizeof(tbmeter_modify
));
831 strncpy(tbmeter_modify
.iface
.cdnr_ifname
,
832 clinfo
->ifinfo
->ifname
+1, IFNAMSIZ
);
833 tbmeter_modify
.cdnr_handle
= clinfo
->handle
;
834 tbmeter_modify
.profile
= cdnrinfo
->tce_un
.tbmeter
.profile
;
835 if (ioctl(cdnr_fd
, CDNR_MOD_TBM
, &tbmeter_modify
) < 0)
836 return (QOPERR_SYSCALL
);
840 memset(&trtcm_modify
, 0, sizeof(trtcm_modify
));
841 strncpy(trtcm_modify
.iface
.cdnr_ifname
,
842 clinfo
->ifinfo
->ifname
+1, IFNAMSIZ
);
843 trtcm_modify
.cdnr_handle
= clinfo
->handle
;
844 trtcm_modify
.cmtd_profile
=
845 cdnrinfo
->tce_un
.trtcm
.cmtd_profile
;
846 trtcm_modify
.peak_profile
=
847 cdnrinfo
->tce_un
.trtcm
.peak_profile
;
848 trtcm_modify
.coloraware
= cdnrinfo
->tce_un
.trtcm
.coloraware
;
849 if (ioctl(cdnr_fd
, CDNR_MOD_TCM
, &trtcm_modify
) < 0)
850 return (QOPERR_SYSCALL
);
854 memset(&tswtcm_modify
, 0, sizeof(tswtcm_modify
));
855 strncpy(tswtcm_modify
.iface
.cdnr_ifname
,
856 clinfo
->ifinfo
->ifname
+1, IFNAMSIZ
);
857 tswtcm_modify
.cdnr_handle
= clinfo
->handle
;
858 tswtcm_modify
.cmtd_rate
= cdnrinfo
->tce_un
.tswtcm
.cmtd_rate
;
859 tswtcm_modify
.peak_rate
= cdnrinfo
->tce_un
.tswtcm
.peak_rate
;
860 tswtcm_modify
.avg_interval
= cdnrinfo
->tce_un
.tswtcm
.avg_interval
;
861 if (ioctl(cdnr_fd
, CDNR_MOD_TSW
, &tswtcm_modify
) < 0)
862 return (QOPERR_SYSCALL
);
866 return (QOPERR_CLASS_INVAL
);
872 cdnr_delete_class(struct classinfo
*clinfo
)
874 struct cdnr_delete_element element_delete
;
876 if (clinfo
->handle
== CDNR_NULL_HANDLE
)
879 memset(&element_delete
, 0, sizeof(element_delete
));
880 strncpy(element_delete
.iface
.cdnr_ifname
, clinfo
->ifinfo
->ifname
+1,
882 element_delete
.cdnr_handle
= clinfo
->handle
;
884 if (ioctl(cdnr_fd
, CDNR_DEL_ELEM
, &element_delete
) < 0)
885 return (QOPERR_SYSCALL
);
890 cdnr_add_filter(struct fltrinfo
*fltrinfo
)
892 struct cdnr_add_filter fltr_add
;
894 memset(&fltr_add
, 0, sizeof(fltr_add
));
895 strncpy(fltr_add
.iface
.cdnr_ifname
,
896 fltrinfo
->clinfo
->ifinfo
->ifname
+1, IFNAMSIZ
);
897 fltr_add
.cdnr_handle
= fltrinfo
->clinfo
->handle
;
898 fltr_add
.filter
= fltrinfo
->fltr
;
900 if (ioctl(cdnr_fd
, CDNR_ADD_FILTER
, &fltr_add
) < 0)
901 return (QOPERR_SYSCALL
);
902 fltrinfo
->handle
= fltr_add
.filter_handle
;
907 cdnr_delete_filter(struct fltrinfo
*fltrinfo
)
909 struct cdnr_delete_filter fltr_del
;
911 memset(&fltr_del
, 0, sizeof(fltr_del
));
912 strncpy(fltr_del
.iface
.cdnr_ifname
,
913 fltrinfo
->clinfo
->ifinfo
->ifname
+1, IFNAMSIZ
);
914 fltr_del
.filter_handle
= fltrinfo
->handle
;
916 if (ioctl(cdnr_fd
, CDNR_DEL_FILTER
, &fltr_del
) < 0)
917 return (QOPERR_SYSCALL
);
923 verify_tbprofile(struct tb_profile
*profile
, const char *cdnr_name
)
925 if (profile
->depth
< 1500) {
927 "warning: token bucket depth for %s is too small (%d)",
928 cdnr_name
, profile
->depth
);