1 /* 2 * src/nl-qdisc-dump.c Dump qdisc attributes 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2006 Thomas Graf <tgraf (at) suug.ch> 10 */ 11 12 #include "utils.h" 13 #include <netlink/route/sch/fifo.h> 14 #include <netlink/route/sch/prio.h> 15 16 static void print_usage(void) 17 { 18 printf( 19 "Usage: nl-qdisc-add <ifindex> <handle> <parent> <kind>\n"); 20 exit(1); 21 } 22 23 static int parse_blackhole_opts(struct rtnl_qdisc *qdisc, char *argv[], 24 int argc) 25 { 26 return 0; 27 } 28 29 static int parse_pfifo_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc) 30 { 31 int err, limit; 32 33 if (argc > 0) { 34 if (argc != 2 || strcasecmp(argv[0], "limit")) { 35 fprintf(stderr, "Usage: ... pfifo limit <limit>\n"); 36 return -1; 37 } 38 39 limit = strtoul(argv[1], NULL, 0); 40 err = rtnl_qdisc_fifo_set_limit(qdisc, limit); 41 if (err < 0) { 42 fprintf(stderr, "%s\n", nl_geterror()); 43 return -1; 44 } 45 } 46 47 return 0; 48 } 49 50 static int parse_bfifo_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc) 51 { 52 int err, limit; 53 54 if (argc > 0) { 55 if (argc != 2 || strcasecmp(argv[0], "limit")) { 56 fprintf(stderr, "Usage: ... bfifo limit <limit>\n"); 57 return -1; 58 } 59 60 limit = nl_size2int(argv[1]); 61 if (limit < 0) { 62 fprintf(stderr, "Invalid value for limit.\n"); 63 return -1; 64 } 65 66 err = rtnl_qdisc_fifo_set_limit(qdisc, limit); 67 if (err < 0) { 68 fprintf(stderr, "%s\n", nl_geterror()); 69 return -1; 70 } 71 } 72 73 return 0; 74 } 75 76 static int parse_prio_opts(struct rtnl_qdisc *qdisc, char *argv[], int argc) 77 { 78 int i, err, bands; 79 uint8_t map[] = QDISC_PRIO_DEFAULT_PRIOMAP; 80 81 if (argc > 0) { 82 if (argc < 2 || strcasecmp(argv[0], "bands")) 83 goto usage; 84 85 bands = strtoul(argv[1], NULL, 0); 86 err = rtnl_qdisc_prio_set_bands(qdisc, bands); 87 if (err < 0) { 88 fprintf(stderr, "%s\n", nl_geterror()); 89 return -1; 90 } 91 } 92 93 if (argc > 2) { 94 if (argc < 5 || strcasecmp(argv[2], "map")) 95 goto usage; 96 97 for (i = 3; i < (argc & ~1U); i += 2) { 98 int prio, band; 99 100 prio = rtnl_str2prio(argv[i]); 101 if (prio < 0 || prio > sizeof(map)/sizeof(map[0])) { 102 fprintf(stderr, "Invalid priority \"%s\"\n", 103 argv[i]); 104 return -1; 105 } 106 107 band = strtoul(argv[i+1], NULL, 0); 108 109 map[prio] = band; 110 } 111 } 112 113 err = rtnl_qdisc_prio_set_priomap(qdisc, map, sizeof(map)); 114 if (err < 0) { 115 fprintf(stderr, "%s\n", nl_geterror()); 116 return -1; 117 } 118 119 return 0; 120 usage: 121 fprintf(stderr, "Usage: ... prio bands <nbands> map MAP\n" 122 "MAP := <prio> <band>\n"); 123 return -1; 124 } 125 126 int main(int argc, char *argv[]) 127 { 128 struct nl_sock *nlh; 129 struct rtnl_qdisc *qdisc; 130 uint32_t handle, parent; 131 int err = 1; 132 133 if (nltool_init(argc, argv) < 0) 134 return -1; 135 136 if (argc < 5 || !strcmp(argv[1], "-h")) 137 print_usage(); 138 139 nlh = nltool_alloc_handle(); 140 if (!nlh) 141 goto errout; 142 143 qdisc = rtnl_qdisc_alloc(); 144 if (!qdisc) 145 goto errout_free_handle; 146 147 rtnl_qdisc_set_ifindex(qdisc, strtoul(argv[1], NULL, 0)); 148 149 if (rtnl_tc_str2handle(argv[2], &handle) < 0) { 150 fprintf(stderr, "%s\n", nl_geterror()); 151 goto errout_free_qdisc; 152 } 153 154 if (rtnl_tc_str2handle(argv[3], &parent) < 0) { 155 fprintf(stderr, "%s\n", nl_geterror()); 156 goto errout_free_qdisc; 157 } 158 159 rtnl_qdisc_set_handle(qdisc, handle); 160 rtnl_qdisc_set_parent(qdisc, parent); 161 rtnl_qdisc_set_kind(qdisc, argv[4]); 162 163 if (!strcasecmp(argv[4], "blackhole")) 164 err = parse_blackhole_opts(qdisc, &argv[5], argc-5); 165 else if (!strcasecmp(argv[4], "pfifo")) 166 err = parse_pfifo_opts(qdisc, &argv[5], argc-5); 167 else if (!strcasecmp(argv[4], "bfifo")) 168 err = parse_bfifo_opts(qdisc, &argv[5], argc-5); 169 else if (!strcasecmp(argv[4], "prio")) 170 err = parse_prio_opts(qdisc, &argv[5], argc-5); 171 else { 172 fprintf(stderr, "Unknown qdisc \"%s\"\n", argv[4]); 173 goto errout_free_qdisc; 174 } 175 176 if (err < 0) 177 goto errout_free_qdisc; 178 179 if (nltool_connect(nlh, NETLINK_ROUTE) < 0) 180 goto errout_free_qdisc; 181 182 if (rtnl_qdisc_add(nlh, qdisc, NLM_F_REPLACE) < 0) { 183 fprintf(stderr, "Unable to add Qdisc: %s\n", nl_geterror()); 184 goto errout_close; 185 } 186 187 err = 0; 188 errout_close: 189 nl_close(nlh); 190 errout_free_qdisc: 191 rtnl_qdisc_put(qdisc); 192 errout_free_handle: 193 nl_handle_destroy(nlh); 194 errout: 195 return err; 196 } 197