libnftnl  1.3.2
queue.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * (C) 2013 by Eric Leblond <eric@regit.org>
4  */
5 
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <string.h>
9 #include <arpa/inet.h>
10 #include <errno.h>
11 #include <linux/netfilter/nf_tables.h>
12 
13 #include "internal.h"
14 #include <libmnl/libmnl.h>
15 #include <libnftnl/expr.h>
16 #include <libnftnl/rule.h>
17 
19  enum nft_registers sreg_qnum;
20  uint16_t queuenum;
21  uint16_t queues_total;
22  uint16_t flags;
23 };
24 
25 static int
26 nftnl_expr_queue_set(struct nftnl_expr *e, uint16_t type,
27  const void *data, uint32_t data_len, uint32_t byteorder)
28 {
29  struct nftnl_expr_queue *queue = nftnl_expr_data(e);
30 
31  switch(type) {
32  case NFTNL_EXPR_QUEUE_NUM:
33  memcpy(&queue->queuenum, data, data_len);
34  break;
35  case NFTNL_EXPR_QUEUE_TOTAL:
36  memcpy(&queue->queues_total, data, data_len);
37  break;
38  case NFTNL_EXPR_QUEUE_FLAGS:
39  memcpy(&queue->flags, data, data_len);
40  break;
41  case NFTNL_EXPR_QUEUE_SREG_QNUM:
42  memcpy(&queue->sreg_qnum, data, data_len);
43  break;
44  }
45  return 0;
46 }
47 
48 static const void *
49 nftnl_expr_queue_get(const struct nftnl_expr *e, uint16_t type,
50  uint32_t *data_len)
51 {
52  struct nftnl_expr_queue *queue = nftnl_expr_data(e);
53 
54  switch(type) {
55  case NFTNL_EXPR_QUEUE_NUM:
56  *data_len = sizeof(queue->queuenum);
57  return &queue->queuenum;
58  case NFTNL_EXPR_QUEUE_TOTAL:
59  *data_len = sizeof(queue->queues_total);
60  return &queue->queues_total;
61  case NFTNL_EXPR_QUEUE_FLAGS:
62  *data_len = sizeof(queue->flags);
63  return &queue->flags;
64  case NFTNL_EXPR_QUEUE_SREG_QNUM:
65  *data_len = sizeof(queue->sreg_qnum);
66  return &queue->sreg_qnum;
67  }
68  return NULL;
69 }
70 
71 static int nftnl_expr_queue_cb(const struct nlattr *attr, void *data)
72 {
73  const struct nlattr **tb = data;
74  int type = mnl_attr_get_type(attr);
75 
76  if (mnl_attr_type_valid(attr, NFTA_QUEUE_MAX) < 0)
77  return MNL_CB_OK;
78 
79  switch(type) {
80  case NFTA_QUEUE_NUM:
81  case NFTA_QUEUE_TOTAL:
82  case NFTA_QUEUE_FLAGS:
83  if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
84  abi_breakage();
85  break;
86  case NFTA_QUEUE_SREG_QNUM:
87  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
88  abi_breakage();
89  break;
90  }
91 
92  tb[type] = attr;
93  return MNL_CB_OK;
94 }
95 
96 static void
97 nftnl_expr_queue_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
98 {
99  struct nftnl_expr_queue *queue = nftnl_expr_data(e);
100 
101  if (e->flags & (1 << NFTNL_EXPR_QUEUE_NUM))
102  mnl_attr_put_u16(nlh, NFTA_QUEUE_NUM, htons(queue->queuenum));
103  if (e->flags & (1 << NFTNL_EXPR_QUEUE_TOTAL))
104  mnl_attr_put_u16(nlh, NFTA_QUEUE_TOTAL, htons(queue->queues_total));
105  if (e->flags & (1 << NFTNL_EXPR_QUEUE_FLAGS))
106  mnl_attr_put_u16(nlh, NFTA_QUEUE_FLAGS, htons(queue->flags));
107  if (e->flags & (1 << NFTNL_EXPR_QUEUE_SREG_QNUM))
108  mnl_attr_put_u32(nlh, NFTA_QUEUE_SREG_QNUM, htonl(queue->sreg_qnum));
109 }
110 
111 static int
112 nftnl_expr_queue_parse(struct nftnl_expr *e, struct nlattr *attr)
113 {
114  struct nftnl_expr_queue *queue = nftnl_expr_data(e);
115  struct nlattr *tb[NFTA_QUEUE_MAX+1] = {};
116 
117  if (mnl_attr_parse_nested(attr, nftnl_expr_queue_cb, tb) < 0)
118  return -1;
119 
120  if (tb[NFTA_QUEUE_NUM]) {
121  queue->queuenum = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_NUM]));
122  e->flags |= (1 << NFTNL_EXPR_QUEUE_NUM);
123  }
124  if (tb[NFTA_QUEUE_TOTAL]) {
125  queue->queues_total = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_TOTAL]));
126  e->flags |= (1 << NFTNL_EXPR_QUEUE_TOTAL);
127  }
128  if (tb[NFTA_QUEUE_FLAGS]) {
129  queue->flags = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_FLAGS]));
130  e->flags |= (1 << NFTNL_EXPR_QUEUE_FLAGS);
131  }
132  if (tb[NFTA_QUEUE_SREG_QNUM]) {
133  queue->sreg_qnum = ntohl(mnl_attr_get_u32(tb[NFTA_QUEUE_SREG_QNUM]));
134  e->flags |= (1 << NFTNL_EXPR_QUEUE_SREG_QNUM);
135  }
136 
137  return 0;
138 }
139 
140 static int
141 nftnl_expr_queue_snprintf(char *buf, size_t remain,
142  uint32_t flags, const struct nftnl_expr *e)
143 {
144  struct nftnl_expr_queue *queue = nftnl_expr_data(e);
145  uint16_t total_queues;
146  int ret, offset = 0;
147 
148  if (e->flags & (1 << NFTNL_EXPR_QUEUE_NUM)) {
149  total_queues = queue->queuenum + queue->queues_total - 1;
150 
151  ret = snprintf(buf + offset, remain, "num %u", queue->queuenum);
152  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
153 
154  if (queue->queues_total && total_queues != queue->queuenum) {
155  ret = snprintf(buf + offset, remain, "-%u", total_queues);
156  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
157  }
158 
159  ret = snprintf(buf + offset, remain, " ");
160  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
161  }
162 
163  if (e->flags & (1 << NFTNL_EXPR_QUEUE_SREG_QNUM)) {
164  ret = snprintf(buf + offset, remain, "sreg_qnum %u ",
165  queue->sreg_qnum);
166  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
167  }
168 
169  if (e->flags & (1 << NFTNL_EXPR_QUEUE_FLAGS)) {
170  if (queue->flags & (NFT_QUEUE_FLAG_BYPASS)) {
171  ret = snprintf(buf + offset, remain, "bypass ");
172  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
173  }
174  if (queue->flags & (NFT_QUEUE_FLAG_CPU_FANOUT)) {
175  ret = snprintf(buf + offset, remain, "fanout ");
176  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
177  }
178  }
179  return offset;
180 }
181 
182 static struct attr_policy queue_attr_policy[__NFTNL_EXPR_QUEUE_MAX] = {
183  [NFTNL_EXPR_QUEUE_NUM] = { .maxlen = sizeof(uint16_t) },
184  [NFTNL_EXPR_QUEUE_TOTAL] = { .maxlen = sizeof(uint16_t) },
185  [NFTNL_EXPR_QUEUE_FLAGS] = { .maxlen = sizeof(uint16_t) },
186  [NFTNL_EXPR_QUEUE_SREG_QNUM] = { .maxlen = sizeof(uint32_t) },
187 };
188 
189 struct expr_ops expr_ops_queue = {
190  .name = "queue",
191  .alloc_len = sizeof(struct nftnl_expr_queue),
192  .nftnl_max_attr = __NFTNL_EXPR_QUEUE_MAX - 1,
193  .attr_policy = queue_attr_policy,
194  .set = nftnl_expr_queue_set,
195  .get = nftnl_expr_queue_get,
196  .parse = nftnl_expr_queue_parse,
197  .build = nftnl_expr_queue_build,
198  .output = nftnl_expr_queue_snprintf,
199 };