1/* 2 * src/nl-qdisc-add.c Add Queueing Discipline 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) 2010 Thomas Graf <tgraf@suug.ch> 10 */ 11 12#include <netlink/cli/utils.h> 13#include <netlink/cli/tc.h> 14#include <netlink/cli/qdisc.h> 15#include <netlink/cli/link.h> 16 17#include <netlink-private/route/tc-api.h> 18 19static int quiet = 0; 20 21static void print_usage(void) 22{ 23 printf( 24"Usage: nl-qdisc-add [OPTIONS]... QDISC [CONFIGURATION]...\n" 25"\n" 26"OPTIONS\n" 27" -q, --quiet Do not print informal notifications.\n" 28" -h, --help Show this help text.\n" 29" -v, --version Show versioning information.\n" 30" --update Update qdisc if it exists.\n" 31" --replace Replace or update qdisc if it exists.\n" 32" --update-only Only update qdisc, never create it.\n" 33" --replace-only Only replace or update qdisc, never create it.\n" 34" -d, --dev=DEV Network device the qdisc should be attached to.\n" 35" -i, --id=ID ID of new qdisc (default: auto-generated)r\n" 36" -p, --parent=ID ID of parent { root | ingress | QDISC-ID }\n" 37"\n" 38"CONFIGURATION\n" 39" -h, --help Show help text of qdisc specific options.\n" 40"\n" 41"EXAMPLE\n" 42" $ nl-qdisc-add --dev=eth1 --parent=root htb --rate=100mbit\n" 43"\n" 44 ); 45 exit(0); 46} 47 48int main(int argc, char *argv[]) 49{ 50 struct nl_sock *sock; 51 struct rtnl_qdisc *qdisc; 52 struct rtnl_tc *tc; 53 struct nl_cache *link_cache; 54 struct nl_dump_params dp = { 55 .dp_type = NL_DUMP_DETAILS, 56 .dp_fd = stdout, 57 }; 58 struct nl_cli_tc_module *tm; 59 struct rtnl_tc_ops *ops; 60 int err, flags = NLM_F_CREATE | NLM_F_EXCL; 61 char *kind, *id = NULL; 62 63 sock = nl_cli_alloc_socket(); 64 nl_cli_connect(sock, NETLINK_ROUTE); 65 66 link_cache = nl_cli_link_alloc_cache(sock); 67 68 qdisc = nl_cli_qdisc_alloc(); 69 tc = (struct rtnl_tc *) qdisc; 70 71 for (;;) { 72 int c, optidx = 0; 73 enum { 74 ARG_REPLACE = 257, 75 ARG_UPDATE = 258, 76 ARG_REPLACE_ONLY, 77 ARG_UPDATE_ONLY, 78 }; 79 static struct option long_opts[] = { 80 { "quiet", 0, 0, 'q' }, 81 { "help", 0, 0, 'h' }, 82 { "version", 0, 0, 'v' }, 83 { "dev", 1, 0, 'd' }, 84 { "parent", 1, 0, 'p' }, 85 { "id", 1, 0, 'i' }, 86 { "replace", 0, 0, ARG_REPLACE }, 87 { "update", 0, 0, ARG_UPDATE }, 88 { "replace-only", 0, 0, ARG_REPLACE_ONLY }, 89 { "update-only", 0, 0, ARG_UPDATE_ONLY }, 90 { 0, 0, 0, 0 } 91 }; 92 93 c = getopt_long(argc, argv, "+qhvd:p:i:", 94 long_opts, &optidx); 95 if (c == -1) 96 break; 97 98 switch (c) { 99 case 'q': quiet = 1; break; 100 case 'h': print_usage(); break; 101 case 'v': nl_cli_print_version(); break; 102 case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; 103 case 'p': nl_cli_tc_parse_parent(tc, optarg); break; 104 case 'i': id = strdup(optarg); break; 105 case ARG_UPDATE: flags = NLM_F_CREATE; break; 106 case ARG_REPLACE: flags = NLM_F_CREATE | NLM_F_REPLACE; break; 107 case ARG_UPDATE_ONLY: flags = 0; break; 108 case ARG_REPLACE_ONLY: flags = NLM_F_REPLACE; break; 109 } 110 } 111 112 if (optind >= argc) 113 print_usage(); 114 115 if (!rtnl_tc_get_ifindex(tc)) 116 nl_cli_fatal(EINVAL, "You must specify a network device (--dev=XXX)"); 117 118 if (!rtnl_tc_get_parent(tc)) 119 nl_cli_fatal(EINVAL, "You must specify a parent"); 120 121 if (id) { 122 nl_cli_tc_parse_handle(tc, id, 1); 123 free(id); 124 } 125 126 kind = argv[optind++]; 127 rtnl_tc_set_kind(tc, kind); 128 129 if (!(ops = rtnl_tc_get_ops(tc))) 130 nl_cli_fatal(ENOENT, "Unknown qdisc \"%s\"", kind); 131 132 if (!(tm = nl_cli_tc_lookup(ops))) 133 nl_cli_fatal(ENOTSUP, "Qdisc type \"%s\" not supported.", kind); 134 135 tm->tm_parse_argv(tc, argc, argv); 136 137 if (!quiet) { 138 printf("Adding "); 139 nl_object_dump(OBJ_CAST(qdisc), &dp); 140 } 141 142 if ((err = rtnl_qdisc_add(sock, qdisc, flags)) < 0) 143 nl_cli_fatal(EINVAL, "Unable to add qdisc: %s", nl_geterror(err)); 144 145 return 0; 146} 147