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