1 /* 2 * src/lib/tc.c CLI Traffic Control Helpers 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 (at) suug.ch> 10 */ 11 12 #include <netlink/cli/utils.h> 13 #include <netlink/cli/tc.h> 14 #include <netlink-private/route/tc-api.h> 15 16 /** 17 * @ingroup cli 18 * @defgroup cli_tc Traffic Control 19 * @{ 20 */ 21 void nl_cli_tc_parse_dev(struct rtnl_tc *tc, struct nl_cache *link_cache, char *name) 22 { 23 struct rtnl_link *link; 24 25 link = rtnl_link_get_by_name(link_cache, name); 26 if (!link) 27 nl_cli_fatal(ENOENT, "Link \"%s\" does not exist.", name); 28 29 rtnl_tc_set_link(tc, link); 30 rtnl_link_put(link); 31 } 32 33 void nl_cli_tc_parse_parent(struct rtnl_tc *tc, char *arg) 34 { 35 uint32_t parent; 36 int err; 37 38 if ((err = rtnl_tc_str2handle(arg, &parent)) < 0) 39 nl_cli_fatal(err, "Unable to parse handle \"%s\": %s", 40 arg, nl_geterror(err)); 41 42 rtnl_tc_set_parent(tc, parent); 43 } 44 45 void nl_cli_tc_parse_handle(struct rtnl_tc *tc, char *arg, int create) 46 { 47 uint32_t handle, parent; 48 int err; 49 50 parent = rtnl_tc_get_parent(tc); 51 52 if ((err = rtnl_tc_str2handle(arg, &handle)) < 0) { 53 if (err == -NLE_OBJ_NOTFOUND && create) 54 err = rtnl_classid_generate(arg, &handle, parent); 55 56 if (err < 0) 57 nl_cli_fatal(err, "Unable to parse handle \"%s\": %s", 58 arg, nl_geterror(err)); 59 } 60 61 rtnl_tc_set_handle(tc, handle); 62 } 63 64 void nl_cli_tc_parse_mtu(struct rtnl_tc *tc, char *arg) 65 { 66 rtnl_tc_set_mtu(tc, nl_cli_parse_u32(arg)); 67 } 68 69 void nl_cli_tc_parse_mpu(struct rtnl_tc *tc, char *arg) 70 { 71 rtnl_tc_set_mpu(tc, nl_cli_parse_u32(arg)); 72 } 73 74 void nl_cli_tc_parse_overhead(struct rtnl_tc *tc, char *arg) 75 { 76 rtnl_tc_set_overhead(tc, nl_cli_parse_u32(arg)); 77 } 78 79 void nl_cli_tc_parse_kind(struct rtnl_tc *tc, char *arg) 80 { 81 rtnl_tc_set_kind(tc, arg); 82 } 83 84 void nl_cli_tc_parse_linktype(struct rtnl_tc *tc, char *arg) 85 { 86 int type; 87 88 if ((type = nl_str2llproto(arg)) < 0) 89 nl_cli_fatal(type, "Unable to parse linktype \"%s\": %s", 90 arg, nl_geterror(type)); 91 92 rtnl_tc_set_linktype(tc, type); 93 } 94 95 static NL_LIST_HEAD(tc_modules); 96 97 static struct nl_cli_tc_module *__nl_cli_tc_lookup(struct rtnl_tc_ops *ops) 98 { 99 struct nl_cli_tc_module *tm; 100 101 nl_list_for_each_entry(tm, &tc_modules, tm_list) 102 if (tm->tm_ops == ops) 103 return tm; 104 105 return NULL; 106 } 107 108 struct nl_cli_tc_module *nl_cli_tc_lookup(struct rtnl_tc_ops *ops) 109 { 110 struct nl_cli_tc_module *tm; 111 112 if ((tm = __nl_cli_tc_lookup(ops))) 113 return tm; 114 115 switch (ops->to_type) { 116 case RTNL_TC_TYPE_QDISC: 117 case RTNL_TC_TYPE_CLASS: 118 nl_cli_load_module("cli/qdisc", ops->to_kind); 119 break; 120 121 case RTNL_TC_TYPE_CLS: 122 nl_cli_load_module("cli/cls", ops->to_kind); 123 break; 124 125 default: 126 nl_cli_fatal(EINVAL, "BUG: unhandled TC object type %d", 127 ops->to_type); 128 } 129 130 if (!(tm = __nl_cli_tc_lookup(ops))) { 131 nl_cli_fatal(EINVAL, "Application bug: The shared library for " 132 "the tc object \"%s\" was successfully loaded but it " 133 "seems that module did not register itself", 134 ops->to_kind); 135 } 136 137 return tm; 138 } 139 140 void nl_cli_tc_register(struct nl_cli_tc_module *tm) 141 { 142 struct rtnl_tc_ops *ops; 143 144 if (!(ops = rtnl_tc_lookup_ops(tm->tm_type, tm->tm_name))) { 145 nl_cli_fatal(ENOENT, "Unable to register CLI TC module " 146 "\"%s\": No matching libnl TC module found.", tm->tm_name); 147 } 148 149 if (__nl_cli_tc_lookup(ops)) { 150 nl_cli_fatal(EEXIST, "Unable to register CLI TC module " 151 "\"%s\": Module already registered.", tm->tm_name); 152 } 153 154 tm->tm_ops = ops; 155 156 nl_list_add_tail(&tm->tm_list, &tc_modules); 157 } 158 159 void nl_cli_tc_unregister(struct nl_cli_tc_module *tm) 160 { 161 nl_list_del(&tm->tm_list); 162 } 163 164 165 /** @} */ 166