@@ -934,4 +934,15 @@ enum {
#define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
+/* Ingress/clsact */
+
+enum {
+ TCA_CLSACT_UNSPEC,
+ TCA_CLSACT_INGRESS_BLOCK,
+ TCA_CLSACT_EGRESS_BLOCK,
+ __TCA_CLSACT_MAX
+};
+
+#define TCA_CLSACT_MAX (__TCA_CLSACT_MAX - 1)
+
#endif
@@ -7,23 +7,65 @@
static void explain(void)
{
- fprintf(stderr, "Usage: ... clsact\n");
+ fprintf(stderr, "Usage: ... clsact [ingress_block BLOCK_INDEX] [egress_block BLOCK_INDEX]\n");
}
static int clsact_parse_opt(struct qdisc_util *qu, int argc, char **argv,
struct nlmsghdr *n, const char *dev)
{
- if (argc > 0) {
- fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
- return -1;
+ struct rtattr *tail;
+ __u32 ingress_block = 0;
+ __u32 egress_block = 0;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "ingress_block") == 0) {
+ NEXT_ARG();
+ if (get_u32(&ingress_block, *argv, 0) || !ingress_block)
+ invarg("invalid ingress block index value", *argv);
+ } else if (strcmp(*argv, "egress_block") == 0) {
+ NEXT_ARG();
+ if (get_u32(&egress_block, *argv, 0) || !egress_block)
+ invarg("invalid egress block index value", *argv);
+ } else {
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ explain();
+ return -1;
+ }
+ NEXT_ARG_FWD();
}
+ tail = NLMSG_TAIL(n);
+ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+ if (ingress_block)
+ addattr32(n, 1024, TCA_CLSACT_INGRESS_BLOCK, ingress_block);
+ if (egress_block)
+ addattr32(n, 1024, TCA_CLSACT_EGRESS_BLOCK, egress_block);
+ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
return 0;
}
static int clsact_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
+ struct rtattr *tb[TCA_CLSACT_MAX + 1];
+ __u32 block;
+
+ if (!opt)
+ return 0;
+
+ parse_rtattr_nested(tb, TCA_CLSACT_MAX, opt);
+
+ if (tb[TCA_CLSACT_INGRESS_BLOCK] &&
+ RTA_PAYLOAD(tb[TCA_CLSACT_INGRESS_BLOCK]) >= sizeof(__u32)) {
+ block = rta_getattr_u32(tb[TCA_CLSACT_INGRESS_BLOCK]);
+ print_uint(PRINT_ANY, "ingress_block",
+ "ingress_block %u ", block);
+ }
+ if (tb[TCA_CLSACT_EGRESS_BLOCK] &&
+ RTA_PAYLOAD(tb[TCA_CLSACT_EGRESS_BLOCK]) >= sizeof(__u32)) {
+ block = rta_getattr_u32(tb[TCA_CLSACT_EGRESS_BLOCK]);
+ print_uint(PRINT_ANY, "egress_block",
+ "egress_block %u ", block);
+ }
return 0;
}
@@ -17,30 +17,54 @@
static void explain(void)
{
- fprintf(stderr, "Usage: ... ingress\n");
+ fprintf(stderr, "Usage: ... ingress [block BLOCK_INDEX]\n");
}
static int ingress_parse_opt(struct qdisc_util *qu, int argc, char **argv,
struct nlmsghdr *n, const char *dev)
{
+ struct rtattr *tail;
+ __u32 block_index = 0;
+
while (argc > 0) {
if (strcmp(*argv, "handle") == 0) {
NEXT_ARG();
- argc--; argv++;
+ } else if (strcmp(*argv, "block") == 0) {
+ NEXT_ARG();
+ if (get_u32(&block_index, *argv, 0) || !block_index)
+ invarg("invalid block index value", *argv);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
explain();
return -1;
}
+ NEXT_ARG_FWD();
}
+ tail = NLMSG_TAIL(n);
+ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+ if (block_index)
+ addattr32(n, 1024, TCA_CLSACT_INGRESS_BLOCK, block_index);
+ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
return 0;
}
static int ingress_print_opt(struct qdisc_util *qu, FILE *f,
struct rtattr *opt)
{
- fprintf(f, "---------------- ");
+ struct rtattr *tb[TCA_CLSACT_MAX + 1];
+ __u32 block_index;
+
+ if (!opt)
+ return 0;
+
+ parse_rtattr_nested(tb, TCA_CLSACT_MAX, opt);
+
+ if (tb[TCA_CLSACT_INGRESS_BLOCK] &&
+ RTA_PAYLOAD(tb[TCA_CLSACT_INGRESS_BLOCK]) >= sizeof(__u32)) {
+ block_index = rta_getattr_u32(tb[TCA_CLSACT_INGRESS_BLOCK]);
+ print_uint(PRINT_ANY, "block", "block %u ", block_index);
+ }
return 0;
}