tc.c

00001 /*
00002  * src/lib/tc.c     CLI Traffic Control Helpers
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 #include <netlink/cli/utils.h>
00013 #include <netlink/cli/tc.h>
00014 #include <netlink/route/tc-api.h>
00015 
00016 /**
00017  * @ingroup cli
00018  * @defgroup cli_tc Traffic Control
00019  * @{
00020  */
00021 void nl_cli_tc_parse_dev(struct rtnl_tc *tc, struct nl_cache *link_cache, char *name)
00022 {
00023         struct rtnl_link *link;
00024         
00025         link = rtnl_link_get_by_name(link_cache, name);
00026         if (!link)
00027                 nl_cli_fatal(ENOENT, "Link \"%s\" does not exist.", name);
00028 
00029         rtnl_tc_set_link(tc, link);
00030         rtnl_link_put(link);
00031 }
00032 
00033 void nl_cli_tc_parse_parent(struct rtnl_tc *tc, char *arg)
00034 {
00035         uint32_t parent;
00036         int err;
00037 
00038         if ((err = rtnl_tc_str2handle(arg, &parent)) < 0)
00039                 nl_cli_fatal(err, "Unable to parse handle \"%s\": %s",
00040                       arg, nl_geterror(err));
00041 
00042         rtnl_tc_set_parent(tc, parent);
00043 }
00044 
00045 void nl_cli_tc_parse_handle(struct rtnl_tc *tc, char *arg, int create)
00046 {
00047         uint32_t handle, parent;
00048         int err;
00049 
00050         parent = rtnl_tc_get_parent(tc);
00051 
00052         if ((err = rtnl_tc_str2handle(arg, &handle)) < 0) {
00053                 if (err == -NLE_OBJ_NOTFOUND && create)
00054                         err = rtnl_classid_generate(arg, &handle, parent);
00055 
00056                 if (err < 0)
00057                         nl_cli_fatal(err, "Unable to parse handle \"%s\": %s",
00058                                      arg, nl_geterror(err));
00059         }
00060 
00061         rtnl_tc_set_handle(tc, handle);
00062 }
00063 
00064 void nl_cli_tc_parse_mtu(struct rtnl_tc *tc, char *arg)
00065 {
00066         rtnl_tc_set_mtu(tc, nl_cli_parse_u32(arg));
00067 }
00068 
00069 void nl_cli_tc_parse_mpu(struct rtnl_tc *tc, char *arg)
00070 {
00071         rtnl_tc_set_mpu(tc, nl_cli_parse_u32(arg));
00072 }
00073 
00074 void nl_cli_tc_parse_overhead(struct rtnl_tc *tc, char *arg)
00075 {
00076         rtnl_tc_set_overhead(tc, nl_cli_parse_u32(arg));
00077 }
00078 
00079 void nl_cli_tc_parse_kind(struct rtnl_tc *tc, char *arg)
00080 {
00081         rtnl_tc_set_kind(tc, arg);
00082 }
00083 
00084 void nl_cli_tc_parse_linktype(struct rtnl_tc *tc, char *arg)
00085 {
00086         int type;
00087 
00088         if ((type = nl_str2llproto(arg)) < 0)
00089                 nl_cli_fatal(type, "Unable to parse linktype \"%s\": %s",
00090                         arg, nl_geterror(type));
00091 
00092         rtnl_tc_set_linktype(tc, type);
00093 }
00094 
00095 static NL_LIST_HEAD(tc_modules);
00096 
00097 struct nl_cli_tc_module *__nl_cli_tc_lookup(struct rtnl_tc_ops *ops)
00098 {
00099         struct nl_cli_tc_module *tm;
00100 
00101         nl_list_for_each_entry(tm, &tc_modules, tm_list)
00102                 if (tm->tm_ops == ops)
00103                         return tm;
00104 
00105         return NULL;
00106 }
00107 
00108 struct nl_cli_tc_module *nl_cli_tc_lookup(struct rtnl_tc_ops *ops)
00109 {
00110         struct nl_cli_tc_module *tm;
00111 
00112         if ((tm = __nl_cli_tc_lookup(ops)))
00113                 return tm;
00114 
00115         switch (ops->to_type) {
00116         case RTNL_TC_TYPE_QDISC:
00117         case RTNL_TC_TYPE_CLASS:
00118                 nl_cli_load_module("cli/qdisc", ops->to_kind);
00119                 break;
00120 
00121         case RTNL_TC_TYPE_CLS:
00122                 nl_cli_load_module("cli/cls", ops->to_kind);
00123                 break;
00124 
00125         default:
00126                 nl_cli_fatal(EINVAL, "BUG: unhandled TC object type %d",
00127                                 ops->to_type);
00128         }
00129 
00130         if (!(tm = __nl_cli_tc_lookup(ops)))  {
00131                 nl_cli_fatal(EINVAL, "Application bug: The shared library for "
00132                         "the tc object \"%s\" was successfully loaded but it "
00133                         "seems that module did not register itself",
00134                         ops->to_kind);
00135         }
00136 
00137         return tm;
00138 }
00139 
00140 void nl_cli_tc_register(struct nl_cli_tc_module *tm)
00141 {
00142         struct rtnl_tc_ops *ops;
00143 
00144         if (!(ops = rtnl_tc_lookup_ops(tm->tm_type, tm->tm_name))) {
00145                 nl_cli_fatal(ENOENT, "Unable to register CLI TC module "
00146                 "\"%s\": No matching libnl TC module found.", tm->tm_name);
00147         }
00148 
00149         if (__nl_cli_tc_lookup(ops)) {
00150                 nl_cli_fatal(EEXIST, "Unable to register CLI TC module "
00151                 "\"%s\": Module already registered.", tm->tm_name);
00152         }
00153 
00154         tm->tm_ops = ops;
00155 
00156         nl_list_add_tail(&tm->tm_list, &tc_modules);
00157 }
00158 
00159 void nl_cli_tc_unregister(struct nl_cli_tc_module *tm)
00160 {
00161         nl_list_del(&tm->tm_list);
00162 }
00163 
00164 
00165 /** @} */