090-tc-add-support-for-action-act_ctinfo.patch 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. From dff8eadcab33209e040e77a5d56d5def04808144 Mon Sep 17 00:00:00 2001
  2. From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
  3. Date: Fri, 15 Mar 2019 09:35:37 +0000
  4. Subject: [PATCH] tc: add support for action act_ctinfo
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. ctinfo is a tc action restoring data stored in conntrack marks to
  9. various fields. At present it has two independent modes of operation,
  10. restoration of DSCP into IPv4/v6 diffserv and restoration of conntrack
  11. marks into packet skb marks.
  12. It understands a number of parameters specific to this action in
  13. additional to the usual action syntax. Each operating mode is
  14. independent of the other so all options are optional, however not
  15. specifying at least one mode is a bit pointless.
  16. Usage: ... ctinfo [dscp mask [statemask]] [cpmark [mask]] [zone ZONE]
  17. [CONTROL] [index <INDEX>]
  18. DSCP mode
  19. dscp enables copying of a DSCP stored in the conntrack mark into the
  20. ipv4/v6 diffserv field. The mask is a 32bit field and specifies where
  21. in the conntrack mark the DSCP value is located. It must be 6
  22. contiguous bits long. eg. 0xfc000000 would restore the DSCP from the
  23. upper 6 bits of the conntrack mark.
  24. The DSCP copying may be optionally controlled by a statemask. The
  25. statemask is a 32bit field, usually with a single bit set and must not
  26. overlap the dscp mask. The DSCP restore operation will only take place
  27. if the corresponding bit/s in conntrack mark ANDed with the statemask
  28. yield a non zero result.
  29. eg. dscp 0xfc000000 0x01000000 would retrieve the DSCP from the top 6
  30. bits, whilst using bit 25 as a flag to do so. Bit 26 is unused in this
  31. example.
  32. CPMARK mode
  33. cpmark enables copying of the conntrack mark to the packet skb mark. In
  34. this mode it is completely equivalent to the existing act_connmark
  35. action. Additional functionality is provided by the optional mask
  36. parameter, whereby the stored conntrack mark is logically ANDed with the
  37. cpmark mask before being stored into skb mark. This allows shared usage
  38. of the conntrack mark between applications.
  39. eg. cpmark 0x00ffffff would restore only the lower 24 bits of the
  40. conntrack mark, thus may be useful in the event that the upper 8 bits
  41. are used by the DSCP function.
  42. Usage: ... ctinfo [dscp mask [statemask]] [cpmark [mask]] [zone ZONE]
  43. [CONTROL] [index <INDEX>]
  44. where :
  45. dscp MASK is the bitmask to restore DSCP
  46. STATEMASK is the bitmask to determine conditional restoring
  47. cpmark MASK mask applied to restored packet mark
  48. ZONE is the conntrack zone
  49. CONTROL := reclassify | pipe | drop | continue | ok |
  50. goto chain <CHAIN_INDEX>
  51. Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
  52. Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
  53. ---
  54. include/uapi/linux/pkt_cls.h | 3 +-
  55. include/uapi/linux/tc_act/tc_ctinfo.h | 29 +++
  56. man/man8/tc-ctinfo.8 | 170 ++++++++++++++++
  57. tc/Makefile | 1 +
  58. tc/m_ctinfo.c | 268 ++++++++++++++++++++++++++
  59. 5 files changed, 470 insertions(+), 1 deletion(-)
  60. create mode 100644 include/uapi/linux/tc_act/tc_ctinfo.h
  61. create mode 100644 man/man8/tc-ctinfo.8
  62. create mode 100644 tc/m_ctinfo.c
  63. diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
  64. index 95d0db2a..a6e7e176 100644
  65. --- a/include/uapi/linux/pkt_cls.h
  66. +++ b/include/uapi/linux/pkt_cls.h
  67. @@ -68,7 +68,8 @@ enum {
  68. TCA_ID_UNSPEC=0,
  69. TCA_ID_POLICE=1,
  70. /* other actions go here */
  71. - __TCA_ID_MAX=255
  72. + TCA_ID_CTINFO=27,
  73. + __TCA_ID_MAX = 255
  74. };
  75. #define TCA_ID_MAX __TCA_ID_MAX
  76. diff --git a/include/uapi/linux/tc_act/tc_ctinfo.h b/include/uapi/linux/tc_act/tc_ctinfo.h
  77. new file mode 100644
  78. index 00000000..f5f26d95
  79. --- /dev/null
  80. +++ b/include/uapi/linux/tc_act/tc_ctinfo.h
  81. @@ -0,0 +1,29 @@
  82. +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
  83. +#ifndef __UAPI_TC_CTINFO_H
  84. +#define __UAPI_TC_CTINFO_H
  85. +
  86. +#include <linux/types.h>
  87. +#include <linux/pkt_cls.h>
  88. +
  89. +struct tc_ctinfo {
  90. + tc_gen;
  91. +};
  92. +
  93. +enum {
  94. + TCA_CTINFO_UNSPEC,
  95. + TCA_CTINFO_PAD,
  96. + TCA_CTINFO_TM,
  97. + TCA_CTINFO_ACT,
  98. + TCA_CTINFO_ZONE,
  99. + TCA_CTINFO_PARMS_DSCP_MASK,
  100. + TCA_CTINFO_PARMS_DSCP_STATEMASK,
  101. + TCA_CTINFO_PARMS_CPMARK_MASK,
  102. + TCA_CTINFO_STATS_DSCP_SET,
  103. + TCA_CTINFO_STATS_DSCP_ERROR,
  104. + TCA_CTINFO_STATS_CPMARK_SET,
  105. + __TCA_CTINFO_MAX
  106. +};
  107. +
  108. +#define TCA_CTINFO_MAX (__TCA_CTINFO_MAX - 1)
  109. +
  110. +#endif
  111. diff --git a/man/man8/tc-ctinfo.8 b/man/man8/tc-ctinfo.8
  112. new file mode 100644
  113. index 00000000..096590d1
  114. --- /dev/null
  115. +++ b/man/man8/tc-ctinfo.8
  116. @@ -0,0 +1,170 @@
  117. +.TH "ctinfo action in tc" 8 "4 Jun 2019" "iproute2" "Linux"
  118. +.SH NAME
  119. +ctinfo \- tc connmark processing action
  120. +.SH SYNOPSIS
  121. +.B tc ... action ctinfo
  122. +[
  123. +.B dscp
  124. +MASK [STATEMASK] ] [
  125. +.B cpmark
  126. +[MASK] ] [
  127. +.B zone
  128. +ZONE ] [
  129. +.B CONTROL
  130. +] [
  131. +.B index
  132. +<INDEX>
  133. +]
  134. +
  135. +.SH DESCRIPTION
  136. +CTINFO (Conntrack Information) is a tc action for retrieving data from
  137. +conntrack marks into various fields. At present it has two independent
  138. +processing modes which may be viewed as sub-functions.
  139. +
  140. +DSCP mode copies a DSCP stored in conntrack's connmark into the IPv4/v6 diffserv
  141. +field. The copying may conditionally occur based on a flag also stored in the
  142. +connmark. DSCP mode was designed to assist in restoring packet classifications on
  143. +ingress, classifications which may then be used by qdiscs such as CAKE. It may be
  144. +used in any circumstance where ingress classification needs to be maintained across
  145. +links that otherwise bleach or remap according to their own policies.
  146. +
  147. +CPMARK (copymark) mode copies the conntrack connmark into the packet's mark field. Without
  148. +additional parameters it is functionally completely equivalent to the existing
  149. +connmark action. An optional mask may be specified to mask which bits of the
  150. +connmark are restored. This may be useful when DSCP and CPMARK modes are combined.
  151. +
  152. +Simple statistics (tc -s) on DSCP restores and CPMARK copies are maintained where values for
  153. +set indicate a count of packets altered for that mode. DSCP includes an error count
  154. +where the destination packet's diffserv field was unwriteable.
  155. +.SH PARAMETERS
  156. +.SS DSCP mode parameters:
  157. +.IP mask
  158. +A mask of 6 contiguous bits indicating where the DSCP value is located in the 32 bit
  159. +conntrack mark field. A mask must be provided for this mode. mask is a 32 bit
  160. +unsigned value.
  161. +.IP statemask
  162. +A mask of at least 1 bit indicating where a conditional restore flag is located in the
  163. +32 bit conntrack mark field. The statemask bit/s must NOT overlap the mask bits. The
  164. +DSCP will be restored if the conntrack mark logically ANDed with the statemask yields
  165. +a non-zero result. statemask is an optional unsigned 32 bit value.
  166. +.SS CPMARK mode parameters:
  167. +.IP mask
  168. +Store the logically ANDed result of conntrack mark and mask into the packet's mark
  169. +field. Default is 0xffffffff i.e. the whole mark field. mask is an optional unsigned 32 bit
  170. +value
  171. +.SS Overall action parameters:
  172. +.IP zone
  173. +Specify the conntrack zone when doing conntrack lookups for packets.
  174. +zone is a 16bit unsigned decimal value.
  175. +Default is 0.
  176. +.IP CONTROL
  177. +The following keywords allow to control how the tree of qdisc, classes,
  178. +filters and actions is further traversed after this action.
  179. +.RS
  180. +.TP
  181. +.B reclassify
  182. +Restart with the first filter in the current list.
  183. +.TP
  184. +.B pipe
  185. +Continue with the next action attached to the same filter.
  186. +.TP
  187. +.B drop
  188. +Drop the packet.
  189. +.TP
  190. +.B shot
  191. +synonym for
  192. +.B drop
  193. +.TP
  194. +.B continue
  195. +Continue classification with the next filter in line.
  196. +.TP
  197. +.B pass
  198. +Finish classification process and return to calling qdisc for further packet
  199. +processing. This is the default.
  200. +.RE
  201. +.IP index
  202. +Specify an index for this action in order to being able to identify it in later
  203. +commands. index is a 32bit unsigned decimal value.
  204. +.SH EXAMPLES
  205. +Example showing conditional restoration of DSCP on ingress via an IFB
  206. +.RS
  207. +.EX
  208. +
  209. +#Set up the IFB interface
  210. +.br
  211. +tc qdisc add dev ifb4eth0 handle ffff: ingress
  212. +
  213. +#Put CAKE qdisc on it
  214. +.br
  215. +tc qdisc add dev ifb4eth0 root cake bandwidth 40mbit
  216. +
  217. +#Set interface UP
  218. +.br
  219. +ip link set dev ifb4eth0 up
  220. +
  221. +#Add 2 actions, ctinfo to restore dscp & mirred to redirect the packets to IFB
  222. +.br
  223. +tc filter add dev eth0 parent ffff: protocol all prio 10 u32 \\
  224. + match u32 0 0 flowid 1:1 action \\
  225. + ctinfo dscp 0xfc000000 0x01000000 \\
  226. + mirred egress redirect dev ifb4eth0
  227. +
  228. +tc -s qdisc show dev eth0 ingress
  229. +
  230. + filter parent ffff: protocol all pref 10 u32 chain 0
  231. + filter parent ffff: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1
  232. + filter parent ffff: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw
  233. + match 00000000/00000000 at 0
  234. + action order 1: ctinfo zone 0 pipe
  235. + index 2 ref 1 bind 1 dscp 0xfc000000 0x01000000 installed 72 sec used 0 sec DSCP set 1333 error 0 CPMARK set 0
  236. + Action statistics:
  237. + Sent 658484 bytes 1833 pkt (dropped 0, overlimits 0 requeues 0)
  238. + backlog 0b 0p requeues 0
  239. +
  240. + action order 2: mirred (Egress Redirect to device ifb4eth0) stolen
  241. + index 1 ref 1 bind 1 installed 72 sec used 0 sec
  242. + Action statistics:
  243. + Sent 658484 bytes 1833 pkt (dropped 0, overlimits 0 requeues 0)
  244. + backlog 0b 0p requeues 0
  245. +.EE
  246. +.RE
  247. +
  248. +Example showing conditional restoration of DSCP on egress
  249. +
  250. +This may appear nonsensical since iptables marking of egress packets is easy
  251. +to achieve, however the iptables flow classification rules may be extensive
  252. +and so some sort of set once and forget may be useful especially on cpu
  253. +constrained devices.
  254. +.RS
  255. +.EX
  256. +
  257. +# Send unmarked connections to a marking chain which needs to store a DSCP
  258. +and set statemask bit in the connmark
  259. +.br
  260. +iptables -t mangle -A POSTROUTING -o eth0 -m connmark \\
  261. + --mark 0x00000000/0x01000000 -g CLASS_MARKING_CHAIN
  262. +
  263. +# Apply marked DSCP to the packets
  264. +.br
  265. +tc filter add dev eth0 protocol all prio 10 u32 \\
  266. + match u32 0 0 flowid 1:1 action \\
  267. + ctinfo dscp 0xfc000000 0x01000000
  268. +
  269. +tc -s filter show dev eth0
  270. + filter parent 800e: protocol all pref 10 u32 chain 0
  271. + filter parent 800e: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1
  272. + filter parent 800e: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw
  273. + match 00000000/00000000 at 0
  274. + action order 1: ctinfo zone 0 pipe
  275. + index 1 ref 1 bind 1 dscp 0xfc000000 0x01000000 installed 7414 sec used 0 sec DSCP set 53404 error 0 CPMARK set 0
  276. + Action statistics:
  277. + Sent 32890260 bytes 120441 pkt (dropped 0, overlimits 0 requeues 0)
  278. + backlog 0b 0p requeues 0
  279. +.br
  280. +.SH SEE ALSO
  281. +.BR tc (8),
  282. +.BR tc-cake (8)
  283. +.BR tc-connmark (8)
  284. +.BR tc-mirred (8)
  285. +.SH AUTHORS
  286. +ctinfo was written by Kevin Darbyshire-Bryant.
  287. diff --git a/tc/Makefile b/tc/Makefile
  288. index 2edaf2c8..ec93a9a1 100644
  289. --- a/tc/Makefile
  290. +++ b/tc/Makefile
  291. @@ -48,6 +48,7 @@ TCMODULES += m_csum.o
  292. TCMODULES += m_simple.o
  293. TCMODULES += m_vlan.o
  294. TCMODULES += m_connmark.o
  295. +TCMODULES += m_ctinfo.o
  296. TCMODULES += m_bpf.o
  297. TCMODULES += m_tunnel_key.o
  298. TCMODULES += m_sample.o
  299. diff --git a/tc/m_ctinfo.c b/tc/m_ctinfo.c
  300. new file mode 100644
  301. index 00000000..5e451f87
  302. --- /dev/null
  303. +++ b/tc/m_ctinfo.c
  304. @@ -0,0 +1,268 @@
  305. +/* SPDX-License-Identifier: GPL-2.0 */
  306. +/*
  307. + * m_ctinfo.c netfilter ctinfo mark action
  308. + *
  309. + * Copyright (c) 2019 Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
  310. + */
  311. +
  312. +#include <stdio.h>
  313. +#include <stdlib.h>
  314. +#include <unistd.h>
  315. +#include <string.h>
  316. +#include "utils.h"
  317. +#include "tc_util.h"
  318. +#include <linux/tc_act/tc_ctinfo.h>
  319. +
  320. +static void
  321. +explain(void)
  322. +{
  323. + fprintf(stderr,
  324. + "Usage: ... ctinfo [dscp mask [statemask]] [cpmark [mask]] [zone ZONE] [CONTROL] [index <INDEX>]\n"
  325. + "where :\n"
  326. + "\tdscp MASK bitmask location of stored DSCP\n"
  327. + "\t STATEMASK bitmask to determine conditional restoring\n"
  328. + "\tcpmark MASK mask applied to mark on restoration\n"
  329. + "\tZONE is the conntrack zone\n"
  330. + "\tCONTROL := reclassify | pipe | drop | continue | ok |\n"
  331. + "\t goto chain <CHAIN_INDEX>\n");
  332. +}
  333. +
  334. +static void
  335. +usage(void)
  336. +{
  337. + explain();
  338. + exit(-1);
  339. +}
  340. +
  341. +static int
  342. +parse_ctinfo(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
  343. + struct nlmsghdr *n)
  344. +{
  345. + unsigned int cpmarkmask = 0, dscpmask = 0, dscpstatemask = 0;
  346. + struct tc_ctinfo sel = {};
  347. + unsigned short zone = 0;
  348. + char **argv = *argv_p;
  349. + struct rtattr *tail;
  350. + int argc = *argc_p;
  351. + int ok = 0;
  352. + __u8 i;
  353. +
  354. + while (argc > 0) {
  355. + if (matches(*argv, "ctinfo") == 0) {
  356. + ok = 1;
  357. + NEXT_ARG_FWD();
  358. + } else if (matches(*argv, "help") == 0) {
  359. + usage();
  360. + } else {
  361. + break;
  362. + }
  363. +
  364. + }
  365. +
  366. + if (!ok) {
  367. + explain();
  368. + return -1;
  369. + }
  370. +
  371. + if (argc) {
  372. + if (matches(*argv, "dscp") == 0) {
  373. + NEXT_ARG();
  374. + if (get_u32(&dscpmask, *argv, 0)) {
  375. + fprintf(stderr,
  376. + "ctinfo: Illegal dscp \"mask\"\n");
  377. + return -1;
  378. + }
  379. + if (NEXT_ARG_OK()) {
  380. + NEXT_ARG_FWD();
  381. + if (!get_u32(&dscpstatemask, *argv, 0))
  382. + NEXT_ARG_FWD(); /* was a statemask */
  383. + } else {
  384. + NEXT_ARG_FWD();
  385. + }
  386. + }
  387. + }
  388. +
  389. + /* cpmark has optional mask parameter, so the next arg might not */
  390. + /* exist, or it might be the next option, or it may actually be a */
  391. + /* 32bit mask */
  392. + if (argc) {
  393. + if (matches(*argv, "cpmark") == 0) {
  394. + cpmarkmask = ~0;
  395. + if (NEXT_ARG_OK()) {
  396. + NEXT_ARG_FWD();
  397. + if (!get_u32(&cpmarkmask, *argv, 0))
  398. + NEXT_ARG_FWD(); /* was a mask */
  399. + } else {
  400. + NEXT_ARG_FWD();
  401. + }
  402. + }
  403. + }
  404. +
  405. + if (argc) {
  406. + if (matches(*argv, "zone") == 0) {
  407. + NEXT_ARG();
  408. + if (get_u16(&zone, *argv, 10)) {
  409. + fprintf(stderr, "ctinfo: Illegal \"zone\"\n");
  410. + return -1;
  411. + }
  412. + NEXT_ARG_FWD();
  413. + }
  414. + }
  415. +
  416. + parse_action_control_dflt(&argc, &argv, &sel.action,
  417. + false, TC_ACT_PIPE);
  418. +
  419. + if (argc) {
  420. + if (matches(*argv, "index") == 0) {
  421. + NEXT_ARG();
  422. + if (get_u32(&sel.index, *argv, 10)) {
  423. + fprintf(stderr, "ctinfo: Illegal \"index\"\n");
  424. + return -1;
  425. + }
  426. + NEXT_ARG_FWD();
  427. + }
  428. + }
  429. +
  430. + if (dscpmask & dscpstatemask) {
  431. + fprintf(stderr,
  432. + "ctinfo: dscp mask & statemask must NOT overlap\n");
  433. + return -1;
  434. + }
  435. +
  436. + i = ffs(dscpmask);
  437. + if (i && ((~0 & (dscpmask >> (i - 1))) != 0x3f)) {
  438. + fprintf(stderr,
  439. + "ctinfo: dscp mask must be 6 contiguous bits long\n");
  440. + return -1;
  441. + }
  442. +
  443. + tail = addattr_nest(n, MAX_MSG, tca_id);
  444. + addattr_l(n, MAX_MSG, TCA_CTINFO_ACT, &sel, sizeof(sel));
  445. + addattr16(n, MAX_MSG, TCA_CTINFO_ZONE, zone);
  446. +
  447. + if (dscpmask)
  448. + addattr32(n, MAX_MSG,
  449. + TCA_CTINFO_PARMS_DSCP_MASK, dscpmask);
  450. +
  451. + if (dscpstatemask)
  452. + addattr32(n, MAX_MSG,
  453. + TCA_CTINFO_PARMS_DSCP_STATEMASK, dscpstatemask);
  454. +
  455. + if (cpmarkmask)
  456. + addattr32(n, MAX_MSG,
  457. + TCA_CTINFO_PARMS_CPMARK_MASK, cpmarkmask);
  458. +
  459. + addattr_nest_end(n, tail);
  460. +
  461. + *argc_p = argc;
  462. + *argv_p = argv;
  463. + return 0;
  464. +}
  465. +
  466. +static void print_ctinfo_stats(FILE *f, struct rtattr *tb[TCA_CTINFO_MAX + 1])
  467. +{
  468. + struct tcf_t *tm;
  469. +
  470. + if (tb[TCA_CTINFO_TM]) {
  471. + tm = RTA_DATA(tb[TCA_CTINFO_TM]);
  472. +
  473. + print_tm(f, tm);
  474. + }
  475. +
  476. + if (tb[TCA_CTINFO_STATS_DSCP_SET])
  477. + print_lluint(PRINT_ANY, "dscpset", " DSCP set %llu",
  478. + rta_getattr_u64(tb[TCA_CTINFO_STATS_DSCP_SET]));
  479. + if (tb[TCA_CTINFO_STATS_DSCP_ERROR])
  480. + print_lluint(PRINT_ANY, "dscperror", " error %llu",
  481. + rta_getattr_u64(tb[TCA_CTINFO_STATS_DSCP_ERROR]));
  482. +
  483. + if (tb[TCA_CTINFO_STATS_CPMARK_SET])
  484. + print_lluint(PRINT_ANY, "cpmarkset", " CPMARK set %llu",
  485. + rta_getattr_u64(tb[TCA_CTINFO_STATS_CPMARK_SET]));
  486. +}
  487. +
  488. +static int print_ctinfo(struct action_util *au, FILE *f, struct rtattr *arg)
  489. +{
  490. + unsigned int cpmarkmask = ~0, dscpmask = 0, dscpstatemask = 0;
  491. + struct rtattr *tb[TCA_CTINFO_MAX + 1];
  492. + unsigned short zone = 0;
  493. + struct tc_ctinfo *ci;
  494. +
  495. + if (arg == NULL)
  496. + return -1;
  497. +
  498. + parse_rtattr_nested(tb, TCA_CTINFO_MAX, arg);
  499. + if (!tb[TCA_CTINFO_ACT]) {
  500. + print_string(PRINT_FP, NULL, "%s",
  501. + "[NULL ctinfo action parameters]");
  502. + return -1;
  503. + }
  504. +
  505. + ci = RTA_DATA(tb[TCA_CTINFO_ACT]);
  506. +
  507. + if (tb[TCA_CTINFO_PARMS_DSCP_MASK]) {
  508. + if (RTA_PAYLOAD(tb[TCA_CTINFO_PARMS_DSCP_MASK]) >=
  509. + sizeof(__u32))
  510. + dscpmask = rta_getattr_u32(
  511. + tb[TCA_CTINFO_PARMS_DSCP_MASK]);
  512. + else
  513. + print_string(PRINT_FP, NULL, "%s",
  514. + "[invalid dscp mask parameter]");
  515. + }
  516. +
  517. + if (tb[TCA_CTINFO_PARMS_DSCP_STATEMASK]) {
  518. + if (RTA_PAYLOAD(tb[TCA_CTINFO_PARMS_DSCP_STATEMASK]) >=
  519. + sizeof(__u32))
  520. + dscpstatemask = rta_getattr_u32(
  521. + tb[TCA_CTINFO_PARMS_DSCP_STATEMASK]);
  522. + else
  523. + print_string(PRINT_FP, NULL, "%s",
  524. + "[invalid dscp statemask parameter]");
  525. + }
  526. +
  527. + if (tb[TCA_CTINFO_PARMS_CPMARK_MASK]) {
  528. + if (RTA_PAYLOAD(tb[TCA_CTINFO_PARMS_CPMARK_MASK]) >=
  529. + sizeof(__u32))
  530. + cpmarkmask = rta_getattr_u32(
  531. + tb[TCA_CTINFO_PARMS_CPMARK_MASK]);
  532. + else
  533. + print_string(PRINT_FP, NULL, "%s",
  534. + "[invalid cpmark mask parameter]");
  535. + }
  536. +
  537. + if (tb[TCA_CTINFO_ZONE] && RTA_PAYLOAD(tb[TCA_CTINFO_ZONE]) >=
  538. + sizeof(__u16))
  539. + zone = rta_getattr_u16(tb[TCA_CTINFO_ZONE]);
  540. +
  541. + print_string(PRINT_ANY, "kind", "%s ", "ctinfo");
  542. + print_hu(PRINT_ANY, "zone", "zone %u", zone);
  543. + print_action_control(f, " ", ci->action, "");
  544. +
  545. + print_string(PRINT_FP, NULL, "%s", _SL_);
  546. + print_uint(PRINT_ANY, "index", "\t index %u", ci->index);
  547. + print_int(PRINT_ANY, "ref", " ref %d", ci->refcnt);
  548. + print_int(PRINT_ANY, "bind", " bind %d", ci->bindcnt);
  549. +
  550. + if (tb[TCA_CTINFO_PARMS_DSCP_MASK]) {
  551. + print_0xhex(PRINT_ANY, "dscpmask", " dscp %#010llx", dscpmask);
  552. + print_0xhex(PRINT_ANY, "dscpstatemask", " %#010llx",
  553. + dscpstatemask);
  554. + }
  555. +
  556. + if (tb[TCA_CTINFO_PARMS_CPMARK_MASK])
  557. + print_0xhex(PRINT_ANY, "cpmark", " cpmark %#010llx",
  558. + cpmarkmask);
  559. +
  560. + if (show_stats)
  561. + print_ctinfo_stats(f, tb);
  562. +
  563. + print_string(PRINT_FP, NULL, "%s", _SL_);
  564. +
  565. + return 0;
  566. +}
  567. +
  568. +struct action_util ctinfo_action_util = {
  569. + .id = "ctinfo",
  570. + .parse_aopt = parse_ctinfo,
  571. + .print_aopt = print_ctinfo,
  572. +};
  573. --
  574. 2.20.1 (Apple Git-117)