diff --git a/bridge/bridge.c b/bridge/bridge.c index 7fcfe111..451d684e 100644 --- a/bridge/bridge.c +++ b/bridge/bridge.c @@ -174,7 +174,7 @@ main(int argc, char **argv) if (netns_switch(argv[1])) exit(-1); } else if (matches(opt, "-color") == 0) { - enable_color(); + ++color; } else if (matches(opt, "-compressvlans") == 0) { ++compress_vlans; } else if (matches(opt, "-force") == 0) { @@ -200,8 +200,7 @@ main(int argc, char **argv) _SL_ = oneline ? "\\" : "\n"; - if (color && !json) - enable_color(); + check_enable_color(color, json); if (batch_file) return batch(batch_file); diff --git a/include/SNAPSHOT.h b/include/SNAPSHOT.h index 168c25ce..2714d17e 100644 --- a/include/SNAPSHOT.h +++ b/include/SNAPSHOT.h @@ -1 +1 @@ -static const char SNAPSHOT[] = "180608"; +static const char SNAPSHOT[] = "180813"; diff --git a/include/color.h b/include/color.h index c80359d3..4f2c918d 100644 --- a/include/color.h +++ b/include/color.h @@ -13,6 +13,7 @@ enum color_attr { }; void enable_color(void); +int check_enable_color(int color, int json); void set_color_palette(void); int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...); enum color_attr ifa_family_color(__u8 ifa_family); diff --git a/ip/ip.c b/ip/ip.c index 71d5170c..38eac5ec 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -304,8 +304,7 @@ int main(int argc, char **argv) _SL_ = oneline ? "\\" : "\n"; - if (color && !json) - enable_color(); + check_enable_color(color, json); if (batch_file) return batch(batch_file); diff --git a/lib/color.c b/lib/color.c index da1f516c..edf96e5c 100644 --- a/lib/color.c +++ b/lib/color.c @@ -77,6 +77,15 @@ void enable_color(void) set_color_palette(); } +int check_enable_color(int color, int json) +{ + if (color && !json) { + enable_color(); + return 0; + } + return 1; +} + void set_color_palette(void) { char *p = getenv("COLORFGBG"); diff --git a/man/man8/tc-bpf.8 b/man/man8/tc-bpf.8 index d311f295..b2f9344f 100644 --- a/man/man8/tc-bpf.8 +++ b/man/man8/tc-bpf.8 @@ -79,10 +79,39 @@ In Linux, it's generally considered that eBPF is the successor of cBPF. The kernel internally transforms cBPF expressions into eBPF expressions and executes the latter. Execution of them can be performed in an interpreter or at setup time, they can be just-in-time compiled (JIT'ed) to run as -native machine code. Currently, x86_64, ARM64, s390, ppc64 and sparc64 -architectures have eBPF JIT support, whereas PPC, SPARC, ARM and MIPS have -cBPF, but did not (yet) switch to eBPF JIT support. - +native machine code. +.PP +Currently, the eBPF JIT compiler is available for the following architectures: +.IP * 4 +x86_64 (since Linux 3.18) +.PD 0 +.IP * +arm64 (since Linux 3.18) +.IP * +s390 (since Linux 4.1) +.IP * +ppc64 (since Linux 4.8) +.IP * +sparc64 (since Linux 4.12) +.IP * +mips64 (since Linux 4.13) +.IP * +arm32 (since Linux 4.14) +.IP * +x86_32 (since Linux 4.18) +.PD +.PP +Whereas the following architectures have cBPF, but did not (yet) switch to eBPF +JIT support: +.IP * 4 +ppc32 +.PD 0 +.IP * +sparc32 +.IP * +mips32 +.PD +.PP eBPF's instruction set has similar underlying principles as the cBPF instruction set, it however is modelled closer to the underlying architecture to better mimic native instruction sets with the aim to diff --git a/man/man8/tc-skbprio.8 b/man/man8/tc-skbprio.8 new file mode 100644 index 00000000..844bbf46 --- /dev/null +++ b/man/man8/tc-skbprio.8 @@ -0,0 +1,70 @@ +.TH SKBPRIO 8 "13 August 2018" "iproute2" "Linux" +.SH NAME +skbprio \- SKB Priority Queue + +.SH SYNOPSIS +.B tc qdisc ... add skbprio +.B [ limit +packets +.B ] + +.SH DESCRIPTION +SKB Priority Queue is a queueing discipline intended to prioritize +the most important packets during a denial-of-service ( +.B DoS +) attack. The priority of a packet is given by +.B skb->priority +, where a higher value places the packet closer to the exit of the queue. When +the queue is full, the lowest priority packet in the queue is dropped to make +room for the packet to be added if it has higher priority. If the packet to be +added has lower priority than all packets in the queue, it is dropped. + +Without SKB priority queue, queue length limits must be imposed +on individual sub-queues, and there is no straightforward way to enforce +a global queue length limit across all priorities. SKBprio queue enforces +a global queue length limit while not restricting the lengths of +individual sub-queues. + +While SKB Priority Queue is agnostic to how +.B skb->priority +is assigned. A typical use case is to copy +the 6-bit DS field of IPv4 and IPv6 packets using +.BR tc-skbedit (8) +. If +.B skb->priority +is greater or equal to 64, the priority is assumed to be 63. +Priorities less than 64 are taken at face value. + +SKB Priority Queue enables routers to locally decide which +packets to drop under a DoS attack. +Priorities should be assigned to packets such that the higher the priority, +the more expected behavior a source shows. +So sources have an incentive to play by the rules. + +.SH ALGORITHM + +Skbprio maintains 64 lists (priorities go from 0 to 63). +When a packet is enqueued, it gets inserted at the +.B tail +of its priority list. When a packet needs to be sent out to the network, it is +taken from the head of the highest priority list. When the queue is full, +the packet at the tail of the lowest priority list is dropped to serve the +ingress packet - if it is of higher priority, otherwise the ingress packet is +dropped. This algorithm allocates as much bandwidth as possible to high +priority packets, while only servicing low priority packets when +there is enough bandwidth. + +.SH PARAMETERS +.TP +limit +Maximum queue size specified in packets. It defaults to 64. +The range for this parameter is [0, UINT32_MAX]. + +.SH SEE ALSO +.BR tc-prio (8), +.BR tc-skbedit (8) + +.SH AUTHORS +Nishanth Devarajan , Michel Machado + +This manpage maintained by Bert Hubert diff --git a/tc/Makefile b/tc/Makefile index 36cde2f8..5a1a7ff9 100644 --- a/tc/Makefile +++ b/tc/Makefile @@ -12,6 +12,7 @@ TCMODULES += q_fifo.o TCMODULES += q_sfq.o TCMODULES += q_red.o TCMODULES += q_prio.o +TCMODULES += q_skbprio.o TCMODULES += q_tbf.o TCMODULES += q_cbq.o TCMODULES += q_rr.o diff --git a/tc/q_skbprio.c b/tc/q_skbprio.c new file mode 100644 index 00000000..2e65a589 --- /dev/null +++ b/tc/q_skbprio.c @@ -0,0 +1,84 @@ +/* + * q_skbprio.c SKB PRIORITY QUEUE. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Nishanth Devarajan, + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "tc_util.h" + +static void explain(void) +{ + fprintf(stderr, "Usage: ... [ limit NUMBER ]\n"); +} + +static int skbprio_parse_opt(struct qdisc_util *qu, int argc, char **argv, + struct nlmsghdr *n, const char *dev) +{ + int ok = 0; + struct tc_skbprio_qopt opt = {}; + + while (argc > 0) { + if (strcmp(*argv, "limit") == 0) { + NEXT_ARG(); + if (get_size(&opt.limit, *argv)) { + fprintf(stderr, + "%s: Illegal \"limit\" value:\"%s\"\n", + qu->id, *argv); + return -1; + } + ok++; + } + else if (strcmp(*argv, "help") == 0) { + explain(); + return -1; + } else { + fprintf(stderr, + "%s: unknown parameter \"%s\"\n", + qu->id, *argv); + explain(); + return -1; + } + argc--; argv++; + } + + if (ok) + addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt)); + return 0; +} + +static int skbprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) +{ + struct tc_skbprio_qopt *qopt; + + if (opt == NULL) + return 0; + + if (RTA_PAYLOAD(opt) < sizeof(*qopt)) + return -1; + qopt = RTA_DATA(opt); + fprintf(f, "limit %u ", qopt->limit); + return 0; +} + +struct qdisc_util skbprio_qdisc_util = { + .id = "skbprio", + .parse_qopt = skbprio_parse_opt, + .print_qopt = skbprio_print_opt, +}; diff --git a/tc/tc.c b/tc/tc.c index a5a654f8..4c7a128c 100644 --- a/tc/tc.c +++ b/tc/tc.c @@ -518,8 +518,7 @@ int main(int argc, char **argv) _SL_ = oneline ? "\\" : "\n"; - if (color & !json) - enable_color(); + check_enable_color(color, json); if (batch_file) return batch(batch_file);