FD.io VPP  v19.04-6-g6f05f72
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  /*
212  * vnet_dns_labels_to_name produces a non NULL terminated vector
213  * vnet_dns_resolve_name expects a C-string.
214  */
215  name0 = vnet_dns_labels_to_name (label0, (u8 *) d0, (u8 **) & q0);
216  vec_add1 (name0, 0);
217  _vec_len (name0) -= 1;
218 
220 
221  /*
222  * See if this is a reverse lookup. Both ip4 and ip6 reverse
223  * requests end with ".arpa"
224  */
225  if (PREDICT_TRUE (vec_len (name0) > 5))
226  {
227  u8 *aptr0 = name0 + vec_len (name0) - 5;
228 
229  if (!memcmp (aptr0, ".arpa", 5))
231  }
232 
233  t0->client_index = ~0;
234  t0->is_ip6 = is_ip6;
235  t0->dst_port = u0->src_port;
236  t0->id = d0->id;
237  t0->name = name0;
238  if (is_ip6)
240  sizeof (ip6_address_t));
241  else
243  sizeof (ip4_address_t));
244 
245  vnet_dns_resolve_name (dm, name0, t0, &ep0);
246 
247  if (ep0)
248  {
249  if (is_ip6)
250  vnet_send_dns6_reply (dm, t0, ep0, b0);
251  else
252  vnet_send_dns4_reply (dm, t0, ep0, b0);
254  }
255  else
256  {
257  error0 = DNS46_REQUEST_ERROR_RESOLUTION_REQUIRED;
258  }
259 
260  done0:
261  b0->error = node->errors[error0];
262 
264  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
265  {
267  vlib_add_trace (vm, node, b0, sizeof (*t));
268  t->disposition = error0;
269  t->pool_index = pool_index0;
270  }
271 
272  /* verify speculative enqueue, maybe switch current next frame */
273  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
274  to_next, n_left_to_next,
275  bi0, next0);
276  }
277 
278  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
279  }
280 
281  return frame->n_vectors;
282 }
283 
284 static uword
286  vlib_node_runtime_t * node, vlib_frame_t * frame)
287 {
288 
289  return dns46_request_inline (vm, node, frame, 0 /* is_ip6 */ );
290 }
291 
292 /* *INDENT-OFF* */
294 {
295  .function = dns4_request_node_fn,
296  .name = "dns4-request",
297  .vector_size = sizeof (u32),
298  .format_trace = format_dns46_request_trace,
299  .type = VLIB_NODE_TYPE_INTERNAL,
301  .error_strings = dns46_request_error_strings,
302  .n_next_nodes = DNS46_REQUEST_N_NEXT,
303  .next_nodes = {
304  [DNS46_REQUEST_NEXT_DROP] = "error-drop",
305  [DNS46_REQUEST_NEXT_PUNT] = "error-punt",
306  [DNS46_REQUEST_NEXT_IP_LOOKUP] = "ip4-lookup",
307  },
308 };
309 /* *INDENT-ON* */
310 
311 static uword
313  vlib_node_runtime_t * node, vlib_frame_t * frame)
314 {
315 
316  return dns46_request_inline (vm, node, frame, 1 /* is_ip6 */ );
317 }
318 
319 /* *INDENT-OFF* */
321 {
322  .function = dns6_request_node_fn,
323  .name = "dns6-request",
324  .vector_size = sizeof (u32),
325  .format_trace = format_dns46_request_trace,
326  .type = VLIB_NODE_TYPE_INTERNAL,
328  .error_strings = dns46_request_error_strings,
329  .n_next_nodes = DNS46_REQUEST_N_NEXT,
330  .next_nodes = {
331  [DNS46_REQUEST_NEXT_DROP] = "error-drop",
332  [DNS46_REQUEST_NEXT_PUNT] = "error-punt",
333  [DNS46_REQUEST_NEXT_IP_LOOKUP] = "ip6-lookup",
334  },
335 };
336 /* *INDENT-ON* */
337 
338 /*
339  * fd.io coding-style-patch-verification: ON
340  *
341  * Local Variables:
342  * eval: (c-set-style "gnu")
343  * End:
344  */
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:124
Definition: dns.h:48
#define CLIB_UNUSED(x)
Definition: clib.h:82
ip4_address_t src_address
Definition: ip4_packet.h:170
#define PREDICT_TRUE(x)
Definition: clib.h:112
u8 as_u8[16]
Definition: ip6_packet.h:48
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
u8 data[0]
Packet data.
Definition: buffer.h:181
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:469
vlib_node_registration_t dns46_request_node
Definition: request_node.c:21
ip6_address_t src_address
Definition: ip6_packet.h:385
unsigned char u8
Definition: types.h:56
dns_main_t dns_main
Definition: dns.c:42
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
unsigned int u32
Definition: types.h:88
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:2737
static uword dns4_request_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: request_node.c:285
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
#define DNS_QR
query=0, response=1
Definition: dns_packet.h:50
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
#define PREDICT_FALSE(x)
Definition: clib.h:111
#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:368
vlib_node_registration_t dns6_request_node
(constructor) VLIB_REGISTER_NODE (dns6_request_node)
Definition: request_node.c:320
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:395
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
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:312
static uword dns6_request_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: request_node.c:312
int vnet_dns_resolve_name(dns_main_t *dm, u8 *name, dns_pending_request_t *t, dns_cache_entry_t **retp)
Definition: dns.c:802
vlib_node_registration_t dns4_request_node
(constructor) VLIB_REGISTER_NODE (dns4_request_node)
Definition: request_node.c:293
#define ARRAY_LEN(x)
Definition: clib.h:62
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:465
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:514
u8 * vnet_dns_labels_to_name(u8 *label, u8 *full_text, u8 **parse_from_here)
arc-function for the above.
Definition: dns.c:491
u8 dst_address[16]
Definition: dns.h:36
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:57
struct _vlib_node_registration vlib_node_registration_t
static char * dns46_request_error_strings[]
Definition: request_node.c:44
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
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:2729
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:274
Definition: dns.h:89
static u8 * format_dns46_request_trace(u8 *s, va_list *args)
Definition: request_node.c:31
u16 flags
Copy of main node flags.
Definition: node.h:508
u8 ip_version_and_header_length
Definition: ip4_packet.h:138
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:301
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
#define foreach_dns46_request_error
Definition: dns.h:128
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
int is_enabled
enable / disable flag
Definition: dns.h:102