FD.io VPP  v21.06-3-gbb25fbf28
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 <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
61  int is_ip6)
62 {
63  u32 n_left_from, *from, *to_next;
65  dns_main_t *dm = &dns_main;
66 
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 */
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)
239  clib_memcpy_fast (t0->dst_address, ip60->src_address.as_u8,
240  sizeof (ip6_address_t));
241  else
243  sizeof (ip4_address_t));
244 
245  vnet_dns_resolve_name (vm, dm, name0, t0, &ep0);
246 
247  if (ep0)
248  {
249  if (is_ip6)
250  vnet_send_dns6_reply (vm, dm, t0, ep0, b0);
251  else
252  vnet_send_dns4_reply (vm, 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 
263  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
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 */
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
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,
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
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,
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  */
vlib.h
format_dns46_request_trace
static u8 * format_dns46_request_trace(u8 *s, va_list *args)
Definition: request_node.c:31
udp_header_t::src_port
u16 src_port
Definition: udp_packet.h:48
vlib_prefetch_buffer_header
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
dns_cache_entry_t
Definition: dns.h:55
dns_pending_request_t::id
u16 id
Definition: dns.h:36
dns_main_t::is_enabled
int is_enabled
enable / disable flag
Definition: dns.h:110
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
DNS_QR
#define DNS_QR
query=0, response=1
Definition: dns_packet.h:50
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
u16
unsigned short u16
Definition: types.h:57
dns_main
dns_main_t dns_main
Definition: dns.c:42
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
dns_pending_request_t::dst_address
u8 dst_address[16]
Definition: dns.h:38
vlib_frame_t
Definition: node.h:372
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
dns46_request_trace_t::disposition
u32 disposition
Definition: request_node.c:26
dns4_request_node_fn
static uword dns4_request_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: request_node.c:285
DNS46_REQUEST_N_NEXT
@ DNS46_REQUEST_N_NEXT
Definition: request_node.c:55
dns46_request_node
vlib_node_registration_t dns46_request_node
Definition: request_node.c:21
vnet_dns_resolve_name
int vnet_dns_resolve_name(vlib_main_t *vm, dns_main_t *dm, u8 *name, dns_pending_request_t *t, dns_cache_entry_t **retp)
Definition: dns.c:810
dns_pending_request_t::name
u8 * name
Definition: dns.h:39
foreach_dns46_request_error
#define foreach_dns46_request_error
Definition: dns.h:141
DNS46_REQUEST_NEXT_PUNT
@ DNS46_REQUEST_NEXT_PUNT
Definition: request_node.c:54
CLIB_PREFETCH
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
vlib_buffer_t::error
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
dns_pending_request_t::client_index
u32 client_index
Definition: dns.h:32
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
vnet_send_dns6_reply
void vnet_send_dns6_reply(vlib_main_t *vm, dns_main_t *dm, dns_pending_request_t *pr, dns_cache_entry_t *ep, vlib_buffer_t *b0)
Definition: dns.c:2738
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
dns46_request_inline
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
dns_pending_request_t::dst_port
u16 dst_port
Definition: dns.h:35
vnet_send_dns4_reply
void vnet_send_dns4_reply(vlib_main_t *vm, dns_main_t *dm, dns_pending_request_t *pr, dns_cache_entry_t *ep, vlib_buffer_t *b0)
Definition: dns.c:2747
uword
u64 uword
Definition: types.h:112
dns46_request_trace_t::pool_index
u32 pool_index
Definition: request_node.c:25
ethernet_header_t
Definition: packet.h:52
dns6_request_node
vlib_node_registration_t dns6_request_node
(constructor) VLIB_REGISTER_NODE (dns6_request_node)
Definition: request_node.c:320
dns46_request_next_t
dns46_request_next_t
Definition: request_node.c:50
ip4_address_t
Definition: ip4_packet.h:50
dns_pending_request_t::request_type
u32 request_type
Definition: dns.h:31
DNS46_REQUEST_NEXT_IP_LOOKUP
@ DNS46_REQUEST_NEXT_IP_LOOKUP
Definition: request_node.c:53
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
DNS_PEER_PENDING_IP_TO_NAME
@ DNS_PEER_PENDING_IP_TO_NAME
Definition: dns.h:52
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
dns46_request_trace_t
Definition: request_node.c:23
is_ip6
bool is_ip6
Definition: ip.api:43
ip4_address_t::as_u8
u8 as_u8[4]
Definition: ip4_packet.h:55
vlib_validate_buffer_enqueue_x1
#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:224
ip4_header_t::src_address
ip4_address_t src_address
Definition: ip4_packet.h:125
dns6_request_node_fn
static uword dns6_request_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: request_node.c:312
format
description fragment has unexpected format
Definition: map.api:433
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
u32
unsigned int u32
Definition: types.h:88
dns4_request_node
vlib_node_registration_t dns4_request_node
(constructor) VLIB_REGISTER_NODE (dns4_request_node)
Definition: request_node.c:293
ip6_header_t
Definition: ip6_packet.h:294
ip6_header_t::src_address
ip6_address_t src_address
Definition: ip6_packet.h:310
dns_pending_request_t::is_ip6
u8 is_ip6
Definition: dns.h:34
vlib_main_t
Definition: main.h:102
ip4_header_t::ip_version_and_header_length
u8 ip_version_and_header_length
Definition: ip4_packet.h:93
vlib_node_t
Definition: node.h:247
vlib_add_trace
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
DNS_PEER_PENDING_NAME_TO_IP
@ DNS_PEER_PENDING_NAME_TO_IP
Definition: dns.h:51
u8
unsigned char u8
Definition: types.h:56
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
vnet_dns_labels_to_name
u8 * vnet_dns_labels_to_name(u8 *label, u8 *full_text, u8 **parse_from_here)
arc-function for the above.
Definition: dns.c:495
vlib_buffer_t::data
u8 data[]
Packet data.
Definition: buffer.h:204
vlib_validate_buffer_enqueue_x2
#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
dns_pending_request_t
Definition: dns.h:29
vnet.h
dns.h
vlib_node_runtime_t
Definition: node.h:454
from
from
Definition: nat44_ei_hairpinning.c:415
PREDICT_TRUE
#define PREDICT_TRUE(x)
Definition: clib.h:125
dns_main_t
Definition: dns.h:96
vlib_get_next_frame
#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:395
DNS46_REQUEST_NEXT_DROP
@ DNS46_REQUEST_NEXT_DROP
Definition: request_node.c:52
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
dns46_request_error_strings
static char * dns46_request_error_strings[]
Definition: request_node.c:44
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169