static int rsvp_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { int family = strcmp(qu->id, "rsvp") == 0 ? AF_INET : AF_INET6; struct tc_rsvp_pinfo pinfo; struct tc_police tp; struct tcmsg *t = NLMSG_DATA(n); int pinfo_ok = 0; struct rtattr *tail; memset(&pinfo, 0, sizeof(pinfo)); memset(&tp, 0, sizeof(tp)); if (handle) { if (get_u32(&t->tcm_handle, handle, 0)) { my_printf("Illegal \"handle\"\n"); return -1; } } if (argc == 0) return 0; tail = NLMSG_TAIL(n); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "session") == 0) { inet_prefix addr; NEXT_ARG(); if (get_addr_and_pi(&argc, &argv, &addr, &pinfo, 1, family)) { my_printf("Illegal \"session\"\n"); return -1; } addattr_l(n, 4096, TCA_RSVP_DST, &addr.data, addr.bytelen); if (pinfo.dpi.mask || pinfo.protocol) pinfo_ok++; continue; } else if (matches(*argv, "sender") == 0 || matches(*argv, "flowspec") == 0) { inet_prefix addr; NEXT_ARG(); if (get_addr_and_pi(&argc, &argv, &addr, &pinfo, 0, family)) { my_printf("Illegal \"sender\"\n"); return -1; } addattr_l(n, 4096, TCA_RSVP_SRC, &addr.data, addr.bytelen); if (pinfo.spi.mask || pinfo.protocol) pinfo_ok++; continue; } else if (matches("ipproto", *argv) == 0) { int num; NEXT_ARG(); num = inet_proto_a2n(*argv); if (num < 0) { my_printf("Illegal \"ipproto\"\n"); return -1; } pinfo.protocol = num; pinfo_ok++; } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { unsigned handle; NEXT_ARG(); if (get_tc_classid(&handle, *argv)) { my_printf("Illegal \"classid\"\n"); return -1; } addattr_l(n, 4096, TCA_RSVP_CLASSID, &handle, 4); } else if (strcmp(*argv, "tunnelid") == 0) { unsigned tid; NEXT_ARG(); if (get_unsigned(&tid, *argv, 0)) { my_printf("Illegal \"tunnelid\"\n"); return -1; } pinfo.tunnelid = tid; pinfo_ok++; } else if (strcmp(*argv, "tunnel") == 0) { unsigned tid; NEXT_ARG(); if (get_unsigned(&tid, *argv, 0)) { my_printf("Illegal \"tunnel\"\n"); return -1; } addattr_l(n, 4096, TCA_RSVP_CLASSID, &tid, 4); NEXT_ARG(); if (strcmp(*argv, "skip") == 0) { NEXT_ARG(); } if (get_unsigned(&tid, *argv, 0)) { my_printf("Illegal \"skip\"\n"); return -1; } pinfo.tunnelhdr = tid; pinfo_ok++; } else if (matches(*argv, "police") == 0) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_RSVP_POLICE, n)) { my_printf("Illegal \"police\"\n"); return -1; } continue; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { my_printf("What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } if (pinfo_ok) addattr_l(n, 4096, TCA_RSVP_PINFO, &pinfo, sizeof(pinfo)); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
static int parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { int argc = *argc_p; char **argv = *argv_p; int ok = 0; struct rtattr *tail; unsigned int tmp; __u16 queue_mapping, ptype; __u32 flags = 0, priority, mark; struct tc_skbedit sel = { 0 }; if (matches(*argv, "skbedit") != 0) return -1; NEXT_ARG(); while (argc > 0) { if (matches(*argv, "queue_mapping") == 0) { flags |= SKBEDIT_F_QUEUE_MAPPING; NEXT_ARG(); if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) { fprintf(stderr, "Illegal queue_mapping\n"); return -1; } queue_mapping = tmp; ok++; } else if (matches(*argv, "priority") == 0) { flags |= SKBEDIT_F_PRIORITY; NEXT_ARG(); if (get_tc_classid(&priority, *argv)) { fprintf(stderr, "Illegal priority\n"); return -1; } ok++; } else if (matches(*argv, "mark") == 0) { flags |= SKBEDIT_F_MARK; NEXT_ARG(); if (get_u32(&mark, *argv, 0)) { fprintf(stderr, "Illegal mark\n"); return -1; } ok++; } else if (matches(*argv, "ptype") == 0) { NEXT_ARG(); if (matches(*argv, "host") == 0) { ptype = PACKET_HOST; } else if (matches(*argv, "broadcast") == 0) { ptype = PACKET_BROADCAST; } else if (matches(*argv, "multicast") == 0) { ptype = PACKET_MULTICAST; } else if (matches(*argv, "otherhost") == 0) { ptype = PACKET_OTHERHOST; } else { fprintf(stderr, "Illegal ptype (%s)\n", *argv); return -1; } flags |= SKBEDIT_F_PTYPE; ok++; } else if (matches(*argv, "help") == 0) { usage(); } else { break; } argc--; argv++; } parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_PIPE); if (argc) { if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&sel.index, *argv, 10)) { fprintf(stderr, "Pedit: Illegal \"index\"\n"); return -1; } argc--; argv++; ok++; } } if (!ok) { explain(); return -1; } tail = addattr_nest(n, MAX_MSG, tca_id); addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel)); if (flags & SKBEDIT_F_QUEUE_MAPPING) addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING, &queue_mapping, sizeof(queue_mapping)); if (flags & SKBEDIT_F_PRIORITY) addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY, &priority, sizeof(priority)); if (flags & SKBEDIT_F_MARK) addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK, &mark, sizeof(mark)); if (flags & SKBEDIT_F_PTYPE) addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE, &ptype, sizeof(ptype)); addattr_nest_end(n, tail); *argc_p = argc; *argv_p = argv; return 0; }
int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv) { struct qdisc_util *q = NULL; struct tc_estimator est; char d[16]; char k[16]; struct { struct nlmsghdr n; struct tcmsg t; char buf[TCA_BUF_MAX]; } req; memset(&req, 0, sizeof(req)); memset(&est, 0, sizeof(est)); memset(&d, 0, sizeof(d)); memset(&k, 0, sizeof(k)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.t.tcm_family = AF_UNSPEC; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if (d[0]) duparg("dev", *argv); strncpy(d, *argv, sizeof(d)-1); } else if (strcmp(*argv, "handle") == 0) { __u32 handle; if (req.t.tcm_handle) duparg("handle", *argv); NEXT_ARG(); if (get_qdisc_handle(&handle, *argv)) invarg(*argv, "invalid qdisc ID"); req.t.tcm_handle = handle; } else if (strcmp(*argv, "root") == 0) { if (req.t.tcm_parent) { fprintf(stderr, "Error: \"root\" is duplicate parent ID\n"); return -1; } req.t.tcm_parent = TC_H_ROOT; #ifdef TC_H_INGRESS } else if (strcmp(*argv, "ingress") == 0) { if (req.t.tcm_parent) { fprintf(stderr, "Error: \"ingress\" is a duplicate parent ID\n"); return -1; } req.t.tcm_parent = TC_H_INGRESS; strncpy(k, "ingress", sizeof(k)-1); q = get_qdisc_kind(k); req.t.tcm_handle = 0xffff0000; argc--; argv++; break; #endif } else if (strcmp(*argv, "parent") == 0) { __u32 handle; NEXT_ARG(); if (req.t.tcm_parent) duparg("parent", *argv); if (get_tc_classid(&handle, *argv)) invarg(*argv, "invalid parent ID"); req.t.tcm_parent = handle; } else if (matches(*argv, "estimator") == 0) { if (parse_estimator(&argc, &argv, &est)) return -1; } else if (matches(*argv, "help") == 0) { usage(); } else { strncpy(k, *argv, sizeof(k)-1); q = get_qdisc_kind(k); argc--; argv++; break; } argc--; argv++; } if (k[0]) addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1); if (est.ewma_log) addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est)); if (q) { if (!q->parse_qopt) { fprintf(stderr, "qdisc '%s' does not support option parsing\n", k); return -1; } if (q->parse_qopt(q, argc, argv, &req.n)) return 1; } else { if (argc) { if (matches(*argv, "help") == 0) usage(); fprintf(stderr, "Garbage instead of arguments \"%s ...\". Try \"tc qdisc help\".\n", *argv); return -1; } } if (d[0]) { int idx; ll_init_map(&rth); if ((idx = ll_name_to_index(d)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", d); return 1; } req.t.tcm_ifindex = idx; } if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) return 2; return 0; }
static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv) { struct qdisc_util *q = NULL; struct tc_estimator est; struct { struct tc_sizespec szopts; __u16 *data; } stab; char d[16]; char k[16]; struct { struct nlmsghdr n; struct tcmsg t; char buf[TCA_BUF_MAX]; } req; memset(&req, 0, sizeof(req)); memset(&stab, 0, sizeof(stab)); memset(&est, 0, sizeof(est)); memset(&d, 0, sizeof(d)); memset(&k, 0, sizeof(k)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.t.tcm_family = AF_UNSPEC; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if (d[0]) duparg("dev", *argv); strncpy(d, *argv, sizeof(d)-1); } else if (strcmp(*argv, "handle") == 0) { __u32 handle; if (req.t.tcm_handle) duparg("handle", *argv); NEXT_ARG(); if (get_qdisc_handle(&handle, *argv)) invarg("invalid qdisc ID", *argv); req.t.tcm_handle = handle; } else if (strcmp(*argv, "root") == 0) { if (req.t.tcm_parent) { fprintf(stderr, "Error: \"root\" is duplicate parent ID\n"); return -1; } req.t.tcm_parent = TC_H_ROOT; } else if (strcmp(*argv, "clsact") == 0) { if (req.t.tcm_parent) { fprintf(stderr, "Error: \"clsact\" is a duplicate parent ID\n"); return -1; } req.t.tcm_parent = TC_H_CLSACT; strncpy(k, "clsact", sizeof(k) - 1); q = get_qdisc_kind(k); req.t.tcm_handle = TC_H_MAKE(TC_H_CLSACT, 0); NEXT_ARG_FWD(); break; } else if (strcmp(*argv, "ingress") == 0) { if (req.t.tcm_parent) { fprintf(stderr, "Error: \"ingress\" is a duplicate parent ID\n"); return -1; } req.t.tcm_parent = TC_H_INGRESS; strncpy(k, "ingress", sizeof(k) - 1); q = get_qdisc_kind(k); req.t.tcm_handle = TC_H_MAKE(TC_H_INGRESS, 0); NEXT_ARG_FWD(); break; } else if (strcmp(*argv, "parent") == 0) { __u32 handle; NEXT_ARG(); if (req.t.tcm_parent) duparg("parent", *argv); if (get_tc_classid(&handle, *argv)) invarg("invalid parent ID", *argv); req.t.tcm_parent = handle; } else if (matches(*argv, "estimator") == 0) { if (parse_estimator(&argc, &argv, &est)) return -1; } else if (matches(*argv, "stab") == 0) { if (parse_size_table(&argc, &argv, &stab.szopts) < 0) return -1; continue; } else if (matches(*argv, "help") == 0) { usage(); } else { strncpy(k, *argv, sizeof(k)-1); q = get_qdisc_kind(k); argc--; argv++; break; } argc--; argv++; } if (k[0]) addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1); if (est.ewma_log) addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est)); if (q) { if (q->parse_qopt) { if (q->parse_qopt(q, argc, argv, &req.n)) return 1; } else if (argc) { fprintf(stderr, "qdisc '%s' does not support option parsing\n", k); return -1; } } else { if (argc) { if (matches(*argv, "help") == 0) usage(); fprintf(stderr, "Garbage instead of arguments \"%s ...\". Try \"tc qdisc help\".\n", *argv); return -1; } } if (check_size_table_opts(&stab.szopts)) { struct rtattr *tail; if (tc_calc_size_table(&stab.szopts, &stab.data) < 0) { fprintf(stderr, "failed to calculate size table.\n"); return -1; } tail = NLMSG_TAIL(&req.n); addattr_l(&req.n, sizeof(req), TCA_STAB, NULL, 0); addattr_l(&req.n, sizeof(req), TCA_STAB_BASE, &stab.szopts, sizeof(stab.szopts)); if (stab.data) addattr_l(&req.n, sizeof(req), TCA_STAB_DATA, stab.data, stab.szopts.tsize * sizeof(__u16)); tail->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail; if (stab.data) free(stab.data); } if (d[0]) { int idx; ll_init_map(&rth); if ((idx = ll_name_to_index(d)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", d); return 1; } req.t.tcm_ifindex = idx; } if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) return 2; return 0; }
static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct tc_police tp; struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; memset(&tp, 0, sizeof(tp)); if (handle) { if (get_u32(&t->tcm_handle, handle, 0)) { fprintf(stderr, "Illegal \"handle\"\n"); return -1; } } if (argc == 0) return 0; tail = NLMSG_TAIL(n); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "classid") == 0 || matches(*argv, "flowid") == 0) { unsigned handle; NEXT_ARG(); if (get_tc_classid(&handle, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } addattr_l(n, 4096, TCA_FW_CLASSID, &handle, 4); } else if (matches(*argv, "police") == 0) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_FW_POLICE, n)) { fprintf(stderr, "Illegal \"police\"\n"); return -1; } continue; } else if (matches(*argv, "action") == 0) { NEXT_ARG(); if (parse_action(&argc, &argv, TCA_FW_ACT, n)) { fprintf(stderr, "Illegal fw \"action\"\n"); return -1; } continue; } else if (strcmp(*argv, "indev") == 0) { char d[IFNAMSIZ+1]; memset(d, 0, sizeof (d)); argc--; argv++; if (argc < 1) { fprintf(stderr, "Illegal indev\n"); return -1; } strncpy(d, *argv, sizeof (d) - 1); addattr_l(n, MAX_MSG, TCA_FW_INDEV, d, strlen(d) + 1); } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv) { struct qdisc_util *q = NULL; struct tc_estimator est; struct { struct tc_sizespec szopts; __u16 *data; } stab; char d[16]; char k[16]; struct { struct nlmsghdr n; struct tcmsg t; char buf[TCA_BUF_MAX]; } * req; req = vmalloc(sizeof(*req)); memset(req, 0, sizeof(*req)); memset(&stab, 0, sizeof(stab)); memset(&est, 0, sizeof(est)); memset(&d, 0, sizeof(d)); memset(&k, 0, sizeof(k)); req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)); req->n.nlmsg_flags = NLM_F_REQUEST|flags; req->n.nlmsg_type = cmd; req->t.tcm_family = AF_UNSPEC; /* printk(KERN_DEBUG "NLM_F_CREATE: %d\n", NLM_F_CREATE); printk(KERN_DEBUG "NLM_F_REPLACE: %d\n", NLM_F_REPLACE); printk(KERN_DEBUG "NLM_F_REQUEST: %d\n", NLM_F_REQUEST); printk(KERN_DEBUG "NLM_F_EXCL: %d\n", NLM_F_EXCL); printk(KERN_DEBUG "RTM_NEWQDISC: %d\n", RTM_NEWQDISC); printk(KERN_DEBUG "RTM_DELQDISC: %d\n", RTM_DELQDISC); printk(KERN_DEBUG "cmd: %d\n", cmd); printk(KERN_DEBUG "req: %d\n", sizeof(*req)); */ while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); // Mangia un argomento if (d[0]) duparg("dev", *argv); strncpy(d, *argv, sizeof(d)-1); } else if (strcmp(*argv, "handle") == 0) { __u32 handle; //unsigned long? if (req->t.tcm_handle) duparg("handle", *argv); NEXT_ARG(); // Mangia un argomento if (get_qdisc_handle(&handle, *argv)) invarg("invalid qdisc ID", *argv); req->t.tcm_handle = handle; } else if (strcmp(*argv, "root") == 0) { if (req->t.tcm_parent) { printk(KERN_DEBUG "[MAT] Error: \"root\" is duplicate parent ID\n"); return -1; } req->t.tcm_parent = TC_H_ROOT; } else if (strcmp(*argv, "parent") == 0) { __u32 handle; NEXT_ARG(); if (req->t.tcm_parent) duparg("parent", *argv); if (get_tc_classid(&handle, *argv)) invarg("invalid parent ID", *argv); req->t.tcm_parent = handle; } /* else if (matches(*argv, "estimator") == 0) { if (parse_estimator(&argc, &argv, &est)) return -1; } */ else if (matches(*argv, "stab") == 0) { if (parse_size_table(&argc, &argv, &stab.szopts) < 0) return -1; continue; } else if (matches(*argv, "help") == 0) { usage(); } else { strncpy(k, *argv, sizeof(k)-1); q = get_qdisc_kind(k); argc--; argv++; break; } argc--; argv++; } if (k[0]) addattr_l(&req->n, sizeof(*req), TCA_KIND, k, strlen(k)+1); if (est.ewma_log) addattr_l(&req->n, sizeof(*req), TCA_RATE, &est, sizeof(est)); if (q) { if (!q->parse_qopt) { printk(KERN_DEBUG "[MAT] qdisc '%s' does not support option parsing\n", k); return -1; } if (q->parse_qopt(q, argc, argv, &req->n)) return 1; } else { if (argc) { if (matches(*argv, "help") == 0) usage(); printk(KERN_DEBUG "[MAT] Garbage instead of arguments \"%s ...\". Try \"tc qdisc help\".\n", *argv); return -1; } } if (check_size_table_opts(&stab.szopts)) { struct rtattr *tail; if (tc_calc_size_table(&stab.szopts, &stab.data) < 0) { printk(KERN_DEBUG "[MAT] failed to calculate size table.\n"); return -1; } tail = NLMSG_TAIL(&req->n); addattr_l(&req->n, sizeof(*req), TCA_STAB, NULL, 0); addattr_l(&req->n, sizeof(*req), TCA_STAB_BASE, &stab.szopts, sizeof(stab.szopts)); if (stab.data) addattr_l(&req->n, sizeof(*req), TCA_STAB_DATA, stab.data, stab.szopts.tsize * sizeof(__u16)); tail->rta_len = (void *)NLMSG_TAIL(&req->n) - (void *)tail; if (stab.data) vfree(stab.data); } /* if (d[0]) { int idx; ll_init_map(&rth); if ((idx = ll_name_to_index(d)) == 0) { printk(KERN_DEBUG "[MAT] Cannot find device \"%s\"\n", d); return 1; } req->t.tcm_ifindex = idx; } */ if (rtnl_talk(&rth, &req->n, 0, 0, NULL) < 0) return 2; return 0; }
static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct { struct tc_u32_sel sel; struct tc_u32_key keys[128]; } sel; struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; int sel_ok = 0; int sample_ok = 0; __u32 htid = 0; __u32 order = 0; memset(&sel, 0, sizeof(sel)); if (handle && get_u32_handle(&t->tcm_handle, handle)) { fprintf(stderr, "Illegal filter ID\n"); return -1; } if (argc == 0) return 0; tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len)); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "match") == 0) { NEXT_ARG(); if (parse_selector(&argc, &argv, &sel.sel)) { fprintf(stderr, "Illegal \"match\"\n"); return -1; } sel_ok++; continue; } else if (matches(*argv, "offset") == 0) { NEXT_ARG(); if (parse_offset(&argc, &argv, &sel.sel)) { fprintf(stderr, "Illegal \"offset\"\n"); return -1; } continue; } else if (matches(*argv, "hashkey") == 0) { NEXT_ARG(); if (parse_hashkey(&argc, &argv, &sel.sel)) { fprintf(stderr, "Illegal \"hashkey\"\n"); return -1; } continue; } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { unsigned handle; NEXT_ARG(); if (get_tc_classid(&handle, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } addattr_l(n, 4096, TCA_U32_CLASSID, &handle, 4); sel.sel.flags |= TC_U32_TERMINAL; } else if (matches(*argv, "divisor") == 0) { unsigned divisor; NEXT_ARG(); if (get_unsigned(&divisor, *argv, 0) || divisor == 0 || divisor > 0x100) { fprintf(stderr, "Illegal \"divisor\"\n"); return -1; } addattr_l(n, 4096, TCA_U32_DIVISOR, &divisor, 4); } else if (matches(*argv, "order") == 0) { NEXT_ARG(); if (get_u32(&order, *argv, 0)) { fprintf(stderr, "Illegal \"order\"\n"); return -1; } } else if (strcmp(*argv, "link") == 0) { unsigned handle; NEXT_ARG(); if (get_u32_handle(&handle, *argv)) { fprintf(stderr, "Illegal \"link\"\n"); return -1; } if (handle && TC_U32_NODE(handle)) { fprintf(stderr, "\"link\" must be a hash table.\n"); return -1; } addattr_l(n, 4096, TCA_U32_LINK, &handle, 4); } else if (strcmp(*argv, "ht") == 0) { unsigned handle; NEXT_ARG(); if (get_u32_handle(&handle, *argv)) { fprintf(stderr, "Illegal \"ht\"\n"); return -1; } if (handle && TC_U32_NODE(handle)) { fprintf(stderr, "\"ht\" must be a hash table.\n"); return -1; } if (sample_ok) htid = (htid&0xFF000)|(handle&0xFFF00000); else htid = (handle&0xFFFFF000); } else if (strcmp(*argv, "sample") == 0) { __u32 hash; struct { struct tc_u32_sel sel; struct tc_u32_key keys[4]; } sel2; NEXT_ARG(); if (parse_selector(&argc, &argv, &sel2.sel)) { fprintf(stderr, "Illegal \"sample\"\n"); return -1; } if (sel2.sel.nkeys != 1) { fprintf(stderr, "\"sample\" must contain exactly ONE key.\n"); return -1; } hash = sel2.sel.keys[0].val&sel2.sel.keys[0].mask; hash ^= hash>>16; hash ^= hash>>8; htid = ((hash<<12)&0xFF000)|(htid&0xFFF00000); sample_ok = 1; continue; #ifdef TC_CONFIG_ALL } else if (matches(*argv, "police") == 0) {
static int basic_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; long h = 0; if (argc == 0) return 0; if (handle) { h = strtol(handle, NULL, 0); if (h == LONG_MIN || h == LONG_MAX) { fprintf(stderr, "Illegal handle \"%s\", must be numeric.\n", handle); return -1; } } t->tcm_handle = h; tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len)); addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "match") == 0) { NEXT_ARG(); if (parse_ematch(&argc, &argv, TCA_BASIC_EMATCHES, n)) { fprintf(stderr, "Illegal \"ematch\"\n"); return -1; } continue; } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { unsigned handle; NEXT_ARG(); if (get_tc_classid(&handle, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } addattr_l(n, MAX_MSG, TCA_BASIC_CLASSID, &handle, 4); } else if (matches(*argv, "action") == 0) { NEXT_ARG(); if (parse_action(&argc, &argv, TCA_BASIC_ACT, n)) { fprintf(stderr, "Illegal \"action\"\n"); return -1; } continue; } else if (matches(*argv, "police") == 0) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_BASIC_POLICE, n)) { fprintf(stderr, "Illegal \"police\"\n"); return -1; } continue; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } tail->rta_len = (((void*)n)+n->nlmsg_len) - (void*)tail; return 0; }
static int atm_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct sockaddr_atmsvc addr; struct atm_qos qos; struct atm_sap sap; unsigned char hdr[MAX_HDR_LEN]; __u32 excess = 0; struct rtattr *tail; int sndbuf = 0; int hdr_len = -1; int set_clip = 0; int s; memset(&addr,0,sizeof(addr)); (void) text2qos("aal5,ubr:sdu=9180,rx:none",&qos,0); (void) text2sap("blli:l2=iso8802",&sap,0); while (argc > 0) { if (!strcmp(*argv,"pvc")) { NEXT_ARG(); if (text2atm(*argv,(struct sockaddr *) &addr, sizeof(addr),T2A_PVC | T2A_NAME) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"svc")) { NEXT_ARG(); if (text2atm(*argv,(struct sockaddr *) &addr, sizeof(addr),T2A_SVC | T2A_NAME) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"qos")) { NEXT_ARG(); if (text2qos(*argv,&qos,0) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"sndbuf")) { char *end; NEXT_ARG(); sndbuf = strtol(*argv,&end,0); if (*end) { explain(); return -1; } } else if (!strcmp(*argv,"sap")) { NEXT_ARG(); if (addr.sas_family != AF_ATMSVC || text2sap(*argv,&sap,T2A_NAME) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"hdr")) { unsigned char *ptr; char *walk; NEXT_ARG(); ptr = hdr; for (walk = *argv; *walk; walk++) { int tmp; if (ptr == hdr+MAX_HDR_LEN) { // fprintf(stderr,"header is too long\n"); return -1; } if (*walk == '.') continue; if (!isxdigit(walk[0]) || !walk[1] || !isxdigit(walk[1])) { explain(); return -1; } sscanf(walk,"%2x",&tmp); *ptr++ = tmp; walk++; } hdr_len = ptr-hdr; } else if (!strcmp(*argv,"excess")) { NEXT_ARG(); if (!strcmp(*argv,"clp")) excess = 0; else if (get_tc_classid(&excess,*argv)) { explain(); return -1; } } else if (!strcmp(*argv,"clip")) { set_clip = 1; } else { explain(); return 1; } argc--; argv++; } s = socket(addr.sas_family,SOCK_DGRAM,0); if (s < 0) { // perror("socket"); return -1; } if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { // perror("SO_ATMQOS"); return -1; } if (sndbuf) if (setsockopt(s,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { // perror("SO_SNDBUF"); return -1; } if (addr.sas_family == AF_ATMSVC && setsockopt(s,SOL_ATM,SO_ATMSAP, &sap,sizeof(sap)) < 0) { // perror("SO_ATMSAP"); return -1; } if (connect(s,(struct sockaddr *) &addr,addr.sas_family == AF_ATMPVC ? sizeof(struct sockaddr_atmpvc) : sizeof(addr)) < 0) { /// perror("connect"); return -1; } if (set_clip) if (ioctl(s,ATMARP_MKIP,0) < 0) { // perror("ioctl ATMARP_MKIP"); return -1; } tail = NLMSG_TAIL(n); addattr_l(n,1024,TCA_OPTIONS,NULL,0); addattr_l(n,1024,TCA_ATM_FD,&s,sizeof(s)); if (excess) addattr_l(n,1024,TCA_ATM_EXCESS,&excess,sizeof(excess)); if (hdr_len != -1) addattr_l(n,1024,TCA_ATM_HDR,hdr,hdr_len); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
static int tcindex_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; char *end; if (handle) { t->tcm_handle = strtoul(handle,&end,0); if (*end) { fprintf(stderr, "Illegal filter ID\n"); return -1; } } if (!argc) return 0; tail = NLMSG_TAIL(n); addattr_l(n,4096,TCA_OPTIONS,NULL,0); while (argc) { if (!strcmp(*argv,"hash")) { int hash; NEXT_ARG(); hash = strtoul(*argv,&end,0); if (*end || !hash || hash > 0x10000) { explain(); return -1; } addattr_l(n,4096,TCA_TCINDEX_HASH,&hash,sizeof(hash)); } else if (!strcmp(*argv,"mask")) { __u16 mask; NEXT_ARG(); mask = strtoul(*argv,&end,0); if (*end) { explain(); return -1; } addattr_l(n,4096,TCA_TCINDEX_MASK,&mask,sizeof(mask)); } else if (!strcmp(*argv,"shift")) { int shift; NEXT_ARG(); shift = strtoul(*argv,&end,0); if (*end) { explain(); return -1; } addattr_l(n,4096,TCA_TCINDEX_SHIFT,&shift, sizeof(shift)); } else if (!strcmp(*argv,"fall_through")) { int value = 1; addattr_l(n,4096,TCA_TCINDEX_FALL_THROUGH,&value, sizeof(value)); } else if (!strcmp(*argv,"pass_on")) { int value = 0; addattr_l(n,4096,TCA_TCINDEX_FALL_THROUGH,&value, sizeof(value)); } else if (!strcmp(*argv,"classid")) { __u32 handle; NEXT_ARG(); if (get_tc_classid(&handle,*argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } addattr_l(n, 4096, TCA_TCINDEX_CLASSID, &handle, 4); } else if (!strcmp(*argv,"police")) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_TCINDEX_POLICE, n)) { fprintf(stderr, "Illegal \"police\"\n"); return -1; } continue; } else { explain(); return -1; } argc--; argv++; } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
static int flow_parse_opt(struct filter_util *fu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct tc_police tp; struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; __u32 mask = ~0U, xor = 0; __u32 keys = 0, nkeys = 0; __u32 mode = FLOW_MODE_MAP; __u32 tmp; memset(&tp, 0, sizeof(tp)); if (handle) { if (get_u32(&t->tcm_handle, handle, 0)) { fprintf(stderr, "Illegal \"handle\"\n"); return -1; } } tail = NLMSG_TAIL(n); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "map") == 0) { mode = FLOW_MODE_MAP; } else if (matches(*argv, "hash") == 0) { mode = FLOW_MODE_HASH; } else if (matches(*argv, "keys") == 0) { NEXT_ARG(); if (flow_parse_keys(&keys, &nkeys, *argv)) return -1; addattr32(n, 4096, TCA_FLOW_KEYS, keys); } else if (matches(*argv, "and") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"mask\"\n"); return -1; } transfer_bitop(&mask, &xor, tmp, 0); } else if (matches(*argv, "or") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"or\"\n"); return -1; } transfer_bitop(&mask, &xor, ~tmp, tmp); } else if (matches(*argv, "xor") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"xor\"\n"); return -1; } transfer_bitop(&mask, &xor, ~0, tmp); } else if (matches(*argv, "rshift") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"rshift\"\n"); return -1; } addattr32(n, 4096, TCA_FLOW_RSHIFT, tmp); } else if (matches(*argv, "addend") == 0) { NEXT_ARG(); if (get_addend(&tmp, *argv, keys)) { fprintf(stderr, "Illegal \"addend\"\n"); return -1; } addattr32(n, 4096, TCA_FLOW_ADDEND, tmp); } else if (matches(*argv, "divisor") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"divisor\"\n"); return -1; } addattr32(n, 4096, TCA_FLOW_DIVISOR, tmp); } else if (matches(*argv, "baseclass") == 0) { NEXT_ARG(); if (get_tc_classid(&tmp, *argv) || TC_H_MIN(tmp) == 0) { fprintf(stderr, "Illegal \"baseclass\"\n"); return -1; } addattr32(n, 4096, TCA_FLOW_BASECLASS, tmp); } else if (matches(*argv, "perturb") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"perturb\"\n"); return -1; } addattr32(n, 4096, TCA_FLOW_PERTURB, tmp); } else if (matches(*argv, "police") == 0) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_FLOW_POLICE, n)) { fprintf(stderr, "Illegal \"police\"\n"); return -1; } continue; } else if (matches(*argv, "action") == 0) { NEXT_ARG(); if (parse_action(&argc, &argv, TCA_FLOW_ACT, n)) { fprintf(stderr, "Illegal \"action\"\n"); return -1; } continue; } else if (matches(*argv, "match") == 0) { NEXT_ARG(); if (parse_ematch(&argc, &argv, TCA_FLOW_EMATCHES, n)) { fprintf(stderr, "Illegal \"ematch\"\n"); return -1; } continue; } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argv++, argc--; } if (nkeys > 1 && mode != FLOW_MODE_HASH) { fprintf(stderr, "Invalid mode \"map\" for multiple keys\n"); return -1; } addattr32(n, 4096, TCA_FLOW_MODE, mode); if (mask != ~0 || xor != 0) { addattr32(n, 4096, TCA_FLOW_MASK, mask); addattr32(n, 4096, TCA_FLOW_XOR, xor); } tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail; return 0; }
static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct { struct tc_u32_sel sel; struct tc_u32_key keys[128]; } sel; struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; int sel_ok = 0; int sample_ok = 0; __u32 htid = 0; __u32 order = 0; memset(&sel, 0, sizeof(sel)); //fprintf(stderr, "handle[%s]\n", handle); if (handle && get_u32_handle(&t->tcm_handle, handle)) { fprintf(stderr, "Illegal filter ID\n"); return -1; } if (argc == 0) return 0; tail = NLMSG_TAIL(n); addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "match") == 0) { NEXT_ARG(); if (parse_selector(&argc, &argv, &sel.sel, n)) { fprintf(stderr, "Illegal \"match\"\n"); return -1; } sel_ok++; continue; } else if (matches(*argv, "offset") == 0) { NEXT_ARG(); if (parse_offset(&argc, &argv, &sel.sel)) { fprintf(stderr, "Illegal \"offset\"\n"); return -1; } continue; } else if (matches(*argv, "hashkey") == 0) { NEXT_ARG(); if (parse_hashkey(&argc, &argv, &sel.sel)) { fprintf(stderr, "Illegal \"hashkey\"\n"); return -1; } continue; } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { unsigned handle; NEXT_ARG(); if (get_tc_classid(&handle, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } addattr_l(n, MAX_MSG, TCA_U32_CLASSID, &handle, 4); sel.sel.flags |= TC_U32_TERMINAL; } else if (matches(*argv, "divisor") == 0) { unsigned int divisor; fprintf(stderr, "parse divisor\n"); NEXT_ARG(); if (get_unsigned(&divisor, *argv, 0) || divisor == 0 || //divisor > 0x100 || ((divisor - 1) & divisor)) {//richie1124 divisor > 0x1000 || ((divisor - 1) & divisor)) { fprintf(stderr, "Illegal \"divisor\"\n"); return -1; } addattr_l(n, MAX_MSG, TCA_U32_DIVISOR, &divisor, 4); } else if (matches(*argv, "order") == 0) { NEXT_ARG(); if (get_u32(&order, *argv, 0)) { fprintf(stderr, "Illegal \"order\"\n"); return -1; } } else if (strcmp(*argv, "link") == 0) { unsigned handle; NEXT_ARG(); if (get_u32_handle(&handle, *argv)) { fprintf(stderr, "Illegal \"link\"\n"); return -1; } if (handle && TC_U32_NODE(handle)) { fprintf(stderr, "\"link\" must be a hash table.\n"); return -1; } addattr_l(n, MAX_MSG, TCA_U32_LINK, &handle, 4); } else if (strcmp(*argv, "ht") == 0) { unsigned handle; NEXT_ARG(); if (get_u32_handle(&handle, *argv)) { fprintf(stderr, "Illegal \"ht\"\n"); return -1; } //fprintf(stderr, "f_u32, handle[%x]\n", handle); if (handle && TC_U32_NODE(handle)) { fprintf(stderr, "\"ht\" must be a hash table.\n"); return -1; } if (sample_ok) { //htid = (htid&0xFF000)|(handle&0xFFF00000); //htid = (htid&0xFFF00)|(handle&0xFFF00000); htid = (htid&0xFFF00)|(handle&0xFFF00000);//richie1124 } else { //htid = (handle&0xFFFFF000); htid = (handle&0xFFFFFF00); //htid = (handle&0xFFFFFF00);//richie1124 } } else if (strcmp(*argv, "sample") == 0) { __u32 hash; unsigned divisor = 0x100; struct { struct tc_u32_sel sel; struct tc_u32_key keys[4]; } sel2; memset(&sel2, 0, sizeof(sel2)); NEXT_ARG(); if (parse_selector(&argc, &argv, &sel2.sel, n)) { fprintf(stderr, "Illegal \"sample\"\n"); return -1; } if (sel2.sel.nkeys != 1) { fprintf(stderr, "\"sample\" must contain exactly ONE key.\n"); return -1; } if (*argv != 0 && strcmp(*argv, "divisor") == 0) { NEXT_ARG(); if (get_unsigned(&divisor, *argv, 0) || divisor == 0 || divisor > 0x100 || ((divisor - 1) & divisor)) { fprintf(stderr, "Illegal sample \"divisor\"\n"); return -1; } NEXT_ARG(); } hash = sel2.sel.keys[0].val&sel2.sel.keys[0].mask; hash ^= hash>>16; hash ^= hash>>8; htid = ((hash%divisor)<<12)|(htid&0xFFF00000); sample_ok = 1; continue; } else if (strcmp(*argv, "indev") == 0) {
static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { int wrr_ok=0, fopt_ok=0; struct tc_ratespec r; struct tc_cbq_lssopt lss; struct tc_cbq_wrropt wrr; struct tc_cbq_fopt fopt; struct tc_cbq_ovl ovl; __u32 rtab[256]; unsigned mpu=0; int cell_log=-1; int ewma_log=-1; unsigned bndw = 0; unsigned minburst=0, maxburst=0; struct rtattr *tail; memset(&r, 0, sizeof(r)); memset(&lss, 0, sizeof(lss)); memset(&wrr, 0, sizeof(wrr)); memset(&fopt, 0, sizeof(fopt)); memset(&ovl, 0, sizeof(ovl)); while (argc > 0) { if (strcmp(*argv, "rate") == 0) { NEXT_ARG(); if (get_rate(&r.rate, *argv)) { explain1("rate"); return -1; } } else if (strcmp(*argv, "bandwidth") == 0) { NEXT_ARG(); if (get_rate(&bndw, *argv)) { explain1("bandwidth"); return -1; } } else if (strcmp(*argv, "minidle") == 0) { NEXT_ARG(); if (get_u32(&lss.minidle, *argv, 0)) { explain1("minidle"); return -1; } lss.change |= TCF_CBQ_LSS_MINIDLE; } else if (strcmp(*argv, "minburst") == 0) { NEXT_ARG(); if (get_u32(&minburst, *argv, 0)) { explain1("minburst"); return -1; } lss.change |= TCF_CBQ_LSS_OFFTIME; } else if (strcmp(*argv, "maxburst") == 0) { NEXT_ARG(); if (get_u32(&maxburst, *argv, 0)) { explain1("maxburst"); return -1; } lss.change |= TCF_CBQ_LSS_MAXIDLE; } else if (strcmp(*argv, "bounded") == 0) { lss.flags |= TCF_CBQ_LSS_BOUNDED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (strcmp(*argv, "borrow") == 0) { lss.flags &= ~TCF_CBQ_LSS_BOUNDED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (strcmp(*argv, "isolated") == 0) { lss.flags |= TCF_CBQ_LSS_ISOLATED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (strcmp(*argv, "sharing") == 0) { lss.flags &= ~TCF_CBQ_LSS_ISOLATED; lss.change |= TCF_CBQ_LSS_FLAGS; } else if (strcmp(*argv, "ewma") == 0) { NEXT_ARG(); if (get_u32(&ewma_log, *argv, 0)) { explain1("ewma"); return -1; } if (ewma_log > 31) { fprintf(stderr, "ewma_log must be < 32\n"); return -1; } lss.change |= TCF_CBQ_LSS_EWMA; } else if (strcmp(*argv, "cell") == 0) { unsigned cell; int i; NEXT_ARG(); if (get_size(&cell, *argv)) { explain1("cell"); return -1; } for (i=0; i<32; i++) if ((1<<i) == cell) break; if (i>=32) { fprintf(stderr, "cell must be 2^n\n"); return -1; } cell_log = i; } else if (strcmp(*argv, "prio") == 0) { unsigned prio; NEXT_ARG(); if (get_u32(&prio, *argv, 0)) { explain1("prio"); return -1; } if (prio > TC_CBQ_MAXPRIO) { fprintf(stderr, "\"prio\" must be number in the range 1...%d\n", TC_CBQ_MAXPRIO); return -1; } wrr.priority = prio; wrr_ok++; } else if (strcmp(*argv, "allot") == 0) { NEXT_ARG(); if (get_size(&wrr.allot, *argv)) { explain1("allot"); return -1; } } else if (strcmp(*argv, "avpkt") == 0) { NEXT_ARG(); if (get_size(&lss.avpkt, *argv)) { explain1("avpkt"); return -1; } lss.change |= TCF_CBQ_LSS_AVPKT; } else if (strcmp(*argv, "mpu") == 0) { NEXT_ARG(); if (get_size(&mpu, *argv)) { explain1("mpu"); return -1; } } else if (strcmp(*argv, "weight") == 0) { NEXT_ARG(); if (get_size(&wrr.weight, *argv)) { explain1("weight"); return -1; } wrr_ok++; } else if (strcmp(*argv, "split") == 0) { NEXT_ARG(); if (get_tc_classid(&fopt.split, *argv)) { fprintf(stderr, "Invalid split node ID.\n"); usage(); } fopt_ok++; } else if (strcmp(*argv, "defmap") == 0) { int err; NEXT_ARG(); err = sscanf(*argv, "%08x/%08x", &fopt.defmap, &fopt.defchange); if (err < 1) { fprintf(stderr, "Invalid defmap, should be MASK32[/MASK]\n"); return -1; } if (err == 1) fopt.defchange = ~0; fopt_ok++; } else if (strcmp(*argv, "help") == 0) { explain_class(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain_class(); return -1; } argc--; argv++; } /* OK. All options are parsed. */ /* 1. Prepare link sharing scheduler parameters */ if (r.rate) { unsigned pktsize = wrr.allot; if (wrr.allot < (lss.avpkt*3)/2) wrr.allot = (lss.avpkt*3)/2; if ((cell_log = tc_calc_rtable(r.rate, rtab, cell_log, pktsize, mpu)) < 0) { fprintf(stderr, "CBQ: failed to calculate rate table.\n"); return -1; } r.cell_log = cell_log; r.mpu = mpu; } if (ewma_log < 0) ewma_log = TC_CBQ_DEF_EWMA; lss.ewma_log = ewma_log; if (lss.change&(TCF_CBQ_LSS_OFFTIME|TCF_CBQ_LSS_MAXIDLE)) { if (lss.avpkt == 0) { fprintf(stderr, "CBQ: avpkt is required for max/minburst.\n"); return -1; } if (bndw==0 || r.rate == 0) { fprintf(stderr, "CBQ: bandwidth&rate are required for max/minburst.\n"); return -1; } } if (wrr.priority == 0 && (n->nlmsg_flags&NLM_F_EXCL)) { wrr_ok = 1; wrr.priority = TC_CBQ_MAXPRIO; if (wrr.allot == 0) wrr.allot = (lss.avpkt*3)/2; } if (wrr_ok) { if (wrr.weight == 0) wrr.weight = (wrr.priority == TC_CBQ_MAXPRIO) ? 1 : r.rate; if (wrr.allot == 0) { fprintf(stderr, "CBQ: \"allot\" is required to set WRR parameters.\n"); return -1; } } if (lss.change&TCF_CBQ_LSS_MAXIDLE) { lss.maxidle = tc_cbq_calc_maxidle(bndw, r.rate, lss.avpkt, ewma_log, maxburst); lss.change |= TCF_CBQ_LSS_MAXIDLE; lss.change |= TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT; } if (lss.change&TCF_CBQ_LSS_OFFTIME) { lss.offtime = tc_cbq_calc_offtime(bndw, r.rate, lss.avpkt, ewma_log, minburst); lss.change |= TCF_CBQ_LSS_OFFTIME; lss.change |= TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT; } if (lss.change&TCF_CBQ_LSS_MINIDLE) { lss.minidle <<= lss.ewma_log; lss.change |= TCF_CBQ_LSS_EWMA; } tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len)); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); if (lss.change) { lss.change |= TCF_CBQ_LSS_FLAGS; addattr_l(n, 1024, TCA_CBQ_LSSOPT, &lss, sizeof(lss)); } if (wrr_ok) addattr_l(n, 1024, TCA_CBQ_WRROPT, &wrr, sizeof(wrr)); if (fopt_ok) addattr_l(n, 1024, TCA_CBQ_FOPT, &fopt, sizeof(fopt)); if (r.rate) { addattr_l(n, 1024, TCA_CBQ_RATE, &r, sizeof(r)); addattr_l(n, 3024, TCA_CBQ_RTAB, rtab, 1024); if (show_raw) { int i; for (i=0; i<256; i++) printf("%u ", rtab[i]); printf("\n"); } } tail->rta_len = (((void*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail; return 0; }
static int parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { int argc = *argc_p; char **argv = *argv_p; int ok = 0; struct rtattr *tail; unsigned int tmp; __u16 queue_mapping; __u32 flags = 0, priority, mark; struct tc_skbedit sel = { 0 }; if (matches(*argv, "skbedit") != 0) return -1; NEXT_ARG(); while (argc > 0) { if (matches(*argv, "queue_mapping") == 0) { flags |= SKBEDIT_F_QUEUE_MAPPING; NEXT_ARG(); if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) { fprintf(stderr, "Illegal queue_mapping\n"); return -1; } queue_mapping = tmp; ok++; } else if (matches(*argv, "priority") == 0) { flags |= SKBEDIT_F_PRIORITY; NEXT_ARG(); if (get_tc_classid(&priority, *argv)) { fprintf(stderr, "Illegal priority\n"); return -1; } ok++; } else if (matches(*argv, "mark") == 0) { flags |= SKBEDIT_F_MARK; NEXT_ARG(); if (get_tc_classid(&mark, *argv)) { fprintf(stderr, "Illegal mark\n"); return -1; } ok++; } else if (matches(*argv, "help") == 0) { usage(); } else { break; } argc--; argv++; } if (argc) { if (matches(*argv, "reclassify") == 0) { sel.action = TC_ACT_RECLASSIFY; NEXT_ARG(); } else if (matches(*argv, "pipe") == 0) { sel.action = TC_ACT_PIPE; NEXT_ARG(); } else if (matches(*argv, "drop") == 0 || matches(*argv, "shot") == 0) { sel.action = TC_ACT_SHOT; NEXT_ARG(); } else if (matches(*argv, "continue") == 0) { sel.action = TC_ACT_UNSPEC; NEXT_ARG(); } else if (matches(*argv, "pass") == 0) { sel.action = TC_ACT_OK; NEXT_ARG(); } } if (argc) { if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&sel.index, *argv, 10)) { fprintf(stderr, "Pedit: Illegal \"index\"\n"); return -1; } argc--; argv++; ok++; } } if (!ok) { explain(); return -1; } tail = NLMSG_TAIL(n); addattr_l(n, MAX_MSG, tca_id, NULL, 0); addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel)); if (flags & SKBEDIT_F_QUEUE_MAPPING) addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING, &queue_mapping, sizeof(queue_mapping)); if (flags & SKBEDIT_F_PRIORITY) addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY, &priority, sizeof(priority)); if (flags & SKBEDIT_F_MARK) addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK, &mark, sizeof(mark)); tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail; *argc_p = argc; *argv_p = argv; return 0; }