libnl
3.2.3
|
00001 /* 00002 * lib/route/qdisc/sfq.c SFQ Qdisc 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @ingroup qdisc 00014 * @defgroup qdisc_sfq Stochastic Fairness Queueing (SFQ) 00015 * @brief 00016 * 00017 * @par Parameter Description 00018 * - \b Quantum: Number of bytes to send out per slot and round. 00019 * - \b Perturbation: Timer period between changing the hash function. 00020 * - \b Limit: Upper limit of queue in number of packets before SFQ starts 00021 * dropping packets. 00022 * - \b Divisor: Hash table divisor, i.e. size of hash table. 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 /** @cond SKIP */ 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 /** @endcond */ 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 * @name Attribute Access 00105 * @{ 00106 */ 00107 00108 /** 00109 * Set quantum of SFQ qdisc. 00110 * @arg qdisc SFQ qdisc to be modified. 00111 * @arg quantum New quantum in bytes. 00112 * @return 0 on success or a negative error code. 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 * Get quantum of SFQ qdisc. 00127 * @arg qdisc SFQ qdisc. 00128 * @return Quantum in bytes or a negative error code. 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 * Set limit of SFQ qdisc. 00145 * @arg qdisc SFQ qdisc to be modified. 00146 * @arg limit New limit in number of packets. 00147 * @return 0 on success or a negative error code. 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 * Get limit of SFQ qdisc. 00162 * @arg qdisc SFQ qdisc. 00163 * @return Limit or a negative error code. 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 * Set perturbation interval of SFQ qdisc. 00180 * @arg qdisc SFQ qdisc to be modified. 00181 * @arg perturb New perturbation interval in seconds. 00182 * @note A value of 0 disables perturbation altogether. 00183 * @return 0 on success or a negative error code. 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 * Get perturbation interval of SFQ qdisc. 00198 * @arg qdisc SFQ qdisc. 00199 * @return Perturbation interval in seconds or a negative error code. 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 * Get divisor of SFQ qdisc. 00216 * @arg qdisc SFQ qdisc. 00217 * @return Divisor in number of entries or a negative error code. 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 /** @} */