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 #include <netlink-local.h>
00027 #include <netlink-tc.h>
00028 #include <netlink/netlink.h>
00029 #include <netlink/utils.h>
00030 #include <netlink/route/tc-api.h>
00031 #include <netlink/route/qdisc.h>
00032 #include <netlink/route/qdisc/sfq.h>
00033
00034
00035 #define SCH_SFQ_ATTR_QUANTUM 0x01
00036 #define SCH_SFQ_ATTR_PERTURB 0x02
00037 #define SCH_SFQ_ATTR_LIMIT 0x04
00038 #define SCH_SFQ_ATTR_DIVISOR 0x08
00039 #define SCH_SFQ_ATTR_FLOWS 0x10
00040
00041
00042 static int sfq_msg_parser(struct rtnl_tc *tc, void *data)
00043 {
00044 struct rtnl_sfq *sfq = data;
00045 struct tc_sfq_qopt *opts;
00046
00047 if (!(tc->ce_mask & TCA_ATTR_OPTS))
00048 return 0;
00049
00050 if (tc->tc_opts->d_size < sizeof(*opts))
00051 return -NLE_INVAL;
00052
00053 opts = (struct tc_sfq_qopt *) tc->tc_opts->d_data;
00054
00055 sfq->qs_quantum = opts->quantum;
00056 sfq->qs_perturb = opts->perturb_period;
00057 sfq->qs_limit = opts->limit;
00058 sfq->qs_divisor = opts->divisor;
00059 sfq->qs_flows = opts->flows;
00060
00061 sfq->qs_mask = (SCH_SFQ_ATTR_QUANTUM | SCH_SFQ_ATTR_PERTURB |
00062 SCH_SFQ_ATTR_LIMIT | SCH_SFQ_ATTR_DIVISOR |
00063 SCH_SFQ_ATTR_FLOWS);
00064
00065 return 0;
00066 }
00067
00068 static void sfq_dump_line(struct rtnl_tc *tc, void *data,
00069 struct nl_dump_params *p)
00070 {
00071 struct rtnl_sfq *sfq = data;
00072
00073 if (sfq)
00074 nl_dump(p, " quantum %u perturb %us", sfq->qs_quantum,
00075 sfq->qs_perturb);
00076 }
00077
00078 static void sfq_dump_details(struct rtnl_tc *tc, void *data,
00079 struct nl_dump_params *p)
00080 {
00081 struct rtnl_sfq *sfq = data;
00082
00083 if (sfq)
00084 nl_dump(p, "limit %u divisor %u",
00085 sfq->qs_limit, sfq->qs_divisor);
00086 }
00087
00088 static int sfq_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
00089 {
00090 struct rtnl_sfq *sfq = data;
00091 struct tc_sfq_qopt opts = {0};
00092
00093 if (!sfq)
00094 BUG();
00095
00096 opts.quantum = sfq->qs_quantum;
00097 opts.perturb_period = sfq->qs_perturb;
00098 opts.limit = sfq->qs_limit;
00099
00100 return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 void rtnl_sfq_set_quantum(struct rtnl_qdisc *qdisc, int quantum)
00115 {
00116 struct rtnl_sfq *sfq;
00117
00118 if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
00119 BUG();
00120
00121 sfq->qs_quantum = quantum;
00122 sfq->qs_mask |= SCH_SFQ_ATTR_QUANTUM;
00123 }
00124
00125
00126
00127
00128
00129
00130 int rtnl_sfq_get_quantum(struct rtnl_qdisc *qdisc)
00131 {
00132 struct rtnl_sfq *sfq;
00133
00134 if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
00135 BUG();
00136
00137 if (sfq->qs_mask & SCH_SFQ_ATTR_QUANTUM)
00138 return sfq->qs_quantum;
00139 else
00140 return -NLE_NOATTR;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149 void rtnl_sfq_set_limit(struct rtnl_qdisc *qdisc, int limit)
00150 {
00151 struct rtnl_sfq *sfq;
00152
00153 if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
00154 BUG();
00155
00156 sfq->qs_limit = limit;
00157 sfq->qs_mask |= SCH_SFQ_ATTR_LIMIT;
00158 }
00159
00160
00161
00162
00163
00164
00165 int rtnl_sfq_get_limit(struct rtnl_qdisc *qdisc)
00166 {
00167 struct rtnl_sfq *sfq;
00168
00169 if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
00170 BUG();
00171
00172 if (sfq->qs_mask & SCH_SFQ_ATTR_LIMIT)
00173 return sfq->qs_limit;
00174 else
00175 return -NLE_NOATTR;
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185 void rtnl_sfq_set_perturb(struct rtnl_qdisc *qdisc, int perturb)
00186 {
00187 struct rtnl_sfq *sfq;
00188
00189 if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
00190 BUG();
00191
00192 sfq->qs_perturb = perturb;
00193 sfq->qs_mask |= SCH_SFQ_ATTR_PERTURB;
00194 }
00195
00196
00197
00198
00199
00200
00201 int rtnl_sfq_get_perturb(struct rtnl_qdisc *qdisc)
00202 {
00203 struct rtnl_sfq *sfq;
00204
00205 if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
00206 BUG();
00207
00208 if (sfq->qs_mask & SCH_SFQ_ATTR_PERTURB)
00209 return sfq->qs_perturb;
00210 else
00211 return -NLE_NOATTR;
00212 }
00213
00214
00215
00216
00217
00218
00219 int rtnl_sfq_get_divisor(struct rtnl_qdisc *qdisc)
00220 {
00221 struct rtnl_sfq *sfq;
00222
00223 if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
00224 BUG();
00225
00226 if (sfq->qs_mask & SCH_SFQ_ATTR_DIVISOR)
00227 return sfq->qs_divisor;
00228 else
00229 return -NLE_NOATTR;
00230 }
00231
00232
00233
00234 static struct rtnl_tc_ops sfq_ops = {
00235 .to_kind = "sfq",
00236 .to_type = RTNL_TC_TYPE_QDISC,
00237 .to_size = sizeof(struct rtnl_sfq),
00238 .to_msg_parser = sfq_msg_parser,
00239 .to_dump = {
00240 [NL_DUMP_LINE] = sfq_dump_line,
00241 [NL_DUMP_DETAILS] = sfq_dump_details,
00242 },
00243 .to_msg_fill = sfq_msg_fill,
00244 };
00245
00246 static void __init sfq_init(void)
00247 {
00248 rtnl_tc_register(&sfq_ops);
00249 }
00250
00251 static void __exit sfq_exit(void)
00252 {
00253 rtnl_tc_unregister(&sfq_ops);
00254 }
00255
00256