FD.io VPP  v18.01.2-1-g9b554f3
Vector Packet Processing
request_node.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <vnet/dns/dns.h>
17 
18 #include <vlib/vlib.h>
19 #include <vnet/vnet.h>
20 
22 
23 typedef struct
24 {
28 
29 /* packet trace format function */
30 static u8 *
31 format_dns46_request_trace (u8 * s, va_list * args)
32 {
33  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
34  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
35  dns46_request_trace_t *t = va_arg (*args, dns46_request_trace_t *);
36 
37  s = format (s, "DNS46_REPLY: pool index %d, disposition %d",
38  t->pool_index, t->disposition);
39  return s;
40 }
41 
43 
44 static char *dns46_request_error_strings[] = {
45 #define _(sym,string) string,
47 #undef _
48 };
49 
50 typedef enum
51 {
57 
58 static uword
60  vlib_node_runtime_t * node, vlib_frame_t * frame,
61  int is_ip6)
62 {
63  u32 n_left_from, *from, *to_next;
64  dns46_request_next_t next_index;
65  dns_main_t *dm = &dns_main;
66 
67  from = vlib_frame_vector_args (frame);
68  n_left_from = frame->n_vectors;
69  next_index = node->cached_next_index;
70 
71  while (n_left_from > 0)
72  {
73  u32 n_left_to_next;
74 
75  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
76 
77 #if 0
78  while (n_left_from >= 4 && n_left_to_next >= 2)
79  {
80  u32 next0 = DNS46_REQUEST_NEXT_INTERFACE_OUTPUT;
81  u32 next1 = DNS46_REQUEST_NEXT_INTERFACE_OUTPUT;
82  u32 sw_if_index0, sw_if_index1;
83  u8 tmp0[6], tmp1[6];
84  ethernet_header_t *en0, *en1;
85  u32 bi0, bi1;
86  vlib_buffer_t *b0, *b1;
87 
88  /* Prefetch next iteration. */
89  {
90  vlib_buffer_t *p2, *p3;
91 
92  p2 = vlib_get_buffer (vm, from[2]);
93  p3 = vlib_get_buffer (vm, from[3]);
94 
95  vlib_prefetch_buffer_header (p2, LOAD);
96  vlib_prefetch_buffer_header (p3, LOAD);
97 
100  }
101 
102  /* speculatively enqueue b0 and b1 to the current next frame */
103  to_next[0] = bi0 = from[0];
104  to_next[1] = bi1 = from[1];
105  from += 2;
106  to_next += 2;
107  n_left_from -= 2;
108  n_left_to_next -= 2;
109 
110  b0 = vlib_get_buffer (vm, bi0);
111  b1 = vlib_get_buffer (vm, bi1);
112 
113  /* $$$$$ End of processing 2 x packets $$$$$ */
114 
115  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
116  {
117  if (b0->flags & VLIB_BUFFER_IS_TRACED)
118  {
120  vlib_add_trace (vm, node, b0, sizeof (*t));
121  t->sw_if_index = sw_if_index0;
122  t->next_index = next0;
123  }
124  if (b1->flags & VLIB_BUFFER_IS_TRACED)
125  {
127  vlib_add_trace (vm, node, b1, sizeof (*t));
128  t->sw_if_index = sw_if_index1;
129  t->next_index = next1;
130  }
131  }
132 
133  /* verify speculative enqueues, maybe switch current next frame */
134  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
135  to_next, n_left_to_next,
136  bi0, bi1, next0, next1);
137  }
138 #endif
139 
140  while (n_left_from > 0 && n_left_to_next > 0)
141  {
142  u32 bi0;
143  vlib_buffer_t *b0;
145  u32 error0 = DNS46_REQUEST_ERROR_NONE;
146  udp_header_t *u0;
147  dns_header_t *d0;
148  dns_query_t *q0;
149  ip4_header_t *ip40 = 0;
150  ip6_header_t *ip60 = 0;
151  dns_cache_entry_t *ep0;
152  dns_pending_request_t _t0, *t0 = &_t0;
153  u16 flags0;
154  u32 pool_index0 = ~0;
155  u8 *name0;
156  u8 *label0;
157 
158  /* speculatively enqueue b0 to the current next frame */
159  bi0 = from[0];
160  to_next[0] = bi0;
161  from += 1;
162  to_next += 1;
163  n_left_from -= 1;
164  n_left_to_next -= 1;
165 
166  b0 = vlib_get_buffer (vm, bi0);
167  d0 = vlib_buffer_get_current (b0);
168  u0 = (udp_header_t *) ((u8 *) d0 - sizeof (*u0));
169 
170  if (PREDICT_FALSE (dm->is_enabled == 0))
171  {
172  next0 = DNS46_REQUEST_NEXT_PUNT;
173  goto done0;
174  }
175 
176  if (is_ip6)
177  {
178  ip60 = (ip6_header_t *) (((u8 *) u0) - sizeof (ip6_header_t));
179  next0 = DNS46_REQUEST_NEXT_DROP;
180  error0 = DNS46_REQUEST_ERROR_UNIMPLEMENTED;
181  goto done0;
182  }
183  else
184  {
185  ip40 = (ip4_header_t *) (((u8 *) u0) - sizeof (ip4_header_t));
186  if (ip40->ip_version_and_header_length != 0x45)
187  {
188  error0 = DNS46_REQUEST_ERROR_IP_OPTIONS;
189  goto done0;
190  }
191  }
192  /* Parse through the DNS request */
193  flags0 = clib_net_to_host_u16 (d0->flags);
194 
195  /* Requests only */
196  if (flags0 & DNS_QR)
197  {
198  next0 = DNS46_REQUEST_NEXT_DROP;
199  error0 = DNS46_REQUEST_ERROR_BAD_REQUEST;
200  goto done0;
201  }
202  if (clib_net_to_host_u16 (d0->qdcount) != 1)
203  {
204  next0 = DNS46_REQUEST_NEXT_DROP;
205  error0 = DNS46_REQUEST_ERROR_TOO_MANY_REQUESTS;
206  goto done0;
207  }
208 
209  label0 = (u8 *) (d0 + 1);
210 
211  name0 = vnet_dns_labels_to_name (label0, (u8 *) d0, (u8 **) & q0);
212 
214 
215  /*
216  * See if this is a reverse lookup. Both ip4 and ip6 reverse
217  * requests end with ".arpa"
218  */
219  if (PREDICT_TRUE (vec_len (name0) > 5))
220  {
221  u8 *aptr0 = name0 + vec_len (name0) - 5;
222 
223  if (!memcmp (aptr0, ".arpa", 5))
225  }
226 
227  t0->client_index = ~0;
228  t0->is_ip6 = is_ip6;
229  t0->dst_port = u0->src_port;
230  t0->id = d0->id;
231  t0->name = name0;
232  if (is_ip6)
234  sizeof (ip6_address_t));
235  else
237  sizeof (ip4_address_t));
238 
239  vnet_dns_resolve_name (dm, name0, t0, &ep0);
240 
241  if (ep0)
242  {
243  if (is_ip6)
244  vnet_send_dns6_reply (dm, t0, ep0, b0);
245  else
246  vnet_send_dns4_reply (dm, t0, ep0, b0);
248  }
249  else
250  {
251  error0 = DNS46_REQUEST_ERROR_RESOLUTION_REQUIRED;
252  }
253 
254  done0:
255  b0->error = node->errors[error0];
256 
258  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
259  {
261  vlib_add_trace (vm, node, b0, sizeof (*t));
262  t->disposition = error0;
263  t->pool_index = pool_index0;
264  }
265 
266  /* verify speculative enqueue, maybe switch current next frame */
267  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
268  to_next, n_left_to_next,
269  bi0, next0);
270  }
271 
272  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
273  }
274 
275  return frame->n_vectors;
276 }
277 
278 static uword
280  vlib_node_runtime_t * node, vlib_frame_t * frame)
281 {
282 
283  return dns46_request_inline (vm, node, frame, 0 /* is_ip6 */ );
284 }
285 
286 /* *INDENT-OFF* */
288 {
289  .function = dns4_request_node_fn,
290  .name = "dns4-request",
291  .vector_size = sizeof (u32),
292  .format_trace = format_dns46_request_trace,
293  .type = VLIB_NODE_TYPE_INTERNAL,
295  .error_strings = dns46_request_error_strings,
296  .n_next_nodes = DNS46_REQUEST_N_NEXT,
297  .next_nodes = {
298  [DNS46_REQUEST_NEXT_DROP] = "error-drop",
299  [DNS46_REQUEST_NEXT_PUNT] = "error-punt",
300  [DNS46_REQUEST_NEXT_IP_LOOKUP] = "ip4-lookup",
301  },
302 };
303 /* *INDENT-ON* */
304 
305 static uword
307  vlib_node_runtime_t * node, vlib_frame_t * frame)
308 {
309 
310  return dns46_request_inline (vm, node, frame, 1 /* is_ip6 */ );
311 }
312 
313 /* *INDENT-OFF* */
315 {
316  .function = dns6_request_node_fn,
317  .name = "dns6-request",
318  .vector_size = sizeof (u32),
319  .format_trace = format_dns46_request_trace,
320  .type = VLIB_NODE_TYPE_INTERNAL,
322  .error_strings = dns46_request_error_strings,
323  .n_next_nodes = DNS46_REQUEST_N_NEXT,
324  .next_nodes = {
325  [DNS46_REQUEST_NEXT_DROP] = "error-drop",
326  [DNS46_REQUEST_NEXT_PUNT] = "error-punt",
327  [DNS46_REQUEST_NEXT_IP_LOOKUP] = "ip6-lookup",
328  },
329 };
330 /* *INDENT-ON* */
331 
332 /*
333  * fd.io coding-style-patch-verification: ON
334  *
335  * Local Variables:
336  * eval: (c-set-style "gnu")
337  * End:
338  */
Definition: dns.h:48
#define CLIB_UNUSED(x)
Definition: clib.h:79
ip4_address_t src_address
Definition: ip4_packet.h:164
#define PREDICT_TRUE(x)
Definition: clib.h:106
u8 as_u8[16]
Definition: ip6_packet.h:48
struct _vlib_node_registration vlib_node_registration_t
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:415
vlib_node_registration_t dns46_request_node
Definition: request_node.c:21
ip6_address_t src_address
Definition: ip6_packet.h:341
dns_main_t dns_main
Definition: dns.c:42
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:171
void vnet_send_dns4_reply(dns_main_t *dm, dns_pending_request_t *pr, dns_cache_entry_t *ep, vlib_buffer_t *b0)
Definition: dns.c:2652
static uword dns4_request_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: request_node.c:279
#define DNS_QR
query=0, response=1
Definition: dns_packet.h:50
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:195
#define PREDICT_FALSE(x)
Definition: clib.h:105
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:218
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:364
vlib_node_registration_t dns6_request_node
(constructor) VLIB_REGISTER_NODE (dns6_request_node)
Definition: request_node.c:314
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:113
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
static uword dns46_request_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_ip6)
Definition: request_node.c:59
vlib_main_t * vm
Definition: buffer.c:283
static uword dns6_request_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: request_node.c:306
int vnet_dns_resolve_name(dns_main_t *dm, u8 *name, dns_pending_request_t *t, dns_cache_entry_t **retp)
Definition: dns.c:766
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
vlib_node_registration_t dns4_request_node
(constructor) VLIB_REGISTER_NODE (dns4_request_node)
Definition: request_node.c:287
#define clib_memcpy(a, b, c)
Definition: string.h:75
#define ARRAY_LEN(x)
Definition: clib.h:59
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:454
dns46_request_next_t
Definition: request_node.c:50
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:456
unsigned int u32
Definition: types.h:88
u8 * vnet_dns_labels_to_name(u8 *label, u8 *full_text, u8 **parse_from_here)
arc-function for the above.
Definition: dns.c:473
u8 dst_address[16]
Definition: dns.h:36
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
unsigned short u16
Definition: types.h:57
static char * dns46_request_error_strings[]
Definition: request_node.c:44
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
void vnet_send_dns6_reply(dns_main_t *dm, dns_pending_request_t *pr, dns_cache_entry_t *ep, vlib_buffer_t *b0)
Definition: dns.c:2644
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
Definition: dns.h:88
static u8 * format_dns46_request_trace(u8 *s, va_list *args)
Definition: request_node.c:31
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 data[0]
Packet data.
Definition: buffer.h:159
u16 flags
Copy of main node flags.
Definition: node.h:450
u8 ip_version_and_header_length
Definition: ip4_packet.h:132
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:75
#define foreach_dns46_request_error
Definition: dns.h:124
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
int is_enabled
enable / disable flag
Definition: dns.h:101