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 nl_error(EINVAL, "FIFO options size mismatch");
00064
00065 fifo = fifo_alloc(qdisc);
00066 if (!fifo)
00067 return nl_errno(ENOMEM);
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 int pfifo_dump_brief(struct rtnl_qdisc *qdisc,
00082 struct nl_dump_params *p, int line)
00083 {
00084 struct rtnl_fifo *fifo = fifo_qdisc(qdisc);
00085
00086 if (fifo)
00087 dp_dump(p, " limit %u packets", fifo->qf_limit);
00088
00089 return line;
00090 }
00091
00092 static int bfifo_dump_brief(struct rtnl_qdisc *qdisc,
00093 struct nl_dump_params *p, int line)
00094 {
00095 struct rtnl_fifo *fifo = fifo_qdisc(qdisc);
00096
00097 if (fifo) {
00098 char *unit;
00099 double r;
00100
00101 r = nl_cancel_down_bytes(fifo->qf_limit, &unit);
00102 dp_dump(p, " limit %.1f%s", r, unit);
00103 }
00104
00105 return line;
00106 }
00107
00108 static struct nl_msg *fifo_get_opts(struct rtnl_qdisc *qdisc)
00109 {
00110 struct rtnl_fifo *fifo;
00111 struct tc_fifo_qopt opts;
00112 struct nl_msg *msg;
00113
00114 fifo = fifo_qdisc(qdisc);
00115 if (!fifo || !(fifo->qf_mask & SCH_FIFO_ATTR_LIMIT))
00116 return NULL;
00117
00118 msg = nlmsg_alloc();
00119 if (!msg)
00120 goto errout;
00121
00122 memset(&opts, 0, sizeof(opts));
00123 opts.limit = fifo->qf_limit;
00124
00125 if (nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD) < 0)
00126 goto errout;
00127
00128 return msg;
00129 errout:
00130 nlmsg_free(msg);
00131 return NULL;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 int rtnl_qdisc_fifo_set_limit(struct rtnl_qdisc *qdisc, int limit)
00146 {
00147 struct rtnl_fifo *fifo;
00148
00149 fifo = fifo_alloc(qdisc);
00150 if (!fifo)
00151 return nl_errno(ENOMEM);
00152
00153 fifo->qf_limit = limit;
00154 fifo->qf_mask |= SCH_FIFO_ATTR_LIMIT;
00155
00156 return 0;
00157 }
00158
00159
00160
00161
00162
00163
00164 int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *qdisc)
00165 {
00166 struct rtnl_fifo *fifo;
00167
00168 fifo = fifo_qdisc(qdisc);
00169 if (fifo && fifo->qf_mask & SCH_FIFO_ATTR_LIMIT)
00170 return fifo->qf_limit;
00171 else
00172 return nl_errno(ENOMEM);
00173 }
00174
00175
00176
00177 static struct rtnl_qdisc_ops pfifo_ops = {
00178 .qo_kind = "pfifo",
00179 .qo_msg_parser = fifo_msg_parser,
00180 .qo_free_data = fifo_free_data,
00181 .qo_dump[NL_DUMP_BRIEF] = pfifo_dump_brief,
00182 .qo_get_opts = fifo_get_opts,
00183 };
00184
00185 static struct rtnl_qdisc_ops bfifo_ops = {
00186 .qo_kind = "bfifo",
00187 .qo_msg_parser = fifo_msg_parser,
00188 .qo_free_data = fifo_free_data,
00189 .qo_dump[NL_DUMP_BRIEF] = bfifo_dump_brief,
00190 .qo_get_opts = fifo_get_opts,
00191 };
00192
00193 static void __init fifo_init(void)
00194 {
00195 rtnl_qdisc_register(&pfifo_ops);
00196 rtnl_qdisc_register(&bfifo_ops);
00197 }
00198
00199 static void __exit fifo_exit(void)
00200 {
00201 rtnl_qdisc_unregister(&pfifo_ops);
00202 rtnl_qdisc_unregister(&bfifo_ops);
00203 }
00204
00205