1bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet/* 2bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * Fair Queue 3bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * 48d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet * Copyright (C) 2013-2015 Eric Dumazet <edumazet@google.com> 5bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * 6bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * Redistribution and use in source and binary forms, with or without 7bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * modification, are permitted provided that the following conditions 8bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * are met: 9bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * 1. Redistributions of source code must retain the above copyright 10bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * notice, this list of conditions, and the following disclaimer, 11bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * without modification. 12bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * 2. Redistributions in binary form must reproduce the above copyright 13bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * notice, this list of conditions and the following disclaimer in the 14bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * documentation and/or other materials provided with the distribution. 15bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * 3. The names of the authors may not be used to endorse or promote products 16bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * derived from this software without specific prior written permission. 17bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * 18bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * Alternatively, provided that this notice is retained in full, this 19bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * software may be distributed under the terms of the GNU General 20bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * Public License ("GPL") version 2, in which case the provisions of the 21bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * GPL apply INSTEAD OF those given above. 22bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * 23bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 34bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * DAMAGE. 35bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet * 36bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet */ 37bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 38bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include <stdio.h> 39bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include <stdlib.h> 40bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include <unistd.h> 41bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include <syslog.h> 42bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include <fcntl.h> 43bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include <sys/socket.h> 44bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include <netinet/in.h> 45bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include <arpa/inet.h> 46bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include <string.h> 47aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang#include <stdbool.h> 48bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 49bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include "utils.h" 50bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet#include "tc_util.h" 51bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 52bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazetstatic void explain(void) 53bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet{ 54bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, "Usage: ... fq [ limit PACKETS ] [ flow_limit PACKETS ]\n"); 55bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, " [ quantum BYTES ] [ initial_quantum BYTES ]\n"); 56bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, " [ maxrate RATE ] [ buckets NUMBER ]\n"); 57565af7b8168416bb8432f9f10935b7897232e853Phil Sutter fprintf(stderr, " [ [no]pacing ] [ refill_delay TIME ]\n"); 588d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet fprintf(stderr, " [ orphan_mask MASK]\n"); 59bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet} 60bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 61bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazetstatic unsigned int ilog2(unsigned int val) 62bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet{ 63bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet unsigned int res = 0; 64bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 65bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet val--; 66bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet while (val) { 67bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet res++; 68bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet val >>= 1; 69bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 70bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return res; 71bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet} 72bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 73bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazetstatic int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, 74bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet struct nlmsghdr *n) 75bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet{ 76aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang unsigned int plimit; 77aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang unsigned int flow_plimit; 78aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang unsigned int quantum; 79aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang unsigned int initial_quantum; 80bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet unsigned int buckets = 0; 81aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang unsigned int maxrate; 82aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang unsigned int defrate; 83565af7b8168416bb8432f9f10935b7897232e853Phil Sutter unsigned int refill_delay; 848d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet unsigned int orphan_mask; 85aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang bool set_plimit = false; 86aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang bool set_flow_plimit = false; 87aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang bool set_quantum = false; 88aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang bool set_initial_quantum = false; 89aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang bool set_maxrate = false; 90aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang bool set_defrate = false; 91565af7b8168416bb8432f9f10935b7897232e853Phil Sutter bool set_refill_delay = false; 928d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet bool set_orphan_mask = false; 93bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet int pacing = -1; 94bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet struct rtattr *tail; 95bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 96bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet while (argc > 0) { 97bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (strcmp(*argv, "limit") == 0) { 98bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet NEXT_ARG(); 99bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (get_unsigned(&plimit, *argv, 0)) { 100bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, "Illegal \"limit\"\n"); 101bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return -1; 102bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 103aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang set_plimit = true; 104bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } else if (strcmp(*argv, "flow_limit") == 0) { 105bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet NEXT_ARG(); 106bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (get_unsigned(&flow_plimit, *argv, 0)) { 107bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, "Illegal \"flow_limit\"\n"); 108bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return -1; 109bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 110aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang set_flow_plimit = true; 111bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } else if (strcmp(*argv, "buckets") == 0) { 112bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet NEXT_ARG(); 113bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (get_unsigned(&buckets, *argv, 0)) { 114bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, "Illegal \"buckets\"\n"); 115bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return -1; 116bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 117bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } else if (strcmp(*argv, "maxrate") == 0) { 118bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet NEXT_ARG(); 119bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (get_rate(&maxrate, *argv)) { 120bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, "Illegal \"maxrate\"\n"); 121bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return -1; 122bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 123aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang set_maxrate = true; 124bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } else if (strcmp(*argv, "defrate") == 0) { 125bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet NEXT_ARG(); 126bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (get_rate(&defrate, *argv)) { 127bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, "Illegal \"defrate\"\n"); 128bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return -1; 129bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 130aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang set_defrate = true; 131bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } else if (strcmp(*argv, "quantum") == 0) { 132bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet NEXT_ARG(); 133bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (get_unsigned(&quantum, *argv, 0)) { 134bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, "Illegal \"quantum\"\n"); 135bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return -1; 136bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 137aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang set_quantum = true; 138bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } else if (strcmp(*argv, "initial_quantum") == 0) { 139bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet NEXT_ARG(); 140bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (get_unsigned(&initial_quantum, *argv, 0)) { 141bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, "Illegal \"initial_quantum\"\n"); 142bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return -1; 143bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 144aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang set_initial_quantum = true; 1458d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet } else if (strcmp(*argv, "orphan_mask") == 0) { 1468d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet NEXT_ARG(); 1478d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet if (get_unsigned(&orphan_mask, *argv, 0)) { 1488d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet fprintf(stderr, "Illegal \"initial_quantum\"\n"); 1498d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet return -1; 1508d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet } 1518d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet set_orphan_mask = true; 152565af7b8168416bb8432f9f10935b7897232e853Phil Sutter } else if (strcmp(*argv, "refill_delay") == 0) { 153565af7b8168416bb8432f9f10935b7897232e853Phil Sutter NEXT_ARG(); 154565af7b8168416bb8432f9f10935b7897232e853Phil Sutter if (get_time(&refill_delay, *argv)) { 155565af7b8168416bb8432f9f10935b7897232e853Phil Sutter fprintf(stderr, "Illegal \"refill_delay\"\n"); 156565af7b8168416bb8432f9f10935b7897232e853Phil Sutter return -1; 157565af7b8168416bb8432f9f10935b7897232e853Phil Sutter } 158565af7b8168416bb8432f9f10935b7897232e853Phil Sutter set_refill_delay = true; 159bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } else if (strcmp(*argv, "pacing") == 0) { 160bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet pacing = 1; 161bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } else if (strcmp(*argv, "nopacing") == 0) { 162bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet pacing = 0; 163bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } else if (strcmp(*argv, "help") == 0) { 164bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet explain(); 165bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return -1; 166bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } else { 167bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(stderr, "What is \"%s\"?\n", *argv); 168bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet explain(); 169bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return -1; 170bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 171bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet argc--; argv++; 172bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 173bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 174bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet tail = NLMSG_TAIL(n); 175bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); 176bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (buckets) { 177bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet unsigned int log = ilog2(buckets); 178bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 179bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet addattr_l(n, 1024, TCA_FQ_BUCKETS_LOG, 180bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet &log, sizeof(log)); 181bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 182aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang if (set_plimit) 183bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet addattr_l(n, 1024, TCA_FQ_PLIMIT, 184bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet &plimit, sizeof(plimit)); 185aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang if (set_flow_plimit) 186bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet addattr_l(n, 1024, TCA_FQ_FLOW_PLIMIT, 187bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet &flow_plimit, sizeof(flow_plimit)); 188aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang if (set_quantum) 189bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet addattr_l(n, 1024, TCA_FQ_QUANTUM, &quantum, sizeof(quantum)); 190aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang if (set_initial_quantum) 191bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet addattr_l(n, 1024, TCA_FQ_INITIAL_QUANTUM, 192bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet &initial_quantum, sizeof(initial_quantum)); 193bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (pacing != -1) 194bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet addattr_l(n, 1024, TCA_FQ_RATE_ENABLE, 195bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet &pacing, sizeof(pacing)); 196aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang if (set_maxrate) 197bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet addattr_l(n, 1024, TCA_FQ_FLOW_MAX_RATE, 198bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet &maxrate, sizeof(maxrate)); 199aeb199d5ce86c6c72decaac333cad5a7d7b38b3aYang Yingliang if (set_defrate) 200bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet addattr_l(n, 1024, TCA_FQ_FLOW_DEFAULT_RATE, 201bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet &defrate, sizeof(defrate)); 202565af7b8168416bb8432f9f10935b7897232e853Phil Sutter if (set_refill_delay) 203565af7b8168416bb8432f9f10935b7897232e853Phil Sutter addattr_l(n, 1024, TCA_FQ_FLOW_REFILL_DELAY, 2048fe9839857d73b770b8aa4e2d9753c6a2c20ad6dStephen Hemminger &refill_delay, sizeof(refill_delay)); 2058d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet if (set_orphan_mask) 2068d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet addattr_l(n, 1024, TCA_FQ_ORPHAN_MASK, 2078fe9839857d73b770b8aa4e2d9753c6a2c20ad6dStephen Hemminger &orphan_mask, sizeof(refill_delay)); 208bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; 209bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return 0; 210bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet} 211bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 212bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazetstatic int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) 213bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet{ 214bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet struct rtattr *tb[TCA_FQ_MAX + 1]; 215bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet unsigned int plimit, flow_plimit; 216bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet unsigned int buckets_log; 217bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet int pacing; 218bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet unsigned int rate, quantum; 219565af7b8168416bb8432f9f10935b7897232e853Phil Sutter unsigned int refill_delay; 2208d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet unsigned int orphan_mask; 221bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet SPRINT_BUF(b1); 222bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 223bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (opt == NULL) 224bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return 0; 225bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 226bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet parse_rtattr_nested(tb, TCA_FQ_MAX, opt); 227bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 228bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (tb[TCA_FQ_PLIMIT] && 229bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet RTA_PAYLOAD(tb[TCA_FQ_PLIMIT]) >= sizeof(__u32)) { 230bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet plimit = rta_getattr_u32(tb[TCA_FQ_PLIMIT]); 231bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, "limit %up ", plimit); 232bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 233bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (tb[TCA_FQ_FLOW_PLIMIT] && 234bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet RTA_PAYLOAD(tb[TCA_FQ_FLOW_PLIMIT]) >= sizeof(__u32)) { 235bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet flow_plimit = rta_getattr_u32(tb[TCA_FQ_FLOW_PLIMIT]); 236bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, "flow_limit %up ", flow_plimit); 237bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 238bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (tb[TCA_FQ_BUCKETS_LOG] && 239bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet RTA_PAYLOAD(tb[TCA_FQ_BUCKETS_LOG]) >= sizeof(__u32)) { 240bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet buckets_log = rta_getattr_u32(tb[TCA_FQ_BUCKETS_LOG]); 241bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, "buckets %u ", 1U << buckets_log); 242bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 2438d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet if (tb[TCA_FQ_ORPHAN_MASK] && 2448d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet RTA_PAYLOAD(tb[TCA_FQ_ORPHAN_MASK]) >= sizeof(__u32)) { 2458d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet orphan_mask = rta_getattr_u32(tb[TCA_FQ_ORPHAN_MASK]); 2468d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet fprintf(f, "orphan_mask %u ", orphan_mask); 2478d5bd8c302952c24b803b30093c880393935bf87Eric Dumazet } 248bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (tb[TCA_FQ_RATE_ENABLE] && 249bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet RTA_PAYLOAD(tb[TCA_FQ_RATE_ENABLE]) >= sizeof(int)) { 250bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet pacing = rta_getattr_u32(tb[TCA_FQ_RATE_ENABLE]); 251bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (pacing == 0) 252bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, "nopacing "); 253bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 254bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (tb[TCA_FQ_QUANTUM] && 255bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet RTA_PAYLOAD(tb[TCA_FQ_QUANTUM]) >= sizeof(__u32)) { 256bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet quantum = rta_getattr_u32(tb[TCA_FQ_QUANTUM]); 257bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, "quantum %u ", quantum); 258bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 259bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (tb[TCA_FQ_INITIAL_QUANTUM] && 260bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet RTA_PAYLOAD(tb[TCA_FQ_INITIAL_QUANTUM]) >= sizeof(__u32)) { 261bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet quantum = rta_getattr_u32(tb[TCA_FQ_INITIAL_QUANTUM]); 262bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, "initial_quantum %u ", quantum); 263bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 264bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (tb[TCA_FQ_FLOW_MAX_RATE] && 265bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet RTA_PAYLOAD(tb[TCA_FQ_FLOW_MAX_RATE]) >= sizeof(__u32)) { 266bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet rate = rta_getattr_u32(tb[TCA_FQ_FLOW_MAX_RATE]); 267bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 268bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (rate != ~0U) 269bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, "maxrate %s ", sprint_rate(rate, b1)); 270bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 271bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (tb[TCA_FQ_FLOW_DEFAULT_RATE] && 272bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet RTA_PAYLOAD(tb[TCA_FQ_FLOW_DEFAULT_RATE]) >= sizeof(__u32)) { 273bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet rate = rta_getattr_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]); 274bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 275bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (rate != 0) 276bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, "defrate %s ", sprint_rate(rate, b1)); 277bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet } 278565af7b8168416bb8432f9f10935b7897232e853Phil Sutter if (tb[TCA_FQ_FLOW_REFILL_DELAY] && 279565af7b8168416bb8432f9f10935b7897232e853Phil Sutter RTA_PAYLOAD(tb[TCA_FQ_FLOW_REFILL_DELAY]) >= sizeof(__u32)) { 280565af7b8168416bb8432f9f10935b7897232e853Phil Sutter refill_delay = rta_getattr_u32(tb[TCA_FQ_FLOW_REFILL_DELAY]); 281565af7b8168416bb8432f9f10935b7897232e853Phil Sutter fprintf(f, "refill_delay %s ", sprint_time(refill_delay, b1)); 282565af7b8168416bb8432f9f10935b7897232e853Phil Sutter } 283bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 284bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return 0; 285bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet} 286bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 287bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazetstatic int fq_print_xstats(struct qdisc_util *qu, FILE *f, 288bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet struct rtattr *xstats) 289bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet{ 290bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet struct tc_fq_qd_stats *st; 291bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 292bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (xstats == NULL) 293bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return 0; 294bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 295bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (RTA_PAYLOAD(xstats) < sizeof(*st)) 296bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return -1; 297bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 298bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet st = RTA_DATA(xstats); 299bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 300bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, " %u flows (%u inactive, %u throttled)", 301bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet st->flows, st->inactive_flows, st->throttled_flows); 302bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 303bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (st->time_next_delayed_flow > 0) 304bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, ", next packet delay %llu ns", st->time_next_delayed_flow); 305bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 306bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, "\n %llu gc, %llu highprio", 307bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet st->gc_flows, st->highprio_packets); 308bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 309bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (st->tcp_retrans) 310bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, ", %llu retrans", st->tcp_retrans); 311bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 312bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, ", %llu throttled", st->throttled); 313bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 314bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (st->flows_plimit) 315bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, ", %llu flows_plimit", st->flows_plimit); 316bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 317bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet if (st->pkts_too_long || st->allocation_errors) 318bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet fprintf(f, "\n %llu too long pkts, %llu alloc errors\n", 319bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet st->pkts_too_long, st->allocation_errors); 320bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 321bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet return 0; 322bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet} 323bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet 324bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazetstruct qdisc_util fq_qdisc_util = { 325bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet .id = "fq", 326bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet .parse_qopt = fq_parse_opt, 327bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet .print_qopt = fq_print_opt, 328bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet .print_xstats = fq_print_xstats, 329bc113e46a3cd06973b37b13c06db3f5f459502f8Eric Dumazet}; 330