dect
/
libnl
Archived
13
0
Fork 0

classid auto generation if provided tc name does not exist

Manually editing etc/libnl/classid before adding tc objects is a pain.
This patch adds code to attempt auto generating a unique tc id which
will then be assigned to the provided name and added to the classid
file.

This will make the following commands work with prior definitions of
the names "top" and "test"
	sudo sbin/nl-qdisc-add --dev eth0 --parent root --id top htb
	sudo sbin/nl-class-add --dev eth0 --parent top --id test htb --rate 100mbit

It will generate the following ids automatically:
4001:			top
4001:1			test
This commit is contained in:
Thomas Graf 2010-11-01 08:17:40 +01:00
parent 7903d6ab4b
commit 4267d8f336
14 changed files with 161 additions and 46 deletions

View File

@ -32,5 +32,14 @@ ffff:ffff root
ffff:fff1 ingress
#
# List your classid definitions below:
# List your classid definitions here:
#
###############################################################################
# List of auto-generated classids
#
# DO NOT ADD CLASSID DEFINITIONS BELOW THIS LINE
#
# <CLASSID> <NAME>

View File

@ -16,7 +16,7 @@
extern void nl_cli_tc_parse_dev(struct rtnl_tc *, struct nl_cache *, char *);
extern void nl_cli_tc_parse_parent(struct rtnl_tc *, char *);
extern void nl_cli_tc_parse_handle(struct rtnl_tc *, char *);
extern void nl_cli_tc_parse_handle(struct rtnl_tc *, char *, int);
extern void nl_cli_tc_parse_mtu(struct rtnl_tc *, char *);
extern void nl_cli_tc_parse_mpu(struct rtnl_tc *, char *);
extern void nl_cli_tc_parse_overhead(struct rtnl_tc *, char *);

View File

@ -66,6 +66,8 @@ extern int rtnl_tc_calc_cell_log(int);
extern int rtnl_tc_read_classid_file(void);
extern char * rtnl_tc_handle2str(uint32_t, char *, size_t);
extern int rtnl_tc_str2handle(const char *, uint32_t *);
extern int rtnl_classid_generate(const char *, uint32_t *,
uint32_t);
#ifdef __cplusplus
}

View File

@ -75,6 +75,20 @@ static int classid_lookup(const char *name, uint32_t *result)
return -NLE_OBJ_NOTFOUND;
}
static char *name_lookup(const uint32_t classid)
{
void *res;
struct classid_map cm = {
.classid = classid,
.name = "search entry",
};
if ((res = tfind(&cm, &id_root, &compare_id)))
return (*(struct classid_map **) res)->name;
return NULL;
}
/**
* @name Traffic Control Handle Translations
* @{
@ -101,14 +115,10 @@ char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
else if (TC_H_INGRESS == handle)
snprintf(buf, len, "ingress");
else {
void *res;
struct classid_map cm = {
.classid = handle,
.name = "search entry",
};
char *name;
if ((res = tfind(&cm, &id_root, &compare_id)))
snprintf(buf, len, "%s", (*(struct classid_map **) res)->name);
if ((name = name_lookup(handle)))
snprintf(buf, len, "%s", name);
else if (0 == TC_H_MAJ(handle))
snprintf(buf, len, ":%02x", TC_H_MIN(handle));
else if (0 == TC_H_MIN(handle))
@ -232,6 +242,15 @@ static void free_nothing(void *arg)
{
}
static void classid_map_free(struct classid_map *map)
{
if (!map)
return;
free(map->name);
free(map);
}
static void clear_hashtable(void)
{
int i;
@ -239,10 +258,8 @@ static void clear_hashtable(void)
for (i = 0; i < CLASSID_NAME_HT_SIZ; i++) {
struct classid_map *map, *n;
nl_list_for_each_entry_safe(map, n, &tbl_name[i], name_list) {
free(map->name);
free(map);
}
nl_list_for_each_entry_safe(map, n, &tbl_name[i], name_list)
classid_map_free(map);
nl_init_list_head(&tbl_name[i]);
@ -254,6 +271,28 @@ static void clear_hashtable(void)
}
}
static int classid_map_add(uint32_t classid, const char *name)
{
struct classid_map *map;
int n;
if (!(map = calloc(1, sizeof(*map))))
return -NLE_NOMEM;
map->classid = classid;
map->name = strdup(name);
n = classid_tbl_hash(map->name);
nl_list_add_tail(&map->name_list, &tbl_name[n]);
if (!tsearch((void *) map, &id_root, &compare_id)) {
classid_map_free(map);
return -NLE_NOMEM;
}
return 0;
}
/**
* (Re-)read classid file
*
@ -289,10 +328,8 @@ int rtnl_tc_read_classid_file(void)
clear_hashtable();
while (fgets(buf, sizeof(buf), fd)) {
struct classid_map *map;
uint32_t classid;
char *ptr, *tok;
int n;
/* ignore comments and empty lines */
if (*buf == '#' || *buf == '\n' || *buf == '\r')
@ -312,21 +349,8 @@ int rtnl_tc_read_classid_file(void)
goto errout_close;
}
if (!(map = calloc(1, sizeof(*map)))) {
err = -NLE_NOMEM;
if ((err = classid_map_add(classid, tok)) < 0)
goto errout_close;
}
map->classid = classid;
map->name = strdup(tok);
n = classid_tbl_hash(map->name);
nl_list_add_tail(&map->name_list, &tbl_name[n]);
if (!tsearch((void *) map, &id_root, &compare_id)) {
err = -NLE_NOMEM;
goto errout_close;
}
}
err = 0;
@ -341,6 +365,64 @@ errout:
}
int rtnl_classid_generate(const char *name, uint32_t *result, uint32_t parent)
{
static uint32_t base = 0x4000 << 16;
uint32_t classid;
char *path;
FILE *fd;
int err = 0;
if (parent == TC_H_ROOT || parent == TC_H_INGRESS) {
do {
base += (1 << 16);
if (base == TC_H_MAJ(TC_H_ROOT))
base = 0x4000 << 16;
} while (name_lookup(base));
classid = base;
} else {
classid = TC_H_MAJ(parent);
do {
if (++classid == TC_H_MIN(TC_H_ROOT))
return -NLE_RANGE;
} while (name_lookup(base));
}
NL_DBG(2, "Generated new classid %#x\n", classid);
if (asprintf(&path, "%s/classid", SYSCONFDIR) < 0)
return -NLE_NOMEM;
if (!(fd = fopen(path, "a"))) {
err = -nl_syserr2nlerr(errno);
goto errout;
}
fprintf(fd, "%x:", TC_H_MAJ(classid) >> 16);
if (TC_H_MIN(classid))
fprintf(fd, "%x", TC_H_MIN(classid));
fprintf(fd, "\t\t\t%s\n", name);
fclose(fd);
if ((err = classid_map_add(classid, name)) < 0) {
/*
* Error adding classid map, re-read classid file is best
* option here. It is likely to fail as well but better
* than nothing, entry was added to the file already anyway.
*/
rtnl_tc_read_classid_file();
}
*result = classid;
err = 0;
errout:
free(path);
return err;
}
/** @} */
static void __init classid_init(void)

View File

@ -42,14 +42,21 @@ void nl_cli_tc_parse_parent(struct rtnl_tc *tc, char *arg)
rtnl_tc_set_parent(tc, parent);
}
void nl_cli_tc_parse_handle(struct rtnl_tc *tc, char *arg)
void nl_cli_tc_parse_handle(struct rtnl_tc *tc, char *arg, int create)
{
uint32_t handle;
uint32_t handle, parent;
int err;
if ((err = rtnl_tc_str2handle(arg, &handle)) < 0)
nl_cli_fatal(err, "Unable to parse handle \"%s\": %s",
arg, nl_geterror(err));
parent = rtnl_tc_get_parent(tc);
if ((err = rtnl_tc_str2handle(arg, &handle)) < 0) {
if (err == -NLE_OBJ_NOTFOUND && create)
err = rtnl_classid_generate(arg, &handle, parent);
if (err < 0)
nl_cli_fatal(err, "Unable to parse handle \"%s\": %s",
arg, nl_geterror(err));
}
rtnl_tc_set_handle(tc, handle);
}

View File

@ -59,7 +59,7 @@ int main(int argc, char *argv[])
struct nl_cli_qdisc_module *qm;
struct rtnl_class_ops *ops;
int err, flags = NLM_F_CREATE | NLM_F_EXCL;
char *kind;
char *kind, *id = NULL;
sock = nl_cli_alloc_socket();
nl_cli_connect(sock, NETLINK_ROUTE);
@ -106,7 +106,7 @@ int main(int argc, char *argv[])
case 'v': nl_cli_print_version(); break;
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg); break;
case 'i': id = strdup(optarg); break;
case ARG_UPDATE: flags = NLM_F_CREATE; break;
case ARG_UPDATE_ONLY: flags = 0; break;
case ARG_MTU: nl_cli_tc_parse_mtu(tc, optarg); break;
@ -125,6 +125,11 @@ int main(int argc, char *argv[])
if (!rtnl_tc_get_parent(tc))
nl_cli_fatal(EINVAL, "You must specify a parent (--parent=XXX)");
if (id) {
nl_cli_tc_parse_handle(tc, id, 1);
free(id);
}
kind = argv[optind++];
rtnl_class_set_kind(class, kind);

View File

@ -109,7 +109,7 @@ int main(int argc, char *argv[])
case 'v': nl_cli_print_version(); break;
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
case 'k': nl_cli_class_parse_kind(class, optarg); break;
}
}

View File

@ -103,7 +103,7 @@ int main(int argc, char *argv[])
case 'v': nl_cli_print_version(); break;
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
case 'k': nl_cli_class_parse_kind(class, optarg); break;
}
}

View File

@ -59,7 +59,7 @@ int main(int argc, char *argv[])
struct nl_cli_cls_module *cm;
struct rtnl_cls_ops *ops;
int err, flags = NLM_F_CREATE | NLM_F_EXCL;
char *kind;
char *kind, *id = NULL;
sock = nl_cli_alloc_socket();
nl_cli_connect(sock, NETLINK_ROUTE);
@ -110,7 +110,7 @@ int main(int argc, char *argv[])
case 'v': nl_cli_print_version(); break;
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg); break;
case 'i': id = strdup(optarg); break;
case ARG_UPDATE: flags = NLM_F_CREATE; break;
case ARG_UPDATE_ONLY: flags = 0; break;
case ARG_MTU: nl_cli_tc_parse_mtu(tc, optarg); break;
@ -133,6 +133,11 @@ int main(int argc, char *argv[])
if (!rtnl_tc_get_parent(tc))
nl_cli_fatal(EINVAL, "You must specify a parent (--parent=XXX)");
if (id) {
nl_cli_tc_parse_handle(tc, id, 1);
free(id);
}
kind = argv[optind++];
rtnl_cls_set_kind(cls, kind);

View File

@ -134,7 +134,7 @@ int main(int argc, char *argv[])
case 'v': nl_cli_print_version(); break;
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
case 'k': nl_cli_cls_parse_kind(cls, optarg); break;
case ARG_PROTO: nl_cli_cls_parse_proto(cls, optarg); break;
case ARG_PRIO:

View File

@ -111,7 +111,7 @@ int main(int argc, char *argv[])
case 'v': nl_cli_print_version(); break;
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
case 'k': nl_cli_cls_parse_kind(cls, optarg); break;
case ARG_PROTO: nl_cli_cls_parse_proto(cls, optarg); break;
case ARG_PRIO:

View File

@ -56,7 +56,7 @@ int main(int argc, char *argv[])
struct nl_cli_qdisc_module *qm;
struct rtnl_qdisc_ops *ops;
int err, flags = NLM_F_CREATE | NLM_F_EXCL;
char *kind;
char *kind, *id = NULL;
sock = nl_cli_alloc_socket();
nl_cli_connect(sock, NETLINK_ROUTE);
@ -99,7 +99,7 @@ int main(int argc, char *argv[])
case 'v': nl_cli_print_version(); break;
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg); break;
case 'i': id = strdup(optarg); break;
case ARG_UPDATE: flags = NLM_F_CREATE; break;
case ARG_REPLACE: flags = NLM_F_CREATE | NLM_F_REPLACE; break;
case ARG_UPDATE_ONLY: flags = 0; break;
@ -116,6 +116,11 @@ int main(int argc, char *argv[])
if (!rtnl_tc_get_parent(tc))
nl_cli_fatal(EINVAL, "You must specify a parent");
if (id) {
nl_cli_tc_parse_handle(tc, id, 1);
free(id);
}
kind = argv[optind++];
rtnl_qdisc_set_kind(qdisc, kind);

View File

@ -115,7 +115,7 @@ int main(int argc, char *argv[])
break;
case 'i':
nfilter++;
nl_cli_tc_parse_handle(tc, optarg);
nl_cli_tc_parse_handle(tc, optarg, 0);
break;
case 'k':
nfilter++;

View File

@ -85,7 +85,7 @@ int main(int argc, char *argv[])
case 'v': nl_cli_print_version(); break;
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
case 'k': nl_cli_qdisc_parse_kind(qdisc, optarg); break;
}
}