diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c index a738ded0..f01bc269 100644 --- a/ip/ipaddrlabel.c +++ b/ip/ipaddrlabel.c @@ -263,4 +263,3 @@ int do_ipaddrlabel(int argc, char **argv) fprintf(stderr, "Command \"%s\" is unknown, try \"ip addrlabel help\".\n", *argv); exit(-1); } - diff --git a/ip/ipfou.c b/ip/ipfou.c index 0b83c277..8a86b18f 100644 --- a/ip/ipfou.c +++ b/ip/ipfou.c @@ -156,4 +156,3 @@ int do_ipfou(int argc, char **argv) fprintf(stderr, "Command \"%s\" is unknown, try \"ip fou help\".\n", *argv); exit(-1); } - diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c index 33bea913..9b569b1d 100644 --- a/ip/iplink_bond_slave.c +++ b/ip/iplink_bond_slave.c @@ -113,4 +113,3 @@ struct link_util bond_slave_link_util = { .parse_opt = bond_slave_parse_opt, .slave = true, }; - diff --git a/ip/ipprefix.c b/ip/ipprefix.c index 26b59615..ee51f04d 100644 --- a/ip/ipprefix.c +++ b/ip/ipprefix.c @@ -107,4 +107,3 @@ int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) return 0; } - diff --git a/ip/iproute.c b/ip/iproute.c index 07640bee..c0ef7bfe 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -1842,4 +1842,3 @@ int do_iproute(int argc, char **argv) fprintf(stderr, "Command \"%s\" is unknown, try \"ip route help\".\n", *argv); exit(-1); } - diff --git a/ip/tcp_metrics.c b/ip/tcp_metrics.c index bdc503ef..57b605fd 100644 --- a/ip/tcp_metrics.c +++ b/ip/tcp_metrics.c @@ -508,4 +508,3 @@ int do_tcp_metrics(int argc, char **argv) "try \"ip tcp_metrics help\".\n", *argv); exit(-1); } - diff --git a/man/man8/Makefile b/man/man8/Makefile index 1845987d..2f776406 100644 --- a/man/man8/Makefile +++ b/man/man8/Makefile @@ -12,7 +12,9 @@ MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 rtpr.8 ss. ip-netns.8 ip-ntable.8 ip-rule.8 ip-tunnel.8 ip-xfrm.8 \ ip-tcp_metrics.8 ip-netconf.8 ip-token.8 \ tipc.8 tipc-bearer.8 tipc-link.8 tipc-media.8 tipc-nametable.8 \ - tipc-node.8 tipc-socket.8 + tipc-node.8 tipc-socket.8 \ + tc-basic.8 tc-cgroup.8 tc-flow.8 tc-flower.8 tc-fw.8 tc-route.8 \ + tc-tcindex.8 tc-u32.8 all: $(TARGETS) diff --git a/man/man8/tc-basic.8 b/man/man8/tc-basic.8 new file mode 100644 index 00000000..fb39eaa9 --- /dev/null +++ b/man/man8/tc-basic.8 @@ -0,0 +1,34 @@ +.TH "Basic classifier in tc" 8 "21 Oct 2015" "iproute2" "Linux" + +.SH NAME +basic \- basic traffic control filter +.SH SYNOPSIS +.in +8 +.ti -8 +.BR tc " " filter " ... " basic " [ " match +.IR EMATCH_TREE " ] [ " +.B action +.IR ACTION_SPEC " ] [ " +.B classid +.IR CLASSID " ]" +.SH DESCRIPTION +The +.B basic +filter allows to classify packets using the extended match infrastructure. +.SH OPTIONS +.TP +.BI action " ACTION_SPEC" +Apply an action from the generic actions framework on matching packets. +.TP +.BI classid " CLASSID" +Push matching packets into the class identified by +.IR CLASSID . +.TP +.BI match " EMATCH_TREE" +Match packets using the extended match infrastructure. See +.BR tc-ematch (8) +for a detailed description of the allowed syntax in +.IR EMATCH_TREE . +.SH SEE ALSO +.BR tc (8), +.BR tc-ematch (8) diff --git a/man/man8/tc-cgroup.8 b/man/man8/tc-cgroup.8 new file mode 100644 index 00000000..2bea7d4a --- /dev/null +++ b/man/man8/tc-cgroup.8 @@ -0,0 +1,80 @@ +.TH "Cgroup classifier in tc" 8 " 21 Oct 2015" "iproute2" "Linux" + +.SH NAME +cgroup \- control group based traffic control filter +.SH SYNOPSIS +.in +8 +.ti -8 +.BR tc " " filter " ... " cgroup " [ " match +.IR EMATCH_TREE " ] [ " +.B action +.IR ACTION_SPEC " ]" +.SH DESCRIPTION +This filter serves as a hint to +.B tc +that the assigned class ID of the net_cls control group the process the packet +originates from belongs to should be used for classification. Obviously, it is +useful for locally generated packets only. +.SH OPTIONS +.TP +.BI action " ACTION_SPEC" +Apply an action from the generic actions framework on matching packets. +.TP +.BI match " EMATCH_TREE" +Match packets using the extended match infrastructure. See +.BR tc-ematch (8) +for a detailed description of the allowed syntax in +.IR EMATCH_TREE . +.SH EXAMPLES +In order to use this filter, a net_cls control group has to be created first and +class as well as process ID(s) assigned to it. The following creates a net_cls +cgroup named "foobar": + +.RS +.EX +modprobe cls_cgroup +mkdir /sys/fs/cgroup/net_cls +mount -t cgroup -onet_cls net_cls /sys/fs/cgroup/net_cls +mkdir /sys/fs/cgroup/net_cls/foobar +.EE +.RE + +To assign a class ID to the created cgroup, a file named +.I net_cls.classid +has to be created which contains the class ID to be assigned as a hexadecimal, +64bit wide number. The upper 32bits are reserved for the major handle, the +remaining hold the minor. So a class ID of e.g. +.B ff:be +has to be written like so: +.B 0xff00be +(leading zeroes may be omitted). To continue the above example, the following +assigns class ID 1:2 to foobar cgroup: + +.RS +.EX +echo 0x10002 > /sys/fs/cgroup/net_cls/foobar/net_cls.classid +.EE +.RE + +Finally some PIDs can be assigned to the given cgroup: + +.RS +.EX +echo 1234 > /sys/fs/cgroup/net_cls/foobar/tasks +echo 5678 > /sys/fs/cgroup/net_cls/foobar/tasks +.EE +.RE + +Now by simply attaching a +.B cgroup +filter to a +.B qdisc +makes packets from PIDs 1234 and 5678 be pushed into class 1:2. + +.SH SEE ALSO +.BR tc (8), +.BR tc-ematch (8), +.br +the file +.I Documentation/cgroups/net_cls.txt +of the Linux kernel tree diff --git a/man/man8/tc-flow.8 b/man/man8/tc-flow.8 new file mode 100644 index 00000000..f1b7e2a4 --- /dev/null +++ b/man/man8/tc-flow.8 @@ -0,0 +1,265 @@ +.TH "Flow filter in tc" 8 "20 Oct 2015" "iproute2" "Linux" + +.SH NAME +flow \- flow based traffic control filter +.SH SYNOPSIS +.TP +Mapping mode: + +.RS +.in +8 +.ti -8 +.BR tc " " filter " ... " "flow map key " +.IR KEY " [ " OPS " ] [ " OPTIONS " ] " +.RE +.TP +Hashing mode: + +.RS +.in +8 +.ti -8 +.BR tc " " filter " ... " "flow hash keys " +.IR KEY_LIST " [ " +.B perturb +.IR secs " ] [ " OPTIONS " ] " +.RE + +.in +8 +.ti -8 +.IR OPS " := [ " OPS " ] " OP + +.ti -8 +.IR OPTIONS " := [ " +.B divisor +.IR NUM " ] [ " +.B baseclass +.IR ID " ] [ " +.B match +.IR EMATCH_TREE " ] [ " +.B action +.IR ACTION_SPEC " ]" + +.ti -8 +.IR KEY_LIST " := [ " KEY_LIST " ] " KEY + +.ti -8 +.IR OP " := { " +.BR or " | " and " | " xor " | " rshift " | " addend " } " +.I NUM + +.ti -8 +.IR ID " := " X : Y + +.ti -8 +.IR KEY " := { " +.BR src " | " dst " | " proto " | " proto-src " | " proto-dst " | " iif " | " +.BR priority " | " mark " | " nfct " | " nfct-src " | " nfct-dst " | " +.BR nfct-proto-src " | " nfct-proto-dst " | " rt-classid " | " sk-uid " | " +.BR sk-gid " | " vlan-tag " | " rxhash " }" +.SH DESCRIPTION +The +.B flow +classifier is meant to extend the +.B SFQ +hashing capabilities without hard-coding new hash functions. It also allows +deterministic mappings of keys to classes. +.SH OPTIONS +.TP +.BI action " ACTION_SPEC" +Apply an action from the generic actions framework on matching packets. +.TP +.BI baseclass " ID" +An offset for the resulting class ID. +.I ID +may be +.BR root ", " none +or a hexadecimal class ID in the form [\fIX\fB:\fR]\fIY\fR. If \fIX\fR is +omitted, it is assumed to be zero. +.TP +.BI divisor " NUM" +Number of buckets to use for sorting into. Keys are calculated modulo +.IR NUM . +.TP +.BI "hash keys " KEY-LIST +Perform a +.B jhash2 +operation over the keys in +.IR KEY-LIST , +the result (modulo the +.B divisor +if given) is taken as class ID, optionally offset by the value of +.BR baseclass . +It is possible to specify an interval (in seconds) after which +.BR jhash2 's +entropy source is recreated using the +.B perturb +parameter. +.TP +.BI "map key " KEY +Packet data identified by +.I KEY +is translated into class IDs to push the packet into. The value may be mangled by +.I OPS +before using it for the mapping. They are applied in the order listed here: +.RS +.TP 4 +.BI and " NUM" +Perform bitwise +.B AND +operation with numeric value +.IR NUM . +.TP +.BI or " NUM" +Perform bitwise +.B OR +operation with numeric value +.IR NUM . +.TP +.BI xor " NUM" +Perform bitwise +.B XOR +operation with numeric value +.IR NUM . +.TP +.BI rshift " NUM" +Shift the value of +.I KEY +to the right by +.I NUM +bits. +.TP +.BI addend " NUM" +Add +.I NUM +to the value of +.IR KEY . + +.RE +.RS +For the +.BR or ", " and ", " xor " and " rshift +operations, +.I NUM +is assumed to be an unsigned, 32bit integer value. For the +.B addend +operation, +.I NUM +may be much more complex: It may be prefixed by a minus ('-') sign to cause +subtraction instead of addition and for keys of +.BR src ", " dst ", " nfct-src " and " nfct-dst +it may be given in IP address notation. See below for an illustrating example. +.RE +.TP +.BI match " EMATCH_TREE" +Match packets using the extended match infrastructure. See +.BR tc-ematch (8) +for a detailed description of the allowed syntax in +.IR EMATCH_TREE . +.SH KEYS +In mapping mode, a single key is used (after optional permutation) to build a +class ID. The resulting ID is deducible in most cases. In hashing more, a number +of keys may be specified which are then hashed and the output used as class ID. +This ID is not deducible in beforehand, and may even change over time for a +given flow if a +.B perturb +interval has been given. + +The range of class IDs can be limited by the +.B divisor +option, which is used for a modulus. +.TP +.BR src ", " dst +Use source or destination address as key. In case of IPv4 and TIPC, this is the +actual address value. For IPv6, the 128bit address is folded into a 32bit value +by XOR'ing the four 32bit words. In all other cases, the kernel-internal socket +address is used (after folding into 32bits on 64bit systems). +.TP +.B proto +Use the layer four protocol number as key. +.TP +.B proto-src +Use the layer four source port as key. If not available, the kernel-internal +socket address is used instead. +.TP +.B proto-dst +Use the layer four destination port as key. If not available, the associated +kernel-internal dst_entry address is used after XOR'ing with the packet's +layer three protocol number. +.TP +.B iif +Use the incoming interface index as key. +.TP +.B priority +Use the packet's priority as key. Usually this is the IP header's DSCP/ECN +value. +.TP +.B mark +Use the netfilter +.B fwmark +as key. +.TP +.B nfct +Use the associated conntrack entry address as key. +.TP +.BR nfct-src ", " nfct-dst ", " nfct-proto-src ", " nfct-proto-dst +These are conntrack-aware variants of +.BR src ", " dst ", " proto-src " and " proto-dst . +In case of NAT, these are basically the packet header's values before NAT was +applied. +.TP +.B rt-classid +Use the packet's destination routing table entry's realm as key. +.TP +.B sk-uid +.TQ +.B sk-gid +For locally generated packets, use the user or group ID the originating socket +belongs to as key. +.TP +.B vlan-tag +Use the packet's vlan ID as key. +.TP +.B rxhash +Use the flow hash as key. + +.SH EXAMPLES +.TP +Classic SFQ hash: + +.EX +tc filter add ... flow hash \\ + keys src,dst,proto,proto-src,proto-dst divisor 1024 +.EE +.TP +Classic SFQ hash, but using information from conntrack to work properly in combination with NAT: + +.EX +tc filter add ... flow hash \\ + keys nfct-src,nfct-dst,proto,nfct-proto-src,nfct-proto-dst \\ + divisor 1024 +.EE +.TP +Map destination IPs of 192.168.0.0/24 to classids 1-257: + +.EX +tc filter add ... flow map \\ + key dst addend -192.168.0.0 divisor 256 +.EE +.TP +Alternative to the above: + +.EX +tc filter add ... flow map \\ + key dst and 0xff +.EE +.TP +The same, but in reverse order: + +.EX +tc filter add ... flow map \\ + key dst and 0xff xor 0xff +.EE +.SH SEE ALSO +.BR tc (8), +.BR tc-ematch (8), +.BR tc-sfq (8) diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 new file mode 100644 index 00000000..df4d8e19 --- /dev/null +++ b/man/man8/tc-flower.8 @@ -0,0 +1,113 @@ +.TH "Flower filter in tc" 8 "22 Oct 2015" "iproute2" "Linux" + +.SH NAME +flower \- flow based traffic control filter +.SH SYNOPSIS +.in +8 +.ti -8 +.BR tc " " filter " ... " flower " [ " +.IR MATCH_LIST " ] [ " +.B action +.IR ACTION_SPEC " ] [ " +.B classid +.IR CLASSID " ]" + +.ti -8 +.IR MATCH_LIST " := [ " MATCH_LIST " ] " MATCH + +.ti -8 +.IR MATCH " := { " +.B indev +.IR ifname " | { " +.BR dst_mac " | " src_mac " } " +.IR mac_address " | " +.BR eth_type " { " ipv4 " | " ipv6 " | " +.IR ETH_TYPE " } | " +.BR ip_proto " { " tcp " | " udp " | " +.IR IP_PROTO " } | { " +.BR dst_ip " | " src_ip " } { " +.IR ipv4_address " | " ipv6_address " } | { " +.BR dst_port " | " src_port " } " +.IR port_number " }" +.SH DESCRIPTION +The +.B flower +filter matches flows to the set of keys specified and assigns an arbitrarily +chosen class ID to packets belonging to them. Additionally (or alternatively) an +action from the generic action framework may be called. +.SH OPTIONS +.TP +.BI action " ACTION_SPEC" +Apply an action from the generic actions framework on matching packets. +.TP +.BI classid " CLASSID" +Specify a class to pass matching packets on to. +.I CLASSID +is in the form +.BR X : Y ", while " X " and " Y +are interpreted as numbers in hexadecimal format. +.TP +.BI indev " ifname" +Match on incoming interface name. Obviously this makes sense only for forwarded +flows. +.I ifname +is the name of an interface which must exist at the time of +.B tc +invocation. +.TP +.BI dst_mac " mac_address" +.TQ +.BI src_mac " mac_address" +Match on source or destination MAC address. +.TP +.BI eth_type " ETH_TYPE" +Match on layer three protocol. +.I ETH_TYPE +may be either +.BR ipv4 , ipv6 +or an unsigned 16bit value in hexadecimal format. +.TP +.BI ip_proto " IP_PROTO" +Match on layer four protocol. +.I IP_PROTO +may be either +.BR tcp , udp +or an unsigned 8bit value in hexadecimal format. +.TP +.BI dst_ip " ADDRESS" +.TQ +.BI src_ip " ADDRESS" +Match on source or destination IP address. +.I ADDRESS +must be a valid IPv4 or IPv6 address, depending on +.BR ether_type , +which has to be specified in beforehand. +.TP +.BI dst_port " NUMBER" +.TQ +.BI src_port " NUMBER" +Match on layer 4 protocol source or destination port number. Only available for +.BR ip_proto " values " udp " and " tcp , +which has to be specified in beforehand. +.SH NOTES +As stated above where applicable, matches of a certain layer implicitly depend +on the matches of the next lower layer. Precisely, layer one and two matches ( +.BR indev , dst_mac , src_mac " and " eth_type ) +have no dependency, layer three matches ( +.BR ip_proto , dst_ip " and " src_ip ) +require +.B eth_type +being set to either +.BR ipv4 " or " ipv6 , +and finally layer four matches ( +.BR dst_port " and " src_port ) +depend on +.B ip_proto +being set to either +.BR tcp " or " udp . +.P +There can be only used one mask per one prio. If user needs to specify different +mask, he has to use different prio. +.SH SEE ALSO +.BR tc (8), +.BR tc-flow (8) diff --git a/man/man8/tc-fw.8 b/man/man8/tc-fw.8 new file mode 100644 index 00000000..d742b473 --- /dev/null +++ b/man/man8/tc-fw.8 @@ -0,0 +1,66 @@ +.TH "Firewall mark classifier in tc" 8 "21 Oct 2015" "iproute2" "Linux" + +.SH NAME +fw \- fwmark traffic control filter +.SH SYNOPSIS +.in +8 +.ti -8 +.BR tc " " filter " ... " fw " [ " classid +.IR CLASSID " ] [ " +.B action +.IR ACTION_SPEC " ]" +.SH DESCRIPTION +the +.B fw +filter allows to classify packets based on a previously set +.BR fwmark " by " iptables . +If it is identical to the filter's +.BR handle , +the filter matches. +.B iptables +allows to mark single packets with the +.B MARK +target, or whole connections using +.BR CONNMARK . +The benefit of using this filter instead of doing the +heavy-lifting with +.B tc +itself is that on one hand it might be convenient to keep packet filtering and +classification in one place, possibly having to match a packet just once, and on +the other users familiar with +.BR iptables " but not " tc +will have a less hard time adding QoS to their setups. +.SH OPTIONS +.TP +.BI classid " CLASSID" +Push matching packets to the class identified by +.IR CLASSID . +.TP +.BI action " ACTION_SPEC" +Apply an action from the generic actions framework on matching packets. +.SH EXAMPLES +Take e.g. the following tc filter statement: + +.RS +.EX +tc filter add ... handle 6 fw classid 1:1 +.EE +.RE + +will match if the packet's +.B fwmark +value is +.BR 6 . +This is a sample +.B iptables +statement marking packets coming in on eth0: + +.RS +.EX +iptables -t mangle -A PREROUTING -i eth0 -j MARK --set-mark 6 +.EE +.RE +.SH SEE ALSO +.BR tc (8), +.BR iptables (8), +.BR iptables-extensions (8) diff --git a/man/man8/tc-route.8 b/man/man8/tc-route.8 new file mode 100644 index 00000000..b865cd11 --- /dev/null +++ b/man/man8/tc-route.8 @@ -0,0 +1,74 @@ +.TH "Route classifier in tc" 8 "21 Oct 2015" "iproute2" "Linux" + +.SH NAME +route \- route traffic control filter +.SH SYNOPSIS +.in +8 +.ti -8 +.BR tc " " filter " ... " route " [ " from +.IR REALM " | " +.B fromif +.IR TAG " ] [ " +.B to +.IR REALM " ] [ " +.B classid +.IR CLASSID " ] [ " +.B action +.IR ACTION_SPEC " ]" +.SH DESCRIPTION +Match packets based on routing table entries. This filter centers around the +possibility to assign a +.B realm +to routing table entries. For any packet to be classified by this filter, a +routing table lookup is performed and the returned +.B realm +is used to decide on whether the packet is a match or not. +.SH OPTIONS +.TP +.BI action " ACTION_SPEC" +Apply an action from the generic actions framework on matching packets. +.TP +.BI classid " CLASSID" +Push matching packets into the class identified by +.IR CLASSID . +.TP +.BI from " REALM" +.TQ +.BI fromif " TAG" +Perform source route lookups. +.I TAG +is the name of an interface which must be present on the system at the time of +.B tc +invocation. +.TP +.BI to " REALM" +Match if normal (i.e., destination) routing returns the given +.IR REALM . +.SH EXAMPLES +Consider the subnet 192.168.2.0/24 being attached to eth0: + +.RS +.EX +ip route add 192.168.2.0/24 dev eth0 realm 2 +.EE +.RE + +The following +.B route +filter will then match packets from that subnet: + +.RS +.EX +tc filter add ... route from 2 classid 1:2 +.EE +.RE + +and pass packets on to class 1:2. +.SH NOTES +Due to implementation details, +.B realm +values must be in a range from 0 to 255, inclusive. Alternatively, a verbose +name defined in /etc/iproute2/rt_realms may be given instead. +.SH SEE ALSO +.BR tc (8), +.BR ip-route (8) diff --git a/man/man8/tc-tcindex.8 b/man/man8/tc-tcindex.8 new file mode 100644 index 00000000..7fcf8254 --- /dev/null +++ b/man/man8/tc-tcindex.8 @@ -0,0 +1,58 @@ +.TH "Traffic control index filter" 8 "21 Oct 2015" "iproute2" "Linux" + +.SH NAME +tcindex \- traffic control index filter +.SH SYNOPSIS +.in +8 +.ti -8 +.BR tc " " filter " ... " tcindex " [ " hash +.IR SIZE " ] [ " +.B mask +.IR MASK " ] [ " +.B shift +.IR SHIFT " ] [ " +.BR pas_on " | " fall_through " ] [ " classid +.IR CLASSID " ] [ " +.B action +.BR ACTION_SPEC " ]" +.SH DESCRIPTION +This filter allows to match packets based on their +.B tcindex +field value, i.e. the combination of the DSCP and ECN fields as present in IPv4 +and IPv6 headers. +.SH OPTIONS +.TP +.BI action " ACTION_SPEC" +Apply an action from the generic actions framework on matching packets. +.TP +.BI classid " CLASSID" +Push matching packets into the class identified by +.IR CLASSID . +.TP +.BI hash " SIZE" +Hash table size in entries to use. Defaults to 64. +.TP +.BI mask " MASK" +An optional bitmask to binary +.BR AND " to the packet's " tcindex +field before use. +.TP +.BI shift " SHIFT" +The number of bits to right-shift a packet's +.B tcindex +value before use. If a +.B mask +has been set, masking is done before shifting. +.TP +.B pass_on +If this flag is set, failure to find a class for the resulting ID will make the +filter fail and lead to the next filter being consulted. +.TP +.B fall_through +This is the opposite of +.B pass_on +and the default. The filter will classify the packet even if there is no class +present for the resulting class ID. + +.SH SEE ALSO +.BR tc (8) diff --git a/man/man8/tc-u32.8 b/man/man8/tc-u32.8 new file mode 100644 index 00000000..47c8f2d0 --- /dev/null +++ b/man/man8/tc-u32.8 @@ -0,0 +1,663 @@ +.TH "Universal 32bit classifier in tc" 8 "25 Sep 2015" "iproute2" "Linux" + +.SH NAME +u32 \- universal 32bit traffic control filter +.SH SYNOPSIS +.in +8 +.ti -8 +.BR tc " " filter " ... [ " handle +.IR HANDLE " ] " +.B u32 +.IR OPTION_LIST " [ " +.B offset +.IR OFFSET " ] [ " +.B hashkey +.IR HASHKEY " ] [ " +.B classid +.IR CLASSID " ] [ " +.B divisor +.IR uint_value " ] [ " +.B order +.IR u32_value " ] [ " +.B ht +.IR HANDLE " ] [ " +.B sample +.IR SELECTOR " [ " +.B divisor +.IR uint_value " ] ] [ " +.B link +.IR HANDLE " ] [ " +.B indev +.IR ifname " ] [ " +.BR help " ]" + +.ti -8 +.IR HANDLE " := { " +\fIu12_hex_htid\fB:\fR[\fIu8_hex_hash\fB:\fR[\fIu12_hex_nodeid\fR] | \fB0x\fIu32_hex_value\fR } + +.ti -8 +.IR OPTION_LIST " := [ " OPTION_LIST " ] " OPTION + +.ti -8 +.IR HASHKEY " := [ " +.B mask +.IR u32_hex_value " ] [ " +.B at +.IR 4*int_value " ]" + +.ti -8 +.IR CLASSID " := { " +.BR root " | " +.BR none " | " +[\fIu16_major\fR]\fB:\fIu16_minor\fR | \fIu32_hex_value\fR } + +.ti -8 +.IR OFFSET " := [ " +.B plus +.IR int_value " ] [ " +.B at +.IR 2*int_value " ] [ " +.B mask +.IR u16_hex_value " ] [ " +.B shift +.IR int_value " ] [ " +.BR eat " ]" + +.ti -8 +.IR OPTION " := { " +.B match +.IR SELECTOR " | " +.B action +.IR ACTION " } " + +.ti -8 +.IR SELECTOR " := { " +.B u32 +.IR VAL_MASK_32 " | " +.B u16 +.IR VAL_MASK_16 " | " +.B u8 +.IR VAL_MASK_8 " | " +.B ip +.IR IP " | " +.B ip6 +.IR IP6 " | { " +.BR tcp " | " udp " } " +.IR TCPUDP " | " +.B icmp +.IR ICMP " | " +.B mark +.IR VAL_MASK_32 " | " +.B ether +.IR ETHER " }" + +.ti -8 +.IR IP " := { { " +.BR src " | " dst " } { " default " | " any " | " all " | " +.IR ip_address " [ " +.BR / " { " +.IR prefixlen " | " netmask " } ] } " AT " | { " +.BR dsfield " | " ihl " | " protocol " | " precedence " | " +.BR icmp_type " | " icmp_code " } " +.IR VAL_MASK_8 " | { " +.BR sport " | " dport " } " +.IR VAL_MASK_16 " | " +.BR nofrag " | " firstfrag " | " df " | " mf " }" + +.ti -8 +.IR IP6 " := { { " +.BR src " | " dst " } { " default " | " any " | " all " | " +.IR ip6_address " [/" prefixlen " ] } " AT " | " +.B priority +.IR VAL_MASK_8 " | { " +.BR protocol " | " icmp_type " | " icmp_code " } " +.IR VAL_MASK_8 " | " +.B flowlabel +.IR VAL_MASK_32 " | { " +.BR sport " | " dport " } " +.IR VAL_MASK_16 " }" + +.ti -8 +.IR TCPUDP " := { " +.BR src " | " dst " } " +.I VAL_MASK_16 + +.ti -8 +.IR ICMP " := { " +.B type +.IR VAL_MASK_8 " | " +.B code +.IR VAL_MASK_8 " }" + +.ti -8 +.IR ETHER " := { " +.BR src " | " dst " } " +.IR ether_address " " AT + +.ti -8 +.IR VAL_MASK_32 " := " u32_value " " u32_hex_mask " [ " AT " ]" + +.ti -8 +.IR VAL_MASK_16 " := " u16_value " " u16_hex_mask " [ " AT " ]" + +.ti -8 +.IR VAL_MASK_8 " := " u8_value " " u8_hex_mask " [ " AT " ]" + +.ti -8 +.IR AT " := [ " +.BR at " [ " nexthdr+ " ] " +.IR int_value " ]" +.SH DESCRIPTION +The Universal/Ugly 32bit filter allows to match arbitrary bitfields in the +packet. Due to breaking everything down to values, masks and offsets, It is +equally powerful and hard to use. Luckily many abstracting directives are +present which allow defining rules on a higher level and therefore free the +user from having to fiddle with bits and masks in many cases. + +There are two general modes of invocation: The first mode creates a new filter +to delegate packets to different destinations. Apart from the obvious ones, +namely classifying the packet by specifying a +.I CLASSID +or calling an +.BR action , +one may +.B link +one filter to another one (or even a list of them), effectively organizing +filters into a tree-like hierarchy. + +Typically filter delegation is done by means of a hash table, which leads to the +second mode of invocation: it merely serves to set up these hash tables. Filters +can select a hash table and provide a key selector from which a hash is to be +computed and used as key to lookup the table's bucket which contains filters for +further processing. This is useful if a high number of filters is in use, as the +overhead of performing the hash operation and table lookup becomes negligible in +that case. Using hashtables with +.B u32 +basically involves the following pattern: +.IP (1) 4 +Creating a new hash table, specifying it's size using the +.B divisor +parameter and ideally a handle by which the table can be identified. If the +latter is not given, the kernel chooses one on it's own, which has to be +guessed later. +.IP (2) 4 +Creating filters which link to the created table in +.I (1) +using the +.B link +parameter and defining the packet data which the kernel will use to calculate +the +.BR hashkey . +.IP (3) 4 +Adding filters to buckets in the hash table from +.IR (1) . +In order to avoid having to know how exactly the kernel creates the hash key, +there is the +.B sample +parameter, which gives sample data to hash and thereby define the table bucket +the filter should be added to. + +.RE +In fact, even if not explicitly requested +.B u32 +creates a hash table for every +.B priority +a filter is being added with. The table's size is 1 though, so it is in fact +merely a linked list. +.SH VALUES +Options and selectors require values to be specified in a specific format, which +is often non-intuitive. Therefore the terminals in +.I SYNOPSIS +have been given descriptive names to indicate the required format and/or maximum +allowed numeric value: Prefixes +.IR u32 ", " u16 " and " u8 +indicate four, two and single byte unsigned values. E.g. +.I u16 +indicates a two byte-sized value in range between 0 and 65535 (0xFFFF) +inclusive. A prefix of +.I int +indicates a four byte signed value. A middle part of +.I _hex_ +indicates that the value is parsed in hexadecimal format. Otherwise, the +value's base is automatically detected, i.e. values prefixed with +.I 0x +are considered hexadecimal, a leading +.I 0 +indicates octal format and decimal format otherwise. There are some values with +special formatting as well: +.IR ip_address " and " netmask +are in dotted-quad formatting as usual for IPv4 addresses. An +.I ip6_address +is specified in common, colon-separated hexadecimal format. Finally, +.I prefixlen +is an unsigned, decimal integer value in range from 0 to the address width in +bits (32 for IPv4 and 128 for IPv6). + +Sometimes values need to be dividable by a certain number. In that case a name +of the form +.I N*val +was chosen, indicating that +.I val +must be dividable by +.IR N . +Or the other way around: the resulting value must be a multiple of +.IR N . +.SH OPTIONS +.B U32 +recognizes the following options: +.TP +.BI handle " HANDLE" +The handle is used to reference a filter and therefore must be unique. It +consists of a hash table identifier +.B htid +and optional +.B hash +(which identifies the hash table's bucket) and +.BR nodeid . +All these values are parsed as unsigned, hexadecimal numbers with length 12bits +( +.BR htid " and " nodeid ) +or 8bits ( +.BR hash ). +Alternatively one may specify a single, 32bit long hex number which contains +the three fields bits in concatenated form. Other than the fields themselves, it +has to be prefixed by +.BR 0x . +.TP +.BI offset " OFFSET" +Set an offset which defines where matches of subsequent filters are applied to. +Therefore this option is useful only when combined with +.BR link " or a combination of " ht " and " sample . +The offset may be given explicitly by using the +.B plus +keyword, or extracted from the packet data with +.BR at . +It is possible to mangle the latter using +.BR mask " and/or " shift +keywords. By default, this offset is recorded but not implicitly applied. It is +used only to substitute the +.B nexthdr+ +statement. Using the keyword +.B eat +though inverses this behaviour: the offset is applied always, and +.B nexthdr+ +will fall back to zero. +.TP +.BI hashkey " HASHKEY" +Spefify what packet data to use to calculate a hash key for bucket lookup. The +kernel adjusts the value according to the hash table's size. For this to work, +the option +.B link +must be given. +.TP +.BI classid " CLASSID" +Classify matching packets into the given +.IR CLASSID , +which consists of either 16bit +.BR major " and " minor +numbers or a single 32bit value combining both. +.TP +.BI divisor " u32_value" +Specify a modulo value. Used when creating hash tables to define their size or +for declaring a +.B sample +to calculate hash table keys from. Must be a power of two with exponent not +exceeding eight. +.TP +.BI order " u32_value" +A value to order filters by, ascending. Conflicts with +.B handle +which serves the same purpose. +.TP +.BI sample " SELECTOR" +Used together with +.B ht +to specify which bucket to add this filter to. This allows one to avoid having +to know how exactly the kernel calculates hashes. The additional +.B divisor +defaults to 256, so must be given for hash tables of different size. +.TP +.BI link " HANDLE" +Delegate matching packets to filters in a hash table. +.I HANDLE +is used to only specify the hash table, so only +.BR htid " may be given, " hash " and " nodeid +have to be omitted. By default, bucket number 0 will be used and can be +overridden by the +.B hashkey +option. +.TP +.BI indev " ifname" +Filter on the incoming interface of the packet. Obviously works only for +forwarded traffic. +.TP +.BI help +Print a brief help text about possible options. +.SH SELECTORS +Basically the only real selector is +.B u32 . +All others merely provide a higher level syntax and are internally translated +into +.B u32 . +.TP +.BI u32 " VAL_MASK_32" +.TQ +.BI u16 " VAL_MASK_16" +.TQ +.BI u8 " VAL_MASK_8" +Match packet data to a given value. The selector name defines the sample length +to extract (32bits for +.BR u32 , +16bits for +.B u16 +and 8bits for +.BR u8 ). +Before comparing, the sample is binary AND'ed with the given mask. This way +uninteresting bits can be cleared before comparison. The position of the sample +is defined by the offset specified in +.IR AT . +.TP +.BI ip " IP" +.TQ +.BI ip6 " IP6" +Assume packet starts with an IPv4 ( +.BR ip ) +or IPv6 ( +.BR ip6 ) +header. +.IR IP / IP6 +then allows to match various header fields: +.RS +.TP +.BI src " ADDR" +.BI dst " ADDR" +Compare Source or Destination Address fields against the value of +.IR ADDR . +The reserved words +.BR default ", " any " and " all +effectively match any address. Otherwise an IP address of the particular +protocol is expected, optionally suffixed by a prefix length to match whole +subnets. In case of IPv4 a netmask may also be given. +.TP +.BI dsfield " VAL_MASK_8" +IPv4 only. Match the packet header's DSCP/ECN field. Synonyms to this are +.BR tos " and " precedence . +.TP +.BI ihl " VAL_MASK_8" +IPv4 only. Match the Internet Header Length field. Note that the value's unit is +32bits, so to match a packet with 24byte header length +.I u8_value +has to be 6. +.TP +.BI protocol " VAL_MASK_8" +Match the Protocol (IPv4) or Next Header (IPv6) field value, e.g. 6 for TCP. +.TP +.BI icmp_type " VAL_MASK_8" +.TQ +.BI icmp_code " VAL_MASK_8" +Assume a next-header protocol of icmp or ipv6-icmp and match Type or Code +field values. This is dangerous, as the code assumes minimal header size for +IPv4 and lack of extension headers for IPv6. +.TP +.BI sport " VAL_MASK_16" +.TQ +.BI dport " VAL_MASK_16" +Match layer four source or destination ports. This is dangerous as well, as it +assumes a suitable layer four protocol is present (which has Source and +Destination Port fields right at the start of the header and 16bit in size). +Also minimal header size for IPv4 and lack of IPv6 extension headers is assumed. +.TP +.B nofrag +.TQ +.B firstfrag +.TQ +.B df +.TQ +.B mf +IPv4 only, check certain flags and fragment offset values. Match if the packet +is not a fragment +.RB ( nofrag ), +the first fragment +.RB ( firstfrag ), +if Don't Fragment +.RB ( df ) +or More Fragments +.RB ( mf ) +bits are set. +.TP +.BI priority " VAL_MASK_8" +IPv6 only. Match the header's Traffic Class field, which has the same purpose +and semantics of IPv4's ToS field since RFC 3168: upper six bits are DSCP, the +lower two ECN. +.TP +.BI flowlabel " VAL_MASK_32" +IPv6 only. Match the Flow Label field's value. Note that Flow Label itself is +only 20bytes long, which are the least significant ones here. The remaining +upper 12bytes match Version and Traffic Class fields. +.RE +.TP +.BI tcp " TCPUDP" +.TQ +.BI udp " TCPUDP" +Match fields of next header of protocol TCP or UDP. The possible values for +.I TCPDUP +are: +.RS +.TP +.BI src " VAL_MASK_16" +Match on Source Port field value. +.TP +.BI dst " VALMASK_16" +Match on Destination Port field value. +.RE +.TP +.BI icmp " ICMP" +Match fields of next header of protocol ICMP. The possible values for +.I ICMP +are: +.RS +.TP +.BI type " VAL_MASK_8" +Match on ICMP Type field. +.TP +.BI code " VAL_MASK_8" +Match on ICMP Code field. +.RE +.TP +.BI mark " VAL_MASK_32" +Match on netfilter fwmark value. +.TP +.BI ether " ETHER" +Match on ethernet header fields. Possible values for +.I ETHER +are: +.RS +.TP +.BI src " ether_address" " " AT +.TQ +.BI dst " ether_address" " " AT +Match on source or destination ethernet address. This is dangerous: It assumes +an ethernet header is present at the start of the packet. This will probably +lead to unexpected things if used with layer three interfaces like e.g. tun or +ppp. +.SH EXAMPLES +.RS +.EX +tc filter add dev eth0 parent 999:0 prio 99 protocol ip u32 \\ + match ip src 192.168.8.0/24 classid 1:1 +.EE +.RE + +This attaches a filter to the qdisc identified by +.BR 999:0. +It's priority is +.BR 99 , +which affects in which order multiple filters attached to the same +.B parent +are consulted (the lower the earlier). The filter handles packets of +.B protocol +type +.BR ip , +and +.BR match es +if the IP header's source address is within the +.B 192.168.8.0/24 +subnet. Matching packets are classified into class +.BR 1.1 . +The effect of this command might be surprising at first glance: + +.RS +.EX +filter parent 1: protocol ip pref 99 u32 +filter parent 1: protocol ip pref 99 u32 \\ + fh 800: ht divisor 1 +filter parent 1: protocol ip pref 99 u32 \\ + fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 \\ + match c0a80800/ffffff00 at 12 +.EE +.RE + +So parent +.B 1: +is assigned a new +.B u32 +filter, which contains a hash table of size 1 (as the +.B divisor +indicates). The table ID is +.BR 800 . +The third line then shows the actual filter which was added above: it sits in +table +.B 800 +and bucket +.BR 0 , +classifies packets into class ID +.B 1:1 +and matches the upper three bytes of the four byte value at offset +.B 12 +to be +.BR 0xc0a808 , +which is 192, 168 and 8. + +Now for something more complicated, namely creating a custom hash table: + +.RS +.EX +tc filter add dev eth0 prio 99 handle 1: u32 divisor 256 +.EE +.RE + +This creates a table of size 256 with handle +.B 1: +in priority +.BR 99 . +The effect is as follows: + +.RS +.EX +filter parent 1: protocol all pref 99 u32 +filter parent 1: protocol all pref 99 u32 fh 1: ht divisor 256 +filter parent 1: protocol all pref 99 u32 fh 800: ht divisor 1 +.EE +.RE + +So along with the requested hash table (handle +.BR 1: ), +the kernel has created his own table of size 1 to hold other filters of the same +priority. + +The next step is to create a filter which links to the created hash table: + +.RS +.EX +tc filter add dev eth0 parent 1: prio 1 u32 \\ + link 1: hashkey mask 0x0000ff00 at 12 \\ + match ip src 192.168.0.0/16 +.EE +.RE + +The filter is given a lower priority than the hash table itself so +.B u32 +consults it before manually traversing the hash table. The options +.BR link " and " hashkey +determine which table and bucket to redirect to. In this case the hash key +should be constructed out of the second byte at offset 12, which corresponds to +an IP packet's third byte of the source address field. Along with the +.B match +statement, this effectively maps all class C networks below 192.168.0.0/16 to +different buckets of the hash table. + +Filters for certain subnets can be created like so: + +.RS +.EX +tc filter add dev eth0 parent 1: prio 99 u32 \\ + ht 1: sample u32 0x00000800 0x0000ff00 at 12 \\ + match ip src 192.168.8.0/24 classid 1:1 +.EE +.RE + +The bucket is defined using the +.B sample +option: In this case, the second byte at offset 12 must be 0x08, exactly. In +this case, the resulting bucket ID is obviously 8, but as soon as +.B sample +selects an amount of data which could exceed the +.BR divisor , +one would have to know the kernel-internal algorithm to deduce the destination +bucket. This filter's +.B match +statement is redundant in this case, as the entropy for the hash key does not +exceed the table size and therefore no collisions can occur. Otherwise it's +necessary to prevent matching unwanted packets. + +Matching upper layer fields is problematic since IPv4 header length is variable +and IPv6 supports extension headers which affect upper layer header offset. To +overcome this, there is the possibility to specify +.B nexthdr+ +when giving an offset, and to make things easier there are the +.BR tcp " and " udp +matches which use +.B nexthdr+ +implicitly. This offset has to be calculated in beforehand though, and the only +way to achieve that is by doing it in a separate filter which then links to the +filter which wants to use it. Here is an example of doing so: + +.RS +.EX +tc filter add dev eth0 parent 1:0 protocol ip handle 1: \\ + u32 divisor 1 +tc filter add dev eth0 parent 1:0 protocol ip \\ + u32 ht 1: \\ + match tcp src 22 FFFF \\ + classid 1:2 +tc filter add dev eth0 parent 1:0 protocol ip \\ + u32 ht 800: \\ + match ip protocol 6 FF \\ + match ip firstfrag \\ + offset at 0 mask 0f00 shift 6 \\ + link 1: +.EE +.RE + +This is what is being done: In the first call, a single element sized hash table +is created so there is a place to hold the linked to filter and a known handle +.RB ( 1: ) +to reference to it. The second call then adds the actual filter, which pushes +packets with TCP source port 22 into class +.BR 1:2 . +Using +.BR ht , +it is moved into the hash table created by the first call. The third call then +does the actual magic: It matches IPv4 packets with next layer protocol 6 (TCP), +only if it's the first fragment (usually TCP sets DF bit, but if it doesn't and +the packet is fragmented, only the first one contains the TCP header), and then +sets the offset based on the IP header's IHL field (right-shifting by 6 +eliminates the offset of the field and at the same time converts the value into +byte unit). Finally, using +.BR link , +the hash table from first call is referenced which holds the filter from second +call. +.SH SEE ALSO +.BR tc (8), +.br +.BR cls_u32.txt " at " http://linux-tc-notes.sourceforge.net/ diff --git a/man/man8/tc.8 b/man/man8/tc.8 index 87350113..700b960c 100644 --- a/man/man8/tc.8 +++ b/man/man8/tc.8 @@ -144,6 +144,50 @@ It is important to notice that filters reside .B within qdiscs - they are not masters of what happens. +The available filters are: +.TP +basic +Filter packets based on an ematch expression. See +.BR tc-ematch (8) +for details. +.TP +bpf +Filter packets using (e)BPF, see +.BR tc-bpf (8) +for details. +.TP +cgroup +Filter packets based on the control group of their process. See +. BR tc-cgroup (8) +for details. +.TP +flow, flower +Flow-based classifiers, filtering packets based on their flow (identified by selectable keys). See +.BR tc-flow "(8) and" +.BR tc-flower (8) +for details. +.TP +fw +Filter based on fwmark. Directly maps fwmark value to traffic class. See +.BR tc-fw (8). +.TP +route +Filter packets based on routing table. See +.BR tc-route (8) +for details. +.TP +rsvp +Match Resource Reservation Protocol (RSVP) packets. +.TP +tcindex +Filter packets based on traffic control index. See +.BR tc-index (8). +.TP +u32 +Generic filtering on arbitrary packet data, assisted by syntax to abstract common operations. See +.BR tc-u32 (8) +for details. + .SH CLASSLESS QDISCS The classless qdiscs are: .TP @@ -655,15 +699,20 @@ Shows classes as ASCII graph with stats info under each class. .B tc was written by Alexey N. Kuznetsov and added in Linux 2.2. .SH SEE ALSO +.BR tc-basic (8), .BR tc-bfifo (8), .BR tc-bpf (8), .BR tc-cbq (8), +.BR tc-cgroup (8), .BR tc-choke (8), .BR tc-codel (8), .BR tc-drr (8), .BR tc-ematch (8), +.BR tc-flow (8), +.BR tc-flower (8), .BR tc-fq (8), .BR tc-fq_codel (8), +.BR tc-fw (8), .BR tc-hfsc (7), .BR tc-hfsc (8), .BR tc-htb (8), @@ -671,10 +720,13 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2. .BR tc-pfifo (8), .BR tc-pfifo_fast (8), .BR tc-red (8), +.BR tc-route (8), .BR tc-sfb (8), .BR tc-sfq (8), .BR tc-stab (8), .BR tc-tbf (8), +.BR tc-tcindex (8), +.BR tc-u32 (8), .br .RB "User documentation at " http://lartc.org/ ", but please direct bugreports and patches to: " diff --git a/misc/ifstat.c b/misc/ifstat.c index 9118c80b..20a8db45 100644 --- a/misc/ifstat.c +++ b/misc/ifstat.c @@ -272,7 +272,7 @@ static void dump_raw_db(FILE *fp, int to_hist) if (jw) { jsonw_name(jw, n->name); jsonw_start_object(jw); - + for (i=0; i=0x1000) return -1; if (*tmp) { - str = tmp+1; + str = tmp + 1; hash = strtoul(str, &tmp, 16); if (tmp == str && *str != ':' && *str != 0) return -1; if (hash>=0x100) return -1; if (*tmp) { - str = tmp+1; + str = tmp + 1; nodeid = strtoul(str, &tmp, 16); if (tmp == str && *str != 0) return -1; @@ -124,9 +124,9 @@ static int pack_key(struct tc_u32_sel *sel, __u32 key, __u32 mask, for (i=0; ikeys[i].off == off && sel->keys[i].offmask == offmask) { - __u32 intersect = mask&sel->keys[i].mask; + __u32 intersect = mask & sel->keys[i].mask; - if ((key^sel->keys[i].val) & intersect) + if ((key ^ sel->keys[i].val) & intersect) return -1; sel->keys[i].val |= key; sel->keys[i].mask |= mask; @@ -346,7 +346,7 @@ static int parse_ip_addr(int *argc_p, char ***argv_p, struct tc_u32_sel *sel, mask = 0; if (addr.bitlen) - mask = htonl(0xFFFFFFFF<<(32-addr.bitlen)); + mask = htonl(0xFFFFFFFF << (32 - addr.bitlen)); if (pack_key(sel, addr.data[0], mask, off, offmask) < 0) return -1; res = 0; @@ -381,17 +381,17 @@ static int parse_ip6_addr(int *argc_p, char ***argv_p, } plen = addr.bitlen; - for (i=0; i>16; - hash ^= hash>>8; - htid = ((hash%divisor)<<12)|(htid&0xFFF00000); + 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) { @@ -1165,7 +1163,7 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, addattr_l(n, MAX_MSG, TCA_U32_HASH, &htid, 4); if (sel_ok) addattr_l(n, MAX_MSG, TCA_U32_SEL, &sel, - sizeof(sel.sel)+sel.sel.nkeys*sizeof(struct tc_u32_key)); + sizeof(sel.sel) + sel.sel.nkeys * sizeof(struct tc_u32_key)); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; } @@ -1173,7 +1171,7 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle) { - struct rtattr *tb[TCA_U32_MAX+1]; + struct rtattr *tb[TCA_U32_MAX + 1]; struct tc_u32_sel *sel = NULL; struct tc_u32_pcnt *pf = NULL; @@ -1209,9 +1207,9 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, if (tb[TCA_U32_CLASSID]) { SPRINT_BUF(b1); fprintf(f, "%sflowid %s ", - !sel || !(sel->flags&TC_U32_TERMINAL) ? "*" : "", + !sel || !(sel->flags & TC_U32_TERMINAL) ? "*" : "", sprint_tc_classid(rta_getattr_u32(tb[TCA_U32_CLASSID]), b1)); - } else if (sel && sel->flags&TC_U32_TERMINAL) { + } else if (sel && sel->flags & TC_U32_TERMINAL) { fprintf(f, "terminal flowid ??? "); } if (tb[TCA_U32_LINK]) { @@ -1254,16 +1252,16 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, } } - if (sel->flags&(TC_U32_VAROFFSET|TC_U32_OFFSET)) { + if (sel->flags & (TC_U32_VAROFFSET | TC_U32_OFFSET)) { fprintf(f, "\n offset "); - if (sel->flags&TC_U32_VAROFFSET) + if (sel->flags & TC_U32_VAROFFSET) fprintf(f, "%04x>>%d at %d ", ntohs(sel->offmask), sel->offshift, sel->offoff); if (sel->off) fprintf(f, "plus %d ", sel->off); } - if (sel->flags&TC_U32_EAT) + if (sel->flags & TC_U32_EAT) fprintf(f, " eat "); if (sel->hmask) { diff --git a/tc/m_action.c b/tc/m_action.c index d363d273..f88ff3a1 100644 --- a/tc/m_action.c +++ b/tc/m_action.c @@ -648,4 +648,3 @@ int do_action(int argc, char **argv) return 0; } - diff --git a/tc/m_ipt.c b/tc/m_ipt.c index e5c48977..948becbc 100644 --- a/tc/m_ipt.c +++ b/tc/m_ipt.c @@ -618,4 +618,3 @@ struct action_util ipt_action_util = { .parse_aopt = parse_ipt, .print_aopt = print_ipt, }; - diff --git a/tc/m_xt_old.c b/tc/m_xt_old.c index 0ea0b4a9..6e643088 100644 --- a/tc/m_xt_old.c +++ b/tc/m_xt_old.c @@ -433,4 +433,3 @@ struct action_util ipt_action_util = { .parse_aopt = parse_ipt, .print_aopt = print_ipt, }; - diff --git a/tc/p_tcp.c b/tc/p_tcp.c index 7f4b6f4a..32ffc027 100644 --- a/tc/p_tcp.c +++ b/tc/p_tcp.c @@ -34,5 +34,3 @@ struct m_pedit_util p_pedit_tcp = { "tcp", parse_tcp, }; - - diff --git a/tc/p_udp.c b/tc/p_udp.c index 17762896..2b9b88fc 100644 --- a/tc/p_udp.c +++ b/tc/p_udp.c @@ -35,4 +35,3 @@ struct m_pedit_util p_pedit_udp = { "udp", parse_udp, }; - diff --git a/tc/q_cbq.c b/tc/q_cbq.c index d76600cc..38a61630 100644 --- a/tc/q_cbq.c +++ b/tc/q_cbq.c @@ -582,4 +582,3 @@ struct qdisc_util cbq_qdisc_util = { .parse_copt = cbq_parse_class_opt, .print_copt = cbq_print_opt, }; - diff --git a/tc/q_netem.c b/tc/q_netem.c index cd990a0a..7bc8c6a5 100644 --- a/tc/q_netem.c +++ b/tc/q_netem.c @@ -688,4 +688,3 @@ struct qdisc_util netem_qdisc_util = { .parse_qopt = netem_parse_opt, .print_qopt = netem_print_opt, }; - diff --git a/tc/q_prio.c b/tc/q_prio.c index bacc7024..3236bec1 100644 --- a/tc/q_prio.c +++ b/tc/q_prio.c @@ -122,4 +122,3 @@ struct qdisc_util prio_qdisc_util = { .parse_qopt = prio_parse_opt, .print_qopt = prio_print_opt, }; - diff --git a/tc/q_tbf.c b/tc/q_tbf.c index 2d563311..0981e6f7 100644 --- a/tc/q_tbf.c +++ b/tc/q_tbf.c @@ -328,4 +328,3 @@ struct qdisc_util tbf_qdisc_util = { .parse_qopt = tbf_parse_opt, .print_qopt = tbf_print_opt, }; - diff --git a/tc/tc_filter.c b/tc/tc_filter.c index 9e416008..ff03db8f 100644 --- a/tc/tc_filter.c +++ b/tc/tc_filter.c @@ -375,4 +375,3 @@ int do_filter(int argc, char **argv) fprintf(stderr, "Command \"%s\" is unknown, try \"tc filter help\".\n", *argv); return -1; } - diff --git a/tc/tc_stab.c b/tc/tc_stab.c index 286681f3..aba8ae87 100644 --- a/tc/tc_stab.c +++ b/tc/tc_stab.c @@ -148,4 +148,3 @@ void print_size_table(FILE *fp, const char *prefix, struct rtattr *rta) } #endif } - diff --git a/tc/tc_util.c b/tc/tc_util.c index aa6de244..4764ecce 100644 --- a/tc/tc_util.c +++ b/tc/tc_util.c @@ -608,4 +608,3 @@ compat_xstats: if (tb[TCA_XSTATS] && xstats) *xstats = tb[TCA_XSTATS]; } -