2 * m_bpf.c BFP based action module
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Jiri Pirko <jiri@resnulli.us>
17 #include <linux/tc_act/tc_bpf.h>
24 static void explain(void)
26 fprintf(stderr
, "Usage: ... bpf ...\n");
27 fprintf(stderr
, "\n");
28 fprintf(stderr
, " [inline]: run bytecode BPF_BYTECODE\n");
29 fprintf(stderr
, " [from file]: run bytecode-file FILE\n");
30 fprintf(stderr
, "\n");
31 fprintf(stderr
, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n");
32 fprintf(stderr
, " c,t,f,k and s are decimals; s denotes number of 4-tuples\n");
33 fprintf(stderr
, "Where FILE points to a file containing the BPF_BYTECODE string\n");
34 fprintf(stderr
, "\nACTION_SPEC := ... look at individual actions\n");
35 fprintf(stderr
, "NOTE: CLASSID is parsed as hexadecimal input.\n");
38 static void usage(void)
44 static int parse_bpf(struct action_util
*a
, int *argc_p
, char ***argv_p
,
45 int tca_id
, struct nlmsghdr
*n
)
48 char **argv
= *argv_p
;
50 struct tc_act_bpf parm
= { 0 };
51 struct sock_filter bpf_ops
[BPF_MAXINSNS
];
54 if (matches(*argv
, "bpf") != 0)
60 if (matches(*argv
, "run") == 0) {
65 if (strcmp(*argv
, "bytecode-file") == 0) {
67 } else if (strcmp(*argv
, "bytecode") == 0) {
70 fprintf(stderr
, "unexpected \"%s\"\n", *argv
);
75 ret
= bpf_parse_ops(argc
, argv
, bpf_ops
, from_file
);
77 fprintf(stderr
, "Illegal \"bytecode\"\n");
81 } else if (matches(*argv
, "help") == 0) {
90 parm
.action
= TC_ACT_PIPE
;
92 if (matches(*argv
, "reclassify") == 0) {
93 parm
.action
= TC_ACT_RECLASSIFY
;
95 } else if (matches(*argv
, "pipe") == 0) {
96 parm
.action
= TC_ACT_PIPE
;
98 } else if (matches(*argv
, "drop") == 0 ||
99 matches(*argv
, "shot") == 0) {
100 parm
.action
= TC_ACT_SHOT
;
102 } else if (matches(*argv
, "continue") == 0) {
103 parm
.action
= TC_ACT_UNSPEC
;
105 } else if (matches(*argv
, "pass") == 0) {
106 parm
.action
= TC_ACT_OK
;
112 if (matches(*argv
, "index") == 0) {
114 if (get_u32(&parm
.index
, *argv
, 10)) {
115 fprintf(stderr
, "bpf: Illegal \"index\"\n");
124 fprintf(stderr
, "bpf: Bytecode needs to be passed\n");
129 tail
= NLMSG_TAIL(n
);
130 addattr_l(n
, MAX_MSG
, tca_id
, NULL
, 0);
131 addattr_l(n
, MAX_MSG
, TCA_ACT_BPF_PARMS
, &parm
, sizeof(parm
));
132 addattr16(n
, MAX_MSG
, TCA_ACT_BPF_OPS_LEN
, bpf_len
);
133 addattr_l(n
, MAX_MSG
, TCA_ACT_BPF_OPS
, &bpf_ops
,
134 bpf_len
* sizeof(struct sock_filter
));
135 tail
->rta_len
= (char *)NLMSG_TAIL(n
) - (char *)tail
;
142 static int print_bpf(struct action_util
*au
, FILE *f
, struct rtattr
*arg
)
144 struct rtattr
*tb
[TCA_ACT_BPF_MAX
+ 1];
145 struct tc_act_bpf
*parm
;
150 parse_rtattr_nested(tb
, TCA_ACT_BPF_MAX
, arg
);
152 if (!tb
[TCA_ACT_BPF_PARMS
]) {
153 fprintf(f
, "[NULL bpf parameters]");
156 parm
= RTA_DATA(tb
[TCA_ACT_BPF_PARMS
]);
160 if (tb
[TCA_ACT_BPF_OPS
] && tb
[TCA_ACT_BPF_OPS_LEN
])
161 bpf_print_ops(f
, tb
[TCA_ACT_BPF_OPS
],
162 rta_getattr_u16(tb
[TCA_ACT_BPF_OPS_LEN
]));
164 fprintf(f
, "\n\tindex %d ref %d bind %d", parm
->index
, parm
->refcnt
,
168 if (tb
[TCA_ACT_BPF_TM
]) {
169 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_ACT_BPF_TM
]);
179 struct action_util bpf_action_util
= {
181 .parse_aopt
= parse_bpf
,
182 .print_aopt
= print_bpf
,