19 #include <netlink-private/netlink.h> 20 #include <netlink-private/tc.h> 21 #include <netlink/netlink.h> 22 #include <netlink/utils.h> 23 #include <netlink/route/tc.h> 32 #define CLASSID_NAME_HT_SIZ 256 34 static struct nl_list_head tbl_name[CLASSID_NAME_HT_SIZ];
36 static void *id_root = NULL;
38 static int compare_id(
const void *pa,
const void *pb)
43 if (ma->classid < mb->classid)
46 if (ma->classid > mb->classid)
53 static unsigned int classid_tbl_hash(
const char *str)
55 unsigned long hash = 5381;
59 hash = ((hash << 5) + hash) + c;
61 return hash % CLASSID_NAME_HT_SIZ;
64 static int classid_lookup(
const char *name, uint32_t *result)
67 int n = classid_tbl_hash(name);
69 nl_list_for_each_entry(map, &tbl_name[n], name_list) {
70 if (!strcasecmp(map->name, name)) {
71 *result = map->classid;
76 return -NLE_OBJ_NOTFOUND;
79 static char *name_lookup(
const uint32_t classid)
84 .name =
"search entry",
87 if ((res = tfind(&cm, &id_root, &compare_id)))
112 if (TC_H_ROOT == handle)
113 snprintf(buf, len,
"root");
114 else if (TC_H_UNSPEC == handle)
115 snprintf(buf, len,
"none");
116 else if (TC_H_INGRESS == handle)
117 snprintf(buf, len,
"ingress");
121 if ((name = name_lookup(handle)))
122 snprintf(buf, len,
"%s", name);
123 else if (0 == TC_H_MAJ(handle))
124 snprintf(buf, len,
":%x", TC_H_MIN(handle));
125 else if (0 == TC_H_MIN(handle))
126 snprintf(buf, len,
"%x:", TC_H_MAJ(handle) >> 16);
128 snprintf(buf, len,
"%x:%x",
129 TC_H_MAJ(handle) >> 16, TC_H_MIN(handle));
161 if (!strcasecmp(str,
"root")) {
166 if (!strcasecmp(str,
"none")) {
171 if (!strcasecmp(str,
"ingress")) {
176 h = strtoul(str, &colon, 16);
186 char name[64] = { 0 };
188 if (!(colon = strpbrk(str,
":"))) {
190 return classid_lookup(str, res);
194 if (len >=
sizeof(name))
197 memcpy(name, str, len);
199 if ((err = classid_lookup(name, &h)) < 0)
207 if (colon[1] ==
'\0')
221 if (
'\0' == colon[1]) {
229 l = strtoul(colon+1, &end, 16);
240 }
else if (
'\0' == *colon) {
249 static void free_nothing(
void *arg)
253 static void classid_map_free(
struct classid_map *map)
262 static void clear_hashtable(
void)
266 for (i = 0; i < CLASSID_NAME_HT_SIZ; i++) {
269 nl_list_for_each_entry_safe(map, n, &tbl_name[i], name_list)
270 classid_map_free(map);
272 nl_init_list_head(&tbl_name[i]);
277 tdestroy(&id_root, &free_nothing);
282 static int classid_map_add(uint32_t classid,
const char *name)
287 if (!(map = calloc(1,
sizeof(*map))))
290 map->classid = classid;
291 map->name = strdup(name);
293 n = classid_tbl_hash(map->name);
294 nl_list_add_tail(&map->name_list, &tbl_name[n]);
296 if (!tsearch((
void *) map, &id_root, &compare_id)) {
297 classid_map_free(map);
314 static time_t last_read;
316 char buf[256], *path;
320 if (build_sysconf_path(&path,
"classid") < 0)
324 if (stat(path, &st) == 0) {
326 if (last_read == st.st_mtime) {
332 if (!(fd = fopen(path,
"re"))) {
333 err = -nl_syserr2nlerr(errno);
339 while (fgets(buf,
sizeof(buf), fd)) {
344 if (*buf ==
'#' || *buf ==
'\n' || *buf ==
'\r')
348 if (!(tok = strtok_r(buf,
" \t", &ptr))) {
356 if (!(tok = strtok_r(NULL,
" \t\n\r#", &ptr))) {
361 if ((err = classid_map_add(classid, tok)) < 0)
366 last_read = st.st_mtime;
377 int rtnl_classid_generate(
const char *name, uint32_t *result, uint32_t parent)
379 static uint32_t base = 0x4000 << 16;
385 if (parent == TC_H_ROOT || parent == TC_H_INGRESS) {
388 if (base == TC_H_MAJ(TC_H_ROOT))
390 }
while (name_lookup(base));
394 classid = TC_H_MAJ(parent);
396 if (TC_H_MIN(++classid) == TC_H_MIN(TC_H_ROOT))
398 }
while (name_lookup(classid));
401 NL_DBG(2,
"Generated new classid %#x\n", classid);
403 if (build_sysconf_path(&path,
"classid") < 0)
406 if (!(fd = fopen(path,
"ae"))) {
407 err = -nl_syserr2nlerr(errno);
411 fprintf(fd,
"%x:", TC_H_MAJ(classid) >> 16);
412 if (TC_H_MIN(classid))
413 fprintf(fd,
"%x", TC_H_MIN(classid));
414 fprintf(fd,
"\t\t\t%s\n", name);
418 if ((err = classid_map_add(classid, name)) < 0) {
437 static void __init classid_init(
void)
441 for (i = 0; i < CLASSID_NAME_HT_SIZ; i++)
442 nl_init_list_head(&tbl_name[i]);
445 NL_DBG(1,
"Failed to read classid file: %s\n", nl_geterror(err));
448 static void free_map(
void *map)
454 static void __exit classid_exit(
void)
456 tdestroy(id_root, free_map);
int rtnl_tc_str2handle(const char *str, uint32_t *res)
Convert a charactering strint to a traffic control handle.
int rtnl_tc_read_classid_file(void)
(Re-)read classid file
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).