14 #include <arpa/inet.h>
16 #include <linux/netfilter/nf_tables.h>
19 #include <libmnl/libmnl.h>
20 #include <libnftnl/expr.h>
21 #include <libnftnl/rule.h>
26 uint16_t queues_total;
30 static int nft_rule_expr_queue_set(
struct nft_rule_expr *e, uint16_t type,
31 const void *data, uint32_t data_len)
36 case NFT_EXPR_QUEUE_NUM:
37 queue->queuenum = *((uint16_t *)data);
39 case NFT_EXPR_QUEUE_TOTAL:
40 queue->queues_total = *((uint16_t *)data);
42 case NFT_EXPR_QUEUE_FLAGS:
43 queue->flags = *((uint16_t *)data);
52 nft_rule_expr_queue_get(
const struct nft_rule_expr *e, uint16_t type,
58 case NFT_EXPR_QUEUE_NUM:
59 *data_len =
sizeof(queue->queuenum);
60 return &queue->queuenum;
61 case NFT_EXPR_QUEUE_TOTAL:
62 *data_len =
sizeof(queue->queues_total);
63 return &queue->queues_total;
64 case NFT_EXPR_QUEUE_FLAGS:
65 *data_len =
sizeof(queue->flags);
71 static int nft_rule_expr_queue_cb(
const struct nlattr *attr,
void *data)
73 const struct nlattr **tb = data;
74 int type = mnl_attr_get_type(attr);
76 if (mnl_attr_type_valid(attr, NFTA_QUEUE_MAX) < 0)
81 case NFTA_QUEUE_TOTAL:
82 case NFTA_QUEUE_FLAGS:
83 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
84 perror(
"mnl_attr_validate");
95 nft_rule_expr_queue_build(
struct nlmsghdr *nlh,
struct nft_rule_expr *e)
99 if (e->flags & (1 << NFT_EXPR_QUEUE_NUM))
100 mnl_attr_put_u16(nlh, NFTA_QUEUE_NUM, htons(queue->queuenum));
101 if (e->flags & (1 << NFT_EXPR_QUEUE_TOTAL))
102 mnl_attr_put_u16(nlh, NFTA_QUEUE_TOTAL, htons(queue->queues_total));
103 if (e->flags & (1 << NFT_EXPR_QUEUE_FLAGS))
104 mnl_attr_put_u16(nlh, NFTA_QUEUE_FLAGS, htons(queue->flags));
108 nft_rule_expr_queue_parse(
struct nft_rule_expr *e,
struct nlattr *attr)
111 struct nlattr *tb[NFTA_QUEUE_MAX+1] = {};
113 if (mnl_attr_parse_nested(attr, nft_rule_expr_queue_cb, tb) < 0)
116 if (tb[NFTA_QUEUE_NUM]) {
117 queue->queuenum = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_NUM]));
118 e->flags |= (1 << NFT_EXPR_QUEUE_NUM);
120 if (tb[NFTA_QUEUE_TOTAL]) {
121 queue->queues_total = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_TOTAL]));
122 e->flags |= (1 << NFT_EXPR_QUEUE_TOTAL);
124 if (tb[NFTA_QUEUE_FLAGS]) {
125 queue->flags = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_FLAGS]));
126 e->flags |= (1 << NFT_EXPR_QUEUE_FLAGS);
133 nft_rule_expr_queue_json_parse(
struct nft_rule_expr *e, json_t *root,
134 struct nft_parse_err *err)
140 if (nft_jansson_parse_val(root,
"num", NFT_TYPE_U16, &type, err) == 0)
141 nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_NUM, type);
142 nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_NUM, type);
144 if (nft_jansson_parse_val(root,
"total", NFT_TYPE_U16, &code, err) == 0)
145 nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_TOTAL, code);
147 if (nft_jansson_parse_val(root,
"flags", NFT_TYPE_U16, &code, err) == 0)
148 nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_FLAGS, code);
158 nft_rule_expr_queue_xml_parse(
struct nft_rule_expr *e, mxml_node_t *tree,
159 struct nft_parse_err *err)
162 uint16_t queue_num, queue_total, flags;
164 if (nft_mxml_num_parse(tree,
"num", MXML_DESCEND_FIRST, BASE_DEC,
165 &queue_num, NFT_TYPE_U16, NFT_XML_MAND,
167 nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_NUM, queue_num);
169 if (nft_mxml_num_parse(tree,
"total", MXML_DESCEND_FIRST, BASE_DEC,
170 &queue_total, NFT_TYPE_U16,
171 NFT_XML_MAND, err) == 0)
172 nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_TOTAL, queue_total);
174 if (nft_mxml_num_parse(tree,
"flags", MXML_DESCEND_FIRST, BASE_DEC,
175 &flags, NFT_TYPE_U16,
176 NFT_XML_MAND, err) == 0)
177 nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_FLAGS, flags);
186 static int nft_rule_expr_queue_snprintf_default(
char *buf,
size_t len,
187 struct nft_rule_expr *e)
190 int ret, size = len, offset = 0;
191 uint16_t total_queues;
193 total_queues = queue->queuenum + queue->queues_total -1;
195 ret = snprintf(buf + offset, len,
"num %u", queue->queuenum);
196 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
198 if (queue->queues_total && total_queues != queue->queuenum) {
199 ret = snprintf(buf + offset, len,
"-%u", total_queues);
200 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
203 if (e->flags & (1 << NFT_EXPR_QUEUE_FLAGS)) {
204 if (queue->flags & (NFT_QUEUE_FLAG_BYPASS)) {
205 ret = snprintf(buf + offset, len,
" bypass");
206 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
208 if (queue->flags & (NFT_QUEUE_FLAG_CPU_FANOUT)) {
209 ret = snprintf(buf + offset, len,
" fanout");
210 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
216 static int nft_rule_expr_queue_snprintf_xml(
char *buf,
size_t len,
217 struct nft_rule_expr *e)
219 int ret, size = len, offset = 0;
222 if (e->flags & (1 << NFT_EXPR_QUEUE_NUM)) {
223 ret = snprintf(buf + offset, len,
"<num>%u</num>",
225 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
228 if (e->flags & (1 << NFT_EXPR_QUEUE_TOTAL)) {
229 ret = snprintf(buf + offset, len,
"<total>%u</total>",
230 queue->queues_total);
231 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
233 if (e->flags & (1 << NFT_EXPR_QUEUE_FLAGS)) {
234 ret = snprintf(buf + offset, len,
"<flags>%u</flags>",
236 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
241 static int nft_rule_expr_queue_snprintf_json(
char *buf,
size_t len,
242 struct nft_rule_expr *e)
244 int ret, size = len, offset = 0;
247 if (e->flags & (1 << NFT_EXPR_QUEUE_NUM)) {
248 ret = snprintf(buf + offset, len,
"\"num\":%u,",
250 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
253 if (e->flags & (1 << NFT_EXPR_QUEUE_TOTAL)) {
254 ret = snprintf(buf + offset, len,
"\"total\":%u,",
255 queue->queues_total);
256 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
258 if (e->flags & (1 << NFT_EXPR_QUEUE_FLAGS)) {
259 ret = snprintf(buf + offset, len,
"\"flags\":%u,",
261 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
272 nft_rule_expr_queue_snprintf(
char *buf,
size_t len, uint32_t type,
273 uint32_t flags,
struct nft_rule_expr *e)
277 case NFT_OUTPUT_DEFAULT:
278 return nft_rule_expr_queue_snprintf_default(buf, len, e);
280 return nft_rule_expr_queue_snprintf_xml(buf, len, e);
281 case NFT_OUTPUT_JSON:
282 return nft_rule_expr_queue_snprintf_json(buf, len, e);
289 struct expr_ops expr_ops_queue = {
292 .max_attr = NFTA_QUEUE_MAX,
293 .set = nft_rule_expr_queue_set,
294 .get = nft_rule_expr_queue_get,
295 .parse = nft_rule_expr_queue_parse,
296 .build = nft_rule_expr_queue_build,
297 .snprintf = nft_rule_expr_queue_snprintf,
298 .xml_parse = nft_rule_expr_queue_xml_parse,
299 .json_parse = nft_rule_expr_queue_json_parse,
302 static void __init expr_queue_init(
void)
304 nft_expr_ops_register(&expr_ops_queue);