#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "utils.h"
#include "tc_util.h"
-extern int show_pretty;
-
static void explain(void)
{
- fprintf(stderr, "Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]\n");
- fprintf(stderr, " [ action ACTION_SPEC ] [ offset OFFSET_SPEC ]\n");
- fprintf(stderr, " [ ht HTID ] [ hashkey HASHKEY_SPEC ]\n");
- fprintf(stderr, " [ sample SAMPLE ]\n");
- fprintf(stderr, "or u32 divisor DIVISOR\n");
- fprintf(stderr, "\n");
- fprintf(stderr, "Where: SELECTOR := SAMPLE SAMPLE ...\n");
- fprintf(stderr, " SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark } SAMPLE_ARGS [divisor DIVISOR]\n");
- fprintf(stderr, " FILTERID := X:Y:Z\n");
- fprintf(stderr, "\nNOTE: CLASSID is parsed at hexadecimal input.\n");
+ fprintf(stderr,
+ "Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]\n"
+ " [ action ACTION_SPEC ] [ offset OFFSET_SPEC ]\n"
+ " [ ht HTID ] [ hashkey HASHKEY_SPEC ]\n"
+ " [ sample SAMPLE ] [skip_hw | skip_sw]\n"
+ "or u32 divisor DIVISOR\n"
+ "\n"
+ "Where: SELECTOR := SAMPLE SAMPLE ...\n"
+ " SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark }\n"
+ " SAMPLE_ARGS [ divisor DIVISOR ]\n"
+ " FILTERID := X:Y:Z\n"
+ "\nNOTE: CLASSID is parsed at hexadecimal input.\n");
}
static int get_u32_handle(__u32 *handle, const char *str)
plen = addr.bitlen;
for (i = 0; i < plen; i += 32) {
- /* if (((i + 31) & ~0x1F) <= plen) { */
- if (i + 31 <= plen) {
+ if (i + 31 < plen) {
res = pack_key(sel, addr.data[i / 32],
0xFFFFFFFF, off + 4 * (i / 32), offmask);
if (res < 0)
}
sel->flags |= TC_U32_VAROFFSET;
} else if (matches(*argv, "mask") == 0) {
- __u16 mask;
-
NEXT_ARG();
- if (get_u16(&mask, *argv, 16))
+ if (get_be16(&sel->offmask, *argv, 16))
return -1;
- sel->offmask = htons(mask);
sel->flags |= TC_U32_VAROFFSET;
} else if (matches(*argv, "shift") == 0) {
int shift;
while (argc > 0) {
if (matches(*argv, "mask") == 0) {
- __u32 mask;
-
NEXT_ARG();
- if (get_u32(&mask, *argv, 16))
+ if (get_be32(&sel->hmask, *argv, 16))
return -1;
- sel->hmask = htonl(mask);
} else if (matches(*argv, "at") == 0) {
int num;
{
int i = 0;
- if (!show_pretty)
+ if (!pretty)
goto show_k;
for (i = 0; i < ARRAY_SIZE(u32_pprinters); i++) {
struct {
struct tc_u32_sel sel;
struct tc_u32_key keys[128];
- } sel;
+ } sel = {};
struct tcmsg *t = NLMSG_DATA(n);
struct rtattr *tail;
int sel_ok = 0, terminal_ok = 0;
int sample_ok = 0;
__u32 htid = 0;
__u32 order = 0;
-
- memset(&sel, 0, sizeof(sel));
+ __u32 flags = 0;
if (handle && get_u32_handle(&t->tcm_handle, handle)) {
fprintf(stderr, "Illegal filter ID\n");
if (argc == 0)
return 0;
- tail = NLMSG_TAIL(n);
- addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
+ tail = addattr_nest(n, MAX_MSG, TCA_OPTIONS);
while (argc > 0) {
if (matches(*argv, "match") == 0) {
fprintf(stderr, "\"link\" must be a hash table.\n");
return -1;
}
- addattr_l(n, MAX_MSG, TCA_U32_LINK, &handle, 4);
+ addattr_l(n, MAX_MSG, TCA_U32_LINK, &linkid, 4);
} else if (strcmp(*argv, "ht") == 0) {
unsigned int ht;
} else if (strcmp(*argv, "sample") == 0) {
__u32 hash;
unsigned int divisor = 0x100;
-
struct {
struct tc_u32_sel sel;
struct tc_u32_key keys[4];
- } sel2;
- memset(&sel2, 0, sizeof(sel2));
+ } sel2 = {};
+
NEXT_ARG();
if (parse_selector(&argc, &argv, &sel2.sel, n)) {
fprintf(stderr, "Illegal \"sample\"\n");
sample_ok = 1;
continue;
} else if (strcmp(*argv, "indev") == 0) {
- char ind[IFNAMSIZ + 1];
+ char ind[IFNAMSIZ + 1] = {};
- memset(ind, 0, sizeof(ind));
argc--;
argv++;
if (argc < 1) {
}
terminal_ok++;
continue;
+ } else if (strcmp(*argv, "skip_hw") == 0) {
+ flags |= TCA_CLS_FLAGS_SKIP_HW;
+ } else if (strcmp(*argv, "skip_sw") == 0) {
+ flags |= TCA_CLS_FLAGS_SKIP_SW;
} else if (strcmp(*argv, "help") == 0) {
explain();
return -1;
argc--; argv++;
}
- /* We dont necessarily need class/flowids */
+ /* We don't necessarily need class/flowids */
if (terminal_ok)
sel.sel.flags |= TC_U32_TERMINAL;
addattr_l(n, MAX_MSG, TCA_U32_SEL, &sel,
sizeof(sel.sel) +
sel.sel.nkeys * sizeof(struct tc_u32_key));
- tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+ if (flags) {
+ if (!(flags ^ (TCA_CLS_FLAGS_SKIP_HW |
+ TCA_CLS_FLAGS_SKIP_SW))) {
+ fprintf(stderr,
+ "skip_hw and skip_sw are mutually exclusive\n");
+ return -1;
+ }
+ addattr_l(n, MAX_MSG, TCA_U32_FLAGS, &flags, 4);
+ }
+
+ addattr_nest_end(n, tail);
return 0;
}
SPRINT_BUF(b1);
fprintf(f, "fh %s ", sprint_u32_handle(handle, b1));
}
- if (TC_U32_NODE(handle)) {
+
+ if (TC_U32_NODE(handle))
fprintf(f, "order %d ", TC_U32_NODE(handle));
- }
if (tb[TCA_U32_SEL]) {
if (RTA_PAYLOAD(tb[TCA_U32_SEL]) < sizeof(*sel))
b1));
}
+ if (tb[TCA_U32_FLAGS]) {
+ __u32 flags = rta_getattr_u32(tb[TCA_U32_FLAGS]);
+
+ if (flags & TCA_CLS_FLAGS_SKIP_HW)
+ fprintf(f, "skip_hw ");
+ if (flags & TCA_CLS_FLAGS_SKIP_SW)
+ fprintf(f, "skip_sw ");
+
+ if (flags & TCA_CLS_FLAGS_IN_HW)
+ fprintf(f, "in_hw ");
+ else if (flags & TCA_CLS_FLAGS_NOT_IN_HW)
+ fprintf(f, "not_in_hw ");
+ }
+
if (tb[TCA_U32_PCNT]) {
if (RTA_PAYLOAD(tb[TCA_U32_PCNT]) < sizeof(*pf)) {
fprintf(f, "Broken perf counters\n");
fprintf(f, "\n");
tc_print_police(f, tb[TCA_U32_POLICE]);
}
+
if (tb[TCA_U32_INDEV]) {
struct rtattr *idev = tb[TCA_U32_INDEV];
fprintf(f, "\n input dev %s\n", rta_getattr_str(idev));
}
- if (tb[TCA_U32_ACT]) {
- tc_print_action(f, tb[TCA_U32_ACT]);
- }
+
+ if (tb[TCA_U32_ACT])
+ tc_print_action(f, tb[TCA_U32_ACT], 0);
return 0;
}