Home | History | Annotate | Download | only in src
      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