libnl
3.2.3
|
00001 /* 00002 * lib/route/qdisc/fifo.c (p|b)fifo 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_fifo Packet/Bytes FIFO (pfifo/bfifo) 00015 * @brief 00016 * 00017 * The FIFO qdisc comes in two flavours: 00018 * @par bfifo (Byte FIFO) 00019 * Allows enqueuing until the currently queued volume in bytes exceeds 00020 * the configured limit.backlog contains currently enqueued volume in bytes. 00021 * 00022 * @par pfifo (Packet FIFO) 00023 * Allows enquueing until the currently queued number of packets 00024 * exceeds the configured limit. 00025 * 00026 * The configuration is exactly the same, the decision which of 00027 * the two variations is going to be used is made based on the 00028 * kind of the qdisc (rtnl_tc_set_kind()). 00029 * @{ 00030 */ 00031 00032 #include <netlink-local.h> 00033 #include <netlink-tc.h> 00034 #include <netlink/netlink.h> 00035 #include <netlink/route/tc-api.h> 00036 #include <netlink/route/qdisc.h> 00037 #include <netlink/route/qdisc/fifo.h> 00038 #include <netlink/utils.h> 00039 00040 /** @cond SKIP */ 00041 #define SCH_FIFO_ATTR_LIMIT 1 00042 /** @endcond */ 00043 00044 static int fifo_msg_parser(struct rtnl_tc *tc, void *data) 00045 { 00046 struct rtnl_fifo *fifo = data; 00047 struct tc_fifo_qopt *opt; 00048 00049 if (tc->tc_opts->d_size < sizeof(struct tc_fifo_qopt)) 00050 return -NLE_INVAL; 00051 00052 opt = (struct tc_fifo_qopt *) tc->tc_opts->d_data; 00053 fifo->qf_limit = opt->limit; 00054 fifo->qf_mask = SCH_FIFO_ATTR_LIMIT; 00055 00056 return 0; 00057 } 00058 00059 static void pfifo_dump_line(struct rtnl_tc *tc, void *data, 00060 struct nl_dump_params *p) 00061 { 00062 struct rtnl_fifo *fifo = data; 00063 00064 if (fifo) 00065 nl_dump(p, " limit %u packets", fifo->qf_limit); 00066 } 00067 00068 static void bfifo_dump_line(struct rtnl_tc *tc, void *data, 00069 struct nl_dump_params *p) 00070 { 00071 struct rtnl_fifo *fifo = data; 00072 char *unit; 00073 double r; 00074 00075 if (!fifo) 00076 return; 00077 00078 r = nl_cancel_down_bytes(fifo->qf_limit, &unit); 00079 nl_dump(p, " limit %.1f%s", r, unit); 00080 } 00081 00082 static int fifo_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) 00083 { 00084 struct rtnl_fifo *fifo = data; 00085 struct tc_fifo_qopt opts = {0}; 00086 00087 if (!fifo || !(fifo->qf_mask & SCH_FIFO_ATTR_LIMIT)) 00088 return -NLE_INVAL; 00089 00090 opts.limit = fifo->qf_limit; 00091 00092 return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD); 00093 } 00094 00095 /** 00096 * @name Attribute Modification 00097 * @{ 00098 */ 00099 00100 /** 00101 * Set limit of FIFO qdisc. 00102 * @arg qdisc FIFO qdisc to be modified. 00103 * @arg limit New limit. 00104 * @return 0 on success or a negative error code. 00105 */ 00106 int rtnl_qdisc_fifo_set_limit(struct rtnl_qdisc *qdisc, int limit) 00107 { 00108 struct rtnl_fifo *fifo; 00109 00110 if (!(fifo = rtnl_tc_data(TC_CAST(qdisc)))) 00111 return -NLE_NOMEM; 00112 00113 fifo->qf_limit = limit; 00114 fifo->qf_mask |= SCH_FIFO_ATTR_LIMIT; 00115 00116 return 0; 00117 } 00118 00119 /** 00120 * Get limit of a FIFO qdisc. 00121 * @arg qdisc FIFO qdisc. 00122 * @return Numeric limit or a negative error code. 00123 */ 00124 int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *qdisc) 00125 { 00126 struct rtnl_fifo *fifo; 00127 00128 if (!(fifo = rtnl_tc_data(TC_CAST(qdisc)))) 00129 return -NLE_NOMEM; 00130 00131 if (fifo->qf_mask & SCH_FIFO_ATTR_LIMIT) 00132 return fifo->qf_limit; 00133 else 00134 return -NLE_NOATTR; 00135 } 00136 00137 /** @} */ 00138 00139 static struct rtnl_tc_ops pfifo_ops = { 00140 .to_kind = "pfifo", 00141 .to_type = RTNL_TC_TYPE_QDISC, 00142 .to_size = sizeof(struct rtnl_fifo), 00143 .to_msg_parser = fifo_msg_parser, 00144 .to_dump[NL_DUMP_LINE] = pfifo_dump_line, 00145 .to_msg_fill = fifo_msg_fill, 00146 }; 00147 00148 static struct rtnl_tc_ops bfifo_ops = { 00149 .to_kind = "bfifo", 00150 .to_type = RTNL_TC_TYPE_QDISC, 00151 .to_size = sizeof(struct rtnl_fifo), 00152 .to_msg_parser = fifo_msg_parser, 00153 .to_dump[NL_DUMP_LINE] = bfifo_dump_line, 00154 .to_msg_fill = fifo_msg_fill, 00155 }; 00156 00157 static void __init fifo_init(void) 00158 { 00159 rtnl_tc_register(&pfifo_ops); 00160 rtnl_tc_register(&bfifo_ops); 00161 } 00162 00163 static void __exit fifo_exit(void) 00164 { 00165 rtnl_tc_unregister(&pfifo_ops); 00166 rtnl_tc_unregister(&bfifo_ops); 00167 } 00168 00169 /** @} */