00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <netlink-local.h>
00033 #include <netlink-tc.h>
00034 #include <netlink/netlink.h>
00035 #include <netlink/route/qdisc.h>
00036 #include <netlink/route/qdisc-modules.h>
00037 #include <netlink/route/sch/fifo.h>
00038 #include <netlink/utils.h>
00039
00040
00041 #define SCH_FIFO_ATTR_LIMIT 1
00042
00043
00044 static inline struct rtnl_fifo *fifo_qdisc(struct rtnl_qdisc *qdisc)
00045 {
00046 return (struct rtnl_fifo *) qdisc->q_subdata;
00047 }
00048
00049 static inline struct rtnl_fifo *fifo_alloc(struct rtnl_qdisc *qdisc)
00050 {
00051 if (!qdisc->q_subdata)
00052 qdisc->q_subdata = calloc(1, sizeof(struct rtnl_fifo));
00053
00054 return fifo_qdisc(qdisc);
00055 }
00056
00057 static int fifo_msg_parser(struct rtnl_qdisc *qdisc)
00058 {
00059 struct rtnl_fifo *fifo;
00060 struct tc_fifo_qopt *opt;
00061
00062 if (qdisc->q_opts->d_size < sizeof(struct tc_fifo_qopt))
00063 return -NLE_INVAL;
00064
00065 fifo = fifo_alloc(qdisc);
00066 if (!fifo)
00067 return -NLE_NOMEM;
00068
00069 opt = (struct tc_fifo_qopt *) qdisc->q_opts->d_data;
00070 fifo->qf_limit = opt->limit;
00071 fifo->qf_mask = SCH_FIFO_ATTR_LIMIT;
00072
00073 return 0;
00074 }
00075
00076 static void fifo_free_data(struct rtnl_qdisc *qdisc)
00077 {
00078 free(qdisc->q_subdata);
00079 }
00080
00081 static void pfifo_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
00082 {
00083 struct rtnl_fifo *fifo = fifo_qdisc(qdisc);
00084
00085 if (fifo)
00086 nl_dump(p, " limit %u packets", fifo->qf_limit);
00087 }
00088
00089 static void bfifo_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
00090 {
00091 struct rtnl_fifo *fifo = fifo_qdisc(qdisc);
00092
00093 if (fifo) {
00094 char *unit;
00095 double r;
00096
00097 r = nl_cancel_down_bytes(fifo->qf_limit, &unit);
00098 nl_dump(p, " limit %.1f%s", r, unit);
00099 }
00100 }
00101
00102 static struct nl_msg *fifo_get_opts(struct rtnl_qdisc *qdisc)
00103 {
00104 struct rtnl_fifo *fifo;
00105 struct tc_fifo_qopt opts;
00106 struct nl_msg *msg;
00107
00108 fifo = fifo_qdisc(qdisc);
00109 if (!fifo || !(fifo->qf_mask & SCH_FIFO_ATTR_LIMIT))
00110 return NULL;
00111
00112 msg = nlmsg_alloc();
00113 if (!msg)
00114 goto errout;
00115
00116 memset(&opts, 0, sizeof(opts));
00117 opts.limit = fifo->qf_limit;
00118
00119 if (nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD) < 0)
00120 goto errout;
00121
00122 return msg;
00123 errout:
00124 nlmsg_free(msg);
00125 return NULL;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 int rtnl_qdisc_fifo_set_limit(struct rtnl_qdisc *qdisc, int limit)
00140 {
00141 struct rtnl_fifo *fifo;
00142
00143 fifo = fifo_alloc(qdisc);
00144 if (!fifo)
00145 return -NLE_NOMEM;
00146
00147 fifo->qf_limit = limit;
00148 fifo->qf_mask |= SCH_FIFO_ATTR_LIMIT;
00149
00150 return 0;
00151 }
00152
00153
00154
00155
00156
00157
00158 int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *qdisc)
00159 {
00160 struct rtnl_fifo *fifo;
00161
00162 fifo = fifo_qdisc(qdisc);
00163 if (fifo && fifo->qf_mask & SCH_FIFO_ATTR_LIMIT)
00164 return fifo->qf_limit;
00165 else
00166 return -NLE_NOATTR;
00167 }
00168
00169
00170
00171 static struct rtnl_qdisc_ops pfifo_ops = {
00172 .qo_kind = "pfifo",
00173 .qo_msg_parser = fifo_msg_parser,
00174 .qo_free_data = fifo_free_data,
00175 .qo_dump[NL_DUMP_LINE] = pfifo_dump_line,
00176 .qo_get_opts = fifo_get_opts,
00177 };
00178
00179 static struct rtnl_qdisc_ops bfifo_ops = {
00180 .qo_kind = "bfifo",
00181 .qo_msg_parser = fifo_msg_parser,
00182 .qo_free_data = fifo_free_data,
00183 .qo_dump[NL_DUMP_LINE] = bfifo_dump_line,
00184 .qo_get_opts = fifo_get_opts,
00185 };
00186
00187 static void __init fifo_init(void)
00188 {
00189 rtnl_qdisc_register(&pfifo_ops);
00190 rtnl_qdisc_register(&bfifo_ops);
00191 }
00192
00193 static void __exit fifo_exit(void)
00194 {
00195 rtnl_qdisc_unregister(&pfifo_ops);
00196 rtnl_qdisc_unregister(&bfifo_ops);
00197 }
00198
00199