FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
dhcp4_proxy_node.c
Go to the documentation of this file.
1 /*
2  * proxy_node.c: dhcp proxy node processing
3  *
4  * Copyright (c) 2013 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vlib/vlib.h>
19 #include <vnet/pg/pg.h>
20 #include <vnet/dhcp/dhcp_proxy.h>
21 #include <vnet/dhcp/client.h>
22 #include <vnet/fib/ip4_fib.h>
23 
24 static char * dhcp_proxy_error_strings[] = {
25 #define dhcp_proxy_error(n,s) s,
27 #undef dhcp_proxy_error
28 };
29 
30 #define foreach_dhcp_proxy_to_server_input_next \
31  _ (DROP, "error-drop") \
32  _ (LOOKUP, "ip4-lookup") \
33  _ (SEND_TO_CLIENT, "dhcp-proxy-to-client")
34 
35 typedef enum {
36 #define _(s,n) DHCP_PROXY_TO_SERVER_INPUT_NEXT_##s,
38 #undef _
41 
42 typedef struct {
43  /* 0 => to server, 1 => to client */
44  int which;
50 
51 #define VPP_DHCP_OPTION82_SUB1_SIZE 6
52 #define VPP_DHCP_OPTION82_SUB5_SIZE 6
53 #define VPP_DHCP_OPTION82_VSS_SIZE 12
54 #define VPP_DHCP_OPTION82_SIZE (VPP_DHCP_OPTION82_SUB1_SIZE + \
55  VPP_DHCP_OPTION82_SUB5_SIZE + \
56  VPP_DHCP_OPTION82_VSS_SIZE +3)
57 
60 
61 static u8 *
62 format_dhcp_proxy_trace (u8 * s, va_list * args)
63 {
64  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
65  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
66  dhcp_proxy_trace_t * t = va_arg (*args, dhcp_proxy_trace_t *);
67 
68  if (t->which == 0)
69  s = format (s, "DHCP proxy: sent to server %U\n",
71  else
72  s = format (s, "DHCP proxy: broadcast to client from %U\n",
74 
75  if (t->error != (u32)~0)
76  s = format (s, " error: %s\n", dhcp_proxy_error_strings[t->error]);
77 
78  s = format (s, " original_sw_if_index: %d, sw_if_index: %d\n",
80 
81  return s;
82 }
83 
84 static u8 *
86 {
87  dhcp_header_t * h = va_arg (*args, dhcp_header_t *);
88  u32 max_header_bytes = va_arg (*args, u32);
89  u32 header_bytes;
90 
91  header_bytes = sizeof (h[0]);
92  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
93  return format (s, "dhcp header truncated");
94 
95  s = format (s, "DHCP Proxy");
96 
97  return s;
98 }
99 
100 static uword
102  vlib_node_runtime_t * node,
103  vlib_frame_t * from_frame)
104 {
105  u32 n_left_from, next_index, * from, * to_next;
107  from = vlib_frame_vector_args (from_frame);
108  n_left_from = from_frame->n_vectors;
109  u32 pkts_to_server=0, pkts_to_client=0, pkts_no_server=0;
110  u32 pkts_no_interface_address=0;
111  u32 pkts_too_big=0;
112  ip4_main_t * im = &ip4_main;
113 
114  next_index = node->cached_next_index;
115 
116  while (n_left_from > 0)
117  {
118  u32 n_left_to_next;
119 
120  vlib_get_next_frame (vm, node, next_index,
121  to_next, n_left_to_next);
122 
123  while (n_left_from > 0 && n_left_to_next > 0)
124  {
125  u32 bi0;
126  vlib_buffer_t * b0;
127  udp_header_t * u0;
128  dhcp_header_t * h0;
129  ip4_header_t * ip0;
130  u32 next0;
131  u32 old0, new0;
132  ip_csum_t sum0;
133  u32 error0 = (u32) ~0;
134  u32 sw_if_index = 0;
135  u32 original_sw_if_index = 0;
136  u8 *end = NULL;
137  u32 fib_index;
138  dhcp_proxy_t *proxy;
139  dhcp_server_t *server;
140  u32 rx_sw_if_index;
141  dhcp_option_t *o;
142  u32 len = 0;
144  u8 is_discover = 0;
145 
146  bi0 = from[0];
147  from += 1;
148  n_left_from -= 1;
149 
150  b0 = vlib_get_buffer (vm, bi0);
151 
152  h0 = vlib_buffer_get_current (b0);
153 
154  /*
155  * udp_local hands us the DHCP header, need udp hdr,
156  * ip hdr to relay to server
157  */
158  vlib_buffer_advance (b0, -(sizeof(*u0)));
159  u0 = vlib_buffer_get_current (b0);
160 
161  /* This blows. Return traffic has src_port = 67, dst_port = 67 */
162  if (u0->src_port == clib_net_to_host_u16(UDP_DST_PORT_dhcp_to_server))
163  {
164  vlib_buffer_advance (b0, sizeof(*u0));
165  next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
166  error0 = 0;
167  pkts_to_client++;
168  goto do_enqueue;
169  }
170 
171  rx_sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_RX];
172 
173  fib_index = im->fib_index_by_sw_if_index [rx_sw_if_index];
174  proxy = dhcp_get_proxy(dpm, fib_index, FIB_PROTOCOL_IP4);
175 
176  if (PREDICT_FALSE (NULL == proxy))
177  {
178  error0 = DHCP_PROXY_ERROR_NO_SERVER;
179  next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
180  pkts_no_server++;
181  goto do_trace;
182  }
183 
184  server = &proxy->dhcp_servers[0];
185  vlib_buffer_advance (b0, -(sizeof(*ip0)));
186  ip0 = vlib_buffer_get_current (b0);
187 
188  /* disable UDP checksum */
189  u0->checksum = 0;
190  sum0 = ip0->checksum;
191  old0 = ip0->dst_address.as_u32;
192  new0 = server->dhcp_server.ip4.as_u32;
193  ip0->dst_address.as_u32 = server->dhcp_server.ip4.as_u32;
194  sum0 = ip_csum_update (sum0, old0, new0,
195  ip4_header_t /* structure */,
196  dst_address /* changed member */);
197  ip0->checksum = ip_csum_fold (sum0);
198 
199  sum0 = ip0->checksum;
200  old0 = ip0->src_address.as_u32;
201  new0 = proxy->dhcp_src_address.ip4.as_u32;
202  ip0->src_address.as_u32 = new0;
203  sum0 = ip_csum_update (sum0, old0, new0,
204  ip4_header_t /* structure */,
205  src_address /* changed member */);
206  ip0->checksum = ip_csum_fold (sum0);
207 
208  /* Send to DHCP server via the configured FIB */
209  vnet_buffer(b0)->sw_if_index[VLIB_TX] =
210  server->server_fib_index;
211 
212  h0->gateway_ip_address.as_u32 = proxy->dhcp_src_address.ip4.as_u32;
213  pkts_to_server++;
214 
215  o = (dhcp_option_t *) h0->options;
216 
217  fib_index = im->fib_index_by_sw_if_index
218  [vnet_buffer(b0)->sw_if_index[VLIB_RX]];
219 
220  end = b0->data + b0->current_data + b0->current_length;
221  /* TLVs are not performance-friendly... */
222  while (o->option != 0xFF /* end of options */ && (u8 *)o < end)
223  {
225  {
226  if (DHCP_PACKET_DISCOVER == o->data[0])
227  {
228  is_discover = 1;
229  }
230  }
231  o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
232  }
233 
235  // start write at (option*)o, some packets have padding
236  if (((u8 *)o - (u8 *)b0->data + VPP_DHCP_OPTION82_SIZE) > fl->n_data_bytes)
237  {
238  next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
239  pkts_too_big++;
240  goto do_trace;
241  }
242 
243  if ((o->option == 0xFF) && ((u8 *)o <= end))
244  {
245  vnet_main_t *vnm = vnet_get_main();
246  u16 old_l0, new_l0;
247  ip4_address_t _ia0, * ia0 = &_ia0;
248  dhcp_vss_t *vss;
249  vnet_sw_interface_t *swif;
250  sw_if_index = 0;
251  original_sw_if_index = 0;
252 
253  original_sw_if_index = sw_if_index =
254  vnet_buffer(b0)->sw_if_index[VLIB_RX];
255  swif = vnet_get_sw_interface (vnm, sw_if_index);
257  sw_if_index = swif->unnumbered_sw_if_index;
258 
259  /*
260  * Get the first ip4 address on the [client-side]
261  * RX interface, if not unnumbered. otherwise use
262  * the loopback interface's ip address.
263  */
264  ia0 = ip4_interface_first_address(&ip4_main, sw_if_index, 0);
265 
266  if (ia0 == 0)
267  {
268  error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS;
269  next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
270  pkts_no_interface_address++;
271  goto do_trace;
272  }
273 
274  /* Add option 82 */
275  o->option = 82; /* option 82 */
276  o->length = 12; /* 12 octets to follow */
277  o->data[0] = 1; /* suboption 1, circuit ID (=FIB id) */
278  o->data[1] = 4; /* length of suboption */
279  o->data[2] = (original_sw_if_index >> 24) & 0xFF;
280  o->data[3] = (original_sw_if_index >> 16) & 0xFF;
281  o->data[4] = (original_sw_if_index >> 8) & 0xFF;
282  o->data[5] = (original_sw_if_index >> 0) & 0xFF;
283  o->data[6] = 5; /* suboption 5 (client RX intfc address) */
284  o->data[7] = 4; /* length 4 */
285  o->data[8] = ia0->as_u8[0];
286  o->data[9] = ia0->as_u8[1];
287  o->data[10] = ia0->as_u8[2];
288  o->data[11] = ia0->as_u8[3];
289  o->data[12] = 0xFF;
290 
291  vss = dhcp_get_vss_info (dpm, fib_index, FIB_PROTOCOL_IP4);
292  if (NULL != vss)
293  {
294  u32 opt82_fib_id=0, opt82_oui=0;
295 
296  opt82_oui = vss->oui;
297  opt82_fib_id = vss->fib_id;
298 
299  o->data[12] = 151; /* vss suboption */
300  if (255 == opt82_fib_id) {
301  o->data[13] = 1; /* length */
302  o->data[14] = 255; /* vss option type */
303  o->data[15] = 152; /* vss control suboption */
304  o->data[16] = 0; /* length */
305  /* and a new "end-of-options" option (0xff) */
306  o->data[17] = 0xFF;
307  o->length += 5;
308  } else {
309  o->data[13] = 8; /* length */
310  o->data[14] = 1; /* vss option type */
311  o->data[15] = (opt82_oui >> 16) & 0xff;
312  o->data[16] = (opt82_oui >> 8) & 0xff;
313  o->data[17] = (opt82_oui ) & 0xff;
314  o->data[18] = (opt82_fib_id >> 24) & 0xff;
315  o->data[19] = (opt82_fib_id >> 16) & 0xff;
316  o->data[20] = (opt82_fib_id >> 8) & 0xff;
317  o->data[21] = (opt82_fib_id) & 0xff;
318  o->data[22] = 152; /* vss control suboption */
319  o->data[23] = 0; /* length */
320 
321  /* and a new "end-of-options" option (0xff) */
322  o->data[24] = 0xFF;
323  o->length += 12;
324  }
325  }
326 
327  len = o->length + 3;
328  b0->current_length += len;
329  /* Fix IP header length and checksum */
330  old_l0 = ip0->length;
331  new_l0 = clib_net_to_host_u16 (old_l0);
332  new_l0 += len;
333  new_l0 = clib_host_to_net_u16 (new_l0);
334  ip0->length = new_l0;
335  sum0 = ip0->checksum;
336  sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
337  length /* changed member */);
338  ip0->checksum = ip_csum_fold (sum0);
339 
340  /* Fix UDP length */
341  new_l0 = clib_net_to_host_u16 (u0->length);
342  new_l0 += len;
343  u0->length = clib_host_to_net_u16 (new_l0);
344  } else {
346  (vm, dhcp_proxy_to_server_node.index,
347  DHCP_PROXY_ERROR_OPTION_82_ERROR, 1);
348  }
349 
350  next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
351 
352  /*
353  * If we have multiple servers configured and this is the
354  * client's discover message, then send copies to each of
355  * those servers
356  */
357  if (is_discover && vec_len(proxy->dhcp_servers) > 1)
358  {
359  u32 ii;
360 
361  for (ii = 1; ii < vec_len(proxy->dhcp_servers); ii++)
362  {
363  vlib_buffer_t *c0;
364  u32 ci0;
365 
366  c0 = vlib_buffer_copy(vm, b0);
367  ci0 = vlib_get_buffer_index(vm, c0);
368  server = &proxy->dhcp_servers[ii];
369 
370  ip0 = vlib_buffer_get_current (c0);
371 
372  sum0 = ip0->checksum;
373  old0 = ip0->dst_address.as_u32;
374  new0 = server->dhcp_server.ip4.as_u32;
375  ip0->dst_address.as_u32 = server->dhcp_server.ip4.as_u32;
376  sum0 = ip_csum_update (sum0, old0, new0,
377  ip4_header_t /* structure */,
378  dst_address /* changed member */);
379  ip0->checksum = ip_csum_fold (sum0);
380 
381  to_next[0] = ci0;
382  to_next += 1;
383  n_left_to_next -= 1;
384 
385  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
386  to_next, n_left_to_next,
387  ci0, next0);
388 
390  {
391  dhcp_proxy_trace_t *tr;
392 
393  tr = vlib_add_trace (vm, node, c0, sizeof (*tr));
394  tr->which = 0; /* to server */
395  tr->error = error0;
396  tr->original_sw_if_index = original_sw_if_index;
397  tr->sw_if_index = sw_if_index;
398  if (next0 == DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP)
399  tr->trace_ip4_address.as_u32 = server->dhcp_server.ip4.as_u32;
400  }
401 
402  if (PREDICT_FALSE(0 == n_left_to_next))
403  {
404  vlib_put_next_frame (vm, node, next_index,
405  n_left_to_next);
406  vlib_get_next_frame (vm, node, next_index,
407  to_next, n_left_to_next);
408  }
409  }
410  }
411  do_trace:
413  {
414  dhcp_proxy_trace_t *tr = vlib_add_trace (vm, node,
415  b0, sizeof (*tr));
416  tr->which = 0; /* to server */
417  tr->error = error0;
418  tr->original_sw_if_index = original_sw_if_index;
419  tr->sw_if_index = sw_if_index;
420  if (next0 == DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP)
422  proxy->dhcp_servers[0].dhcp_server.ip4.as_u32;
423  }
424 
425  do_enqueue:
426  to_next[0] = bi0;
427  to_next += 1;
428  n_left_to_next -= 1;
429 
430  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
431  to_next, n_left_to_next,
432  bi0, next0);
433  }
434 
435  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
436  }
437 
439  DHCP_PROXY_ERROR_RELAY_TO_CLIENT,
440  pkts_to_client);
442  DHCP_PROXY_ERROR_RELAY_TO_SERVER,
443  pkts_to_server);
445  DHCP_PROXY_ERROR_NO_SERVER,
446  pkts_no_server);
448  DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS,
449  pkts_no_interface_address);
451  DHCP_PROXY_ERROR_PKT_TOO_BIG,
452  pkts_too_big);
453  return from_frame->n_vectors;
454 }
455 
457  .function = dhcp_proxy_to_server_input,
458  .name = "dhcp-proxy-to-server",
459  /* Takes a vector of packets. */
460  .vector_size = sizeof (u32),
461 
462  .n_errors = DHCP_PROXY_N_ERROR,
463  .error_strings = dhcp_proxy_error_strings,
464 
465  .n_next_nodes = DHCP_PROXY_TO_SERVER_INPUT_N_NEXT,
466  .next_nodes = {
467 #define _(s,n) [DHCP_PROXY_TO_SERVER_INPUT_NEXT_##s] = n,
469 #undef _
470  },
471 
472  .format_buffer = format_dhcp_proxy_header_with_length,
473  .format_trace = format_dhcp_proxy_trace,
474 #if 0
475  .unformat_buffer = unformat_dhcp_proxy_header,
476 #endif
477 };
478 
479 static uword
481  vlib_node_runtime_t * node,
482  vlib_frame_t * from_frame)
483 {
484  u32 n_left_from, * from;
487  vnet_main_t * vnm = vnet_get_main();
488  ip4_main_t * im = &ip4_main;
489 
490  from = vlib_frame_vector_args (from_frame);
491  n_left_from = from_frame->n_vectors;
492 
493  while (n_left_from > 0)
494  {
495  u32 bi0;
496  vlib_buffer_t * b0;
497  udp_header_t * u0;
498  dhcp_header_t * h0;
499  ip4_header_t * ip0 = 0;
500  ip4_address_t * ia0 = 0;
501  u32 old0, new0;
502  ip_csum_t sum0;
504  ethernet_header_t *mac0;
505  vnet_hw_interface_t *hi0;
506  vlib_frame_t *f0;
507  u32 * to_next0;
508  u32 sw_if_index = ~0;
509  vnet_sw_interface_t *si0;
510  u32 error0 = (u32)~0;
511  vnet_sw_interface_t *swif;
512  u32 fib_index;
513  dhcp_proxy_t *proxy;
514  dhcp_server_t *server;
515  u32 original_sw_if_index = (u32) ~0;
516  ip4_address_t relay_addr = {
517  .as_u32 = 0,
518  };
519 
520  bi0 = from[0];
521  from += 1;
522  n_left_from -= 1;
523 
524  b0 = vlib_get_buffer (vm, bi0);
525  h0 = vlib_buffer_get_current (b0);
526 
527  /*
528  * udp_local hands us the DHCP header, need udp hdr,
529  * ip hdr to relay to client
530  */
531  vlib_buffer_advance (b0, -(sizeof(*u0)));
532  u0 = vlib_buffer_get_current (b0);
533 
534  vlib_buffer_advance (b0, -(sizeof(*ip0)));
535  ip0 = vlib_buffer_get_current (b0);
536 
537  /* Consumed by dhcp client code? */
538  if (dhcp_client_for_us (bi0, b0, ip0, u0, h0))
539  continue;
540 
541  if (1 /* dpm->insert_option_82 */)
542  {
543  dhcp_option_t *o = (dhcp_option_t *) h0->options;
545 
546  /* Parse through TLVs looking for option 82.
547  The circuit-ID is the FIB number we need
548  to track down the client-facing interface */
549 
550  while (o->option != 0xFF /* end of options */ &&
551  (u8 *) o < (b0->data + b0->current_data + b0->current_length))
552  {
553  if (o->option == 82)
554  {
555  u32 vss_exist = 0;
556  u32 vss_ctrl = 0;
557  sub = (dhcp_option_t *) &o->data[0];
558  while (sub->option != 0xFF /* end of options */ &&
559  (u8 *) sub < (u8 *)(o + o->length)) {
560  /* If this is one of ours, it will have
561  total length 12, circuit-id suboption type,
562  and the sw_if_index */
563  if (sub->option == 1 && sub->length == 4)
564  {
565  sw_if_index = ((sub->data[0] << 24) |
566  (sub->data[1] << 16) |
567  (sub->data[2] << 8) |
568  (sub->data[3]));
569  }
570  else if (sub->option == 5 && sub->length == 4)
571  {
572  relay_addr.as_u8[0] = sub->data[0];
573  relay_addr.as_u8[1] = sub->data[1];
574  relay_addr.as_u8[2] = sub->data[2];
575  relay_addr.as_u8[3] = sub->data[3];
576  }
577  else if (sub->option == 151 &&
578  sub->length == 7 &&
579  sub->data[0] == 1)
580  vss_exist = 1;
581  else if (sub->option == 152 && sub->length == 0)
582  vss_ctrl = 1;
583  sub = (dhcp_option_t *)
584  (((uword) sub) + (sub->length + 2));
585  }
586  if (vss_ctrl && vss_exist)
588  (vm, dhcp_proxy_to_client_node.index,
589  DHCP_PROXY_ERROR_OPTION_82_VSS_NOT_PROCESSED, 1);
590 
591  }
592  o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
593  }
594  }
595 
596  if (sw_if_index == (u32)~0)
597  {
598  error0 = DHCP_PROXY_ERROR_NO_OPTION_82;
599 
600  drop_packet:
602  error0, 1);
604  to_next0 = vlib_frame_vector_args (f0);
605  to_next0[0] = bi0;
606  f0->n_vectors = 1;
608  goto do_trace;
609  }
610 
611  if (relay_addr.as_u32 == 0)
612  {
613  error0 = DHCP_PROXY_ERROR_BAD_OPTION_82_ADDR;
614  goto drop_packet;
615  }
616 
617  if (sw_if_index >= vec_len (im->fib_index_by_sw_if_index))
618  {
619  error0 = DHCP_PROXY_ERROR_BAD_OPTION_82_ITF;
620  goto drop_packet;
621  }
622 
623  fib_index = im->fib_index_by_sw_if_index [sw_if_index];
624  proxy = dhcp_get_proxy(dpm, fib_index, FIB_PROTOCOL_IP4);
625 
626  if (PREDICT_FALSE (NULL == proxy))
627  {
628  error0 = DHCP_PROXY_ERROR_NO_SERVER;
629  goto drop_packet;
630  }
631 
632  vec_foreach(server, proxy->dhcp_servers)
633  {
634  if (ip0->src_address.as_u32 == server->dhcp_server.ip4.as_u32)
635  {
636  goto server_found;
637  }
638  }
639 
640  error0 = DHCP_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS;
641  goto drop_packet;
642 
643  server_found:
644  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index;
645 
646  swif = vnet_get_sw_interface (vnm, sw_if_index);
647  original_sw_if_index = sw_if_index;
649  sw_if_index = swif->unnumbered_sw_if_index;
650 
651  ia0 = ip4_interface_first_address (&ip4_main, sw_if_index, 0);
652  if (ia0 == 0)
653  {
654  error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS;
655  goto drop_packet;
656  }
657 
658  if (relay_addr.as_u32 != ia0->as_u32)
659  {
660  error0 = DHCP_PROXY_ERROR_BAD_YIADDR;
661  goto drop_packet;
662  }
663 
664  u0->checksum = 0;
665  u0->dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcp_to_client);
666  sum0 = ip0->checksum;
667  old0 = ip0->dst_address.as_u32;
668  new0 = 0xFFFFFFFF;
669  ip0->dst_address.as_u32 = new0;
670  sum0 = ip_csum_update (sum0, old0, new0,
671  ip4_header_t /* structure */,
672  dst_address /* offset of changed member */);
673  ip0->checksum = ip_csum_fold (sum0);
674 
675  sum0 = ip0->checksum;
676  old0 = ip0->src_address.as_u32;
677  new0 = ia0->as_u32;
678  ip0->src_address.as_u32 = new0;
679  sum0 = ip_csum_update (sum0, old0, new0,
680  ip4_header_t /* structure */,
681  src_address /* offset of changed member */);
682  ip0->checksum = ip_csum_fold (sum0);
683 
684  vlib_buffer_advance (b0, -(sizeof(ethernet_header_t)));
685  si0 = vnet_get_sw_interface (vnm, original_sw_if_index);
686  if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
687  vlib_buffer_advance (b0, -4 /* space for VLAN tag */);
688 
689  mac0 = vlib_buffer_get_current (b0);
690 
691  hi0 = vnet_get_sup_hw_interface (vnm, original_sw_if_index);
692  ei0 = pool_elt_at_index (em->interfaces, hi0->hw_instance);
693  clib_memcpy (mac0->src_address, ei0->address, sizeof (ei0->address));
694  memset (mac0->dst_address, 0xff, sizeof (mac0->dst_address));
695  mac0->type = (si0->type == VNET_SW_INTERFACE_TYPE_SUB) ?
696  clib_net_to_host_u16(0x8100) : clib_net_to_host_u16 (0x0800);
697 
698  if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
699  {
700  u32 * vlan_tag = (u32 *)(mac0+1);
701  u32 tmp;
702  tmp = (si0->sub.id << 16) | 0x0800;
703  *vlan_tag = clib_host_to_net_u32 (tmp);
704  }
705 
706  /* $$$ This needs to be rewritten, for sure */
708  to_next0 = vlib_frame_vector_args (f0);
709  to_next0[0] = bi0;
710  f0->n_vectors = 1;
712 
713  do_trace:
715  {
716  dhcp_proxy_trace_t *tr = vlib_add_trace (vm, node,
717  b0, sizeof (*tr));
718  tr->which = 1; /* to client */
719  tr->trace_ip4_address.as_u32 = ia0 ? ia0->as_u32 : 0;
720  tr->error = error0;
721  tr->original_sw_if_index = original_sw_if_index;
722  tr->sw_if_index = sw_if_index;
723  }
724  }
725  return from_frame->n_vectors;
726 }
727 
729  .function = dhcp_proxy_to_client_input,
730  .name = "dhcp-proxy-to-client",
731  /* Takes a vector of packets. */
732  .vector_size = sizeof (u32),
733 
734  .n_errors = DHCP_PROXY_N_ERROR,
735  .error_strings = dhcp_proxy_error_strings,
736  .format_buffer = format_dhcp_proxy_header_with_length,
737  .format_trace = format_dhcp_proxy_trace,
738 #if 0
739  .unformat_buffer = unformat_dhcp_proxy_header,
740 #endif
741 };
742 
743 static clib_error_t *
745 {
747  vlib_node_t * error_drop_node;
748 
749  error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
750  dm->error_drop_node_index = error_drop_node->index;
751 
752  udp_register_dst_port (vm, UDP_DST_PORT_dhcp_to_client,
753  dhcp_proxy_to_client_node.index, 1 /* is_ip4 */);
754 
755  udp_register_dst_port (vm, UDP_DST_PORT_dhcp_to_server,
756  dhcp_proxy_to_server_node.index, 1 /* is_ip4 */);
757 
758  return 0;
759 }
760 
761 
763 
764 int
765 dhcp4_proxy_set_server (ip46_address_t *addr,
766  ip46_address_t *src_addr,
767  u32 rx_table_id,
768  u32 server_table_id,
769  int is_del)
770 {
771  u32 rx_fib_index = 0;
772  int rc = 0;
773 
774  const fib_prefix_t all_1s =
775  {
776  .fp_len = 32,
777  .fp_addr.ip4.as_u32 = 0xffffffff,
778  .fp_proto = FIB_PROTOCOL_IP4,
779  };
780 
781  if (ip46_address_is_zero(addr))
782  return VNET_API_ERROR_INVALID_DST_ADDRESS;
783 
784  if (ip46_address_is_zero(src_addr))
785  return VNET_API_ERROR_INVALID_SRC_ADDRESS;
786 
788  rx_table_id);
789 
790  if (is_del)
791  {
792  if (dhcp_proxy_server_del (FIB_PROTOCOL_IP4, rx_fib_index,
793  addr, server_table_id))
794  {
795  fib_table_entry_special_remove(rx_fib_index,
796  &all_1s,
798  fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4);
799  }
800  }
801  else
802  {
804  addr, src_addr,
805  rx_fib_index, server_table_id))
806  {
807  fib_table_entry_special_add(rx_fib_index,
808  &all_1s,
811  fib_table_lock (rx_fib_index, FIB_PROTOCOL_IP4);
812  }
813  }
814  fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4);
815 
816  return (rc);
817 }
818 
819 static clib_error_t *
821  unformat_input_t * input,
822  vlib_cli_command_t * cmd)
823 {
824  ip46_address_t server_addr, src_addr;
825  u32 server_table_id = 0, rx_table_id = 0;
826  int is_del = 0;
827  int set_src = 0, set_server = 0;
828 
829  memset(&server_addr, 0, sizeof(server_addr));
830  memset(&src_addr, 0, sizeof(src_addr));
831 
833  {
834  if (unformat (input, "server %U",
835  unformat_ip4_address, &server_addr.ip4))
836  set_server = 1;
837  else if (unformat (input, "server-fib-id %d", &server_table_id))
838  ;
839  else if (unformat (input, "rx-fib-id %d", &rx_table_id))
840  ;
841  else if (unformat(input, "src-address %U",
842  unformat_ip4_address, &src_addr.ip4))
843  set_src = 1;
844  else if (unformat (input, "delete") ||
845  unformat (input, "del"))
846  is_del = 1;
847  else
848  break;
849  }
850 
851  if (is_del || (set_server && set_src))
852  {
853  int rv;
854 
855  rv = dhcp4_proxy_set_server (&server_addr, &src_addr, rx_table_id,
856  server_table_id, is_del);
857  switch (rv)
858  {
859  case 0:
860  return 0;
861 
862  case VNET_API_ERROR_INVALID_DST_ADDRESS:
863  return clib_error_return (0, "Invalid server address");
864 
865  case VNET_API_ERROR_INVALID_SRC_ADDRESS:
866  return clib_error_return (0, "Invalid src address");
867 
868  case VNET_API_ERROR_NO_SUCH_ENTRY:
869  return clib_error_return
870  (0, "Fib id %d: no per-fib DHCP server configured", rx_table_id);
871 
872  default:
873  return clib_error_return (0, "BUG: rv %d", rv);
874  }
875  }
876  else
877  return clib_error_return (0, "parse error`%U'",
878  format_unformat_error, input);
879 }
880 
881 VLIB_CLI_COMMAND (dhcp_proxy_set_command, static) = {
882  .path = "set dhcp proxy",
883  .short_help = "set dhcp proxy [del] server <ip-addr> src-address <ip-addr> [server-fib-id <n>] [rx-fib-id <n>]",
884  .function = dhcp4_proxy_set_command_fn,
885 };
886 
887 static u8 *
888 format_dhcp4_proxy_server (u8 * s, va_list * args)
889 {
890  dhcp_proxy_t *proxy = va_arg (*args, dhcp_proxy_t *);
891  ip4_fib_t * rx_fib, * server_fib;
892  dhcp_server_t *server;
893 
894  if (proxy == 0)
895  {
896  s = format (s, "%=14s%=16s%s", "RX FIB", "Src Address",
897  "Servers FIB,Address");
898  return s;
899  }
900 
901  rx_fib = ip4_fib_get(proxy->rx_fib_index);
902 
903  s = format (s, "%=14u%=16U",
904  rx_fib->table_id,
906 
907  vec_foreach(server, proxy->dhcp_servers)
908  {
909  server_fib = ip4_fib_get(server->server_fib_index);
910  s = format (s, "%u,%U ",
911  server_fib->table_id,
913  }
914  return s;
915 }
916 
917 static int
919  void *ctx)
920 {
921  vlib_main_t * vm = ctx;
922 
923  vlib_cli_output (vm, "%U", format_dhcp4_proxy_server, server);
924 
925  return (1);
926 }
927 
928 static clib_error_t *
930  unformat_input_t * input,
931  vlib_cli_command_t * cmd)
932 {
933  vlib_cli_output (vm, "%U", format_dhcp4_proxy_server, NULL /* header line */);
934 
936 
937  return (NULL);
938 }
939 
940 VLIB_CLI_COMMAND (dhcp_proxy_show_command, static) = {
941  .path = "show dhcp proxy",
942  .short_help = "Display dhcp proxy server info",
943  .function = dhcp4_proxy_show_command_fn,
944 };
945 
946 static clib_error_t *
948  unformat_input_t * input,
949  vlib_cli_command_t * cmd)
950 {
951  int is_del = 0, got_new_vpn_id=0;
952  u32 oui=0, fib_id=0, tbl_id=~0;
953 
955  {
956 
957  if (unformat(input, "delete") || unformat(input, "del"))
958  is_del = 1;
959  else if (unformat (input, "oui %d", &oui))
960  got_new_vpn_id = 1;
961  else if (unformat (input, "vpn-id %d", &fib_id))
962  got_new_vpn_id = 1;
963  else if (unformat (input, "table %d", &tbl_id))
964  got_new_vpn_id = 1;
965  else
966  break;
967  }
968  if (tbl_id == ~0)
969  return clib_error_return (0, "no table ID specified.");
970 
971  if (is_del || got_new_vpn_id)
972  {
973  int rv;
974  rv = dhcp_proxy_set_vss(FIB_PROTOCOL_IP4, tbl_id, oui, fib_id, is_del);
975  switch (rv)
976  {
977  case 0:
978  return 0;
979 
980  case VNET_API_ERROR_NO_SUCH_FIB:
981  return clib_error_return (0, "option 82 vss(oui:%d, vpn-id:%d) not found in table %d",
982  oui, fib_id, tbl_id);
983 
984  case VNET_API_ERROR_NO_SUCH_ENTRY:
985  return clib_error_return (0, "option 82 vss for table %d not found in in pool.",
986  tbl_id);
987  default:
988  return clib_error_return (0, "BUG: rv %d", rv);
989  }
990  }
991  else
992  return clib_error_return (0, "parse error`%U'",
993  format_unformat_error, input);
994 }
995 
996 VLIB_CLI_COMMAND (dhcp_proxy_vss_command,static) = {
997  .path = "set dhcp option-82 vss",
998  .short_help = "set dhcp option-82 vss [del] table <table id> oui <oui> vpn-id <vpn-id>",
999  .function = dhcp_option_82_vss_fn,
1000 };
1001 
1002 static clib_error_t *
1004  unformat_input_t * input,
1005  vlib_cli_command_t * cmd)
1006 
1007 {
1009 
1010  return (NULL);
1011 }
1012 
1013 VLIB_CLI_COMMAND (dhcp_proxy_vss_show_command, static) = {
1014  .path = "show dhcp vss",
1015  .short_help = "show dhcp VSS",
1016  .function = dhcp_vss_show_command_fn,
1017 };
1018 
1019 static clib_error_t *
1021  unformat_input_t * input,
1022  vlib_cli_command_t * cmd)
1023 
1024 {
1025  vnet_main_t *vnm = vnet_get_main();
1026  u32 sw_if_index0=0, sw_if_index;
1027  vnet_sw_interface_t *swif;
1028  ip4_address_t *ia0;
1029 
1030  while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
1031  {
1032 
1033  if (unformat(input, "%U",
1034  unformat_vnet_sw_interface, vnm, &sw_if_index0))
1035  {
1036  swif = vnet_get_sw_interface (vnm, sw_if_index0);
1037  sw_if_index = (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED) ?
1038  swif->unnumbered_sw_if_index : sw_if_index0;
1039  ia0 = ip4_interface_first_address(&ip4_main, sw_if_index, 0);
1040  if (ia0)
1041  {
1042  vlib_cli_output (vm, "%=20s%=20s", "interface",
1043  "source IP address");
1044 
1045  vlib_cli_output (vm, "%=20U%=20U",
1047  vnm, sw_if_index0,
1048  format_ip4_address, ia0);
1049  }
1050  else
1051  vlib_cli_output (vm, "%=34s %=20U",
1052  "No IPv4 address configured on",
1054  vnm, sw_if_index);
1055  }
1056  else
1057  break;
1058  }
1059 
1060  return 0;
1061 }
1062 
1063 VLIB_CLI_COMMAND (dhcp_proxy_address_show_command,static) = {
1064  .path = "show dhcp option-82-address interface",
1065  .short_help = "show dhcp option-82-address interface <interface>",
1067 };
static vlib_node_registration_t dhcp_proxy_to_client_node
(constructor) VLIB_REGISTER_NODE (dhcp_proxy_to_client_node)
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:567
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
static dhcp_vss_t * dhcp_get_vss_info(dhcp_proxy_main_t *dm, u32 rx_fib_index, fib_protocol_t proto)
Get the VSS data for the FIB index.
Definition: dhcp_proxy.h:237
#define CLIB_UNUSED(x)
Definition: clib.h:79
ip4_address_t src_address
Definition: ip4_packet.h:164
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
ethernet_main_t * ethernet_get_main(vlib_main_t *vm)
Definition: init.c:116
void dhcp_vss_walk(fib_protocol_t proto, dhcp_vss_walk_fn_t fn, void *ctx)
Walk/Visit each DHCP proxy VSS.
Definition: dhcp_proxy.c:92
void fib_table_lock(u32 fib_index, fib_protocol_t proto)
Release a reference counting lock on the table.
Definition: fib_table.c:1159
dhcp_server_t * dhcp_servers
The set of DHCP servers to which messages are relayed.
Definition: dhcp_proxy.h:90
static uword dhcp_proxy_to_client_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
Definition: buffer.h:99
void dhcp_proxy_walk(fib_protocol_t proto, dhcp_proxy_walk_fn_t fn, void *ctx)
Walk/Visit each DHCP proxy server.
Definition: dhcp_proxy.c:70
static clib_error_t * dhcp4_proxy_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define VPP_DHCP_OPTION82_SIZE
#define NULL
Definition: clib.h:55
u32 index
Definition: node.h:238
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
Definition: ip4_forward.c:684
dhcp_proxy_main_t dhcp_proxy_main
Shard 4/6 instance of DHCP main.
Definition: dhcp_proxy.c:25
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:459
u8 src_address[6]
Definition: packet.h:54
int dhcp_vss_show_walk(dhcp_vss_t *vss, u32 rx_table_id, void *ctx)
Show (on CLI) a VSS config during a show walk.
Definition: dhcp_proxy.c:274
static uword dhcp_proxy_to_server_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
ip46_address_t dhcp_src_address
The source address to use in relayed messaes.
Definition: dhcp_proxy.h:105
add_epi add_epi sub
Definition: vector_sse2.h:283
The Virtual Sub-net Selection information for a given RX FIB.
Definition: dhcp_proxy.h:49
int dhcp_client_for_us(u32 bi, vlib_buffer_t *b, ip4_header_t *ip, udp_header_t *udp, dhcp_header_t *dhcp)
Definition: client.c:66
struct _vlib_node_registration vlib_node_registration_t
u32 rx_fib_index
The FIB index (not the external Table-ID) in which the client is resides.
Definition: dhcp_proxy.h:111
format_function_t format_ip46_address
Definition: format.h:61
uword ip_csum_t
Definition: ip_packet.h:90
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:99
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
unformat_function_t unformat_vnet_sw_interface
u32 oui
?? RFC doesn&#39;t say
Definition: dhcp_proxy.h:53
format_function_t format_vnet_sw_if_index_name
static vlib_buffer_t * vlib_buffer_copy(vlib_main_t *vm, vlib_buffer_t *b)
Definition: buffer_funcs.h:475
format_function_t format_ip4_address
Definition: format.h:79
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:67
unformat_function_t unformat_ip4_address
Definition: format.h:76
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
u32 table_id
Definition: ip4_fib.h:51
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:390
ip4_address_t dst_address
Definition: ip4_packet.h:164
u8 dst_address[6]
Definition: packet.h:53
static vlib_node_registration_t dhcp_proxy_to_server_node
(constructor) VLIB_REGISTER_NODE (dhcp_proxy_to_server_node)
Aggregrate type for a prefix.
Definition: fib_types.h:160
static clib_error_t * dhcp4_proxy_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static dhcp_proxy_t * dhcp_get_proxy(dhcp_proxy_main_t *dm, u32 rx_fib_index, fib_protocol_t proto)
Get the DHCP proxy server data for the FIB index.
Definition: dhcp_proxy.h:258
#define clib_error_return(e, args...)
Definition: error.h:99
int dhcp_proxy_server_add(fib_protocol_t proto, ip46_address_t *addr, ip46_address_t *src_address, u32 rx_fib_index, u32 server_table_id)
Add a new DHCP proxy server configuration.
Definition: dhcp_proxy.c:192
u16 fp_len
The mask length.
Definition: fib_types.h:164
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:70
u32 server_fib_index
The FIB index (not the external Table-ID) in which the server is reachable.
Definition: dhcp_proxy.h:75
static u8 * format_dhcp4_proxy_server(u8 *s, va_list *args)
Definition: fib_entry.h:238
void fib_table_unlock(u32 fib_index, fib_protocol_t proto)
Take a reference counting lock on the table.
Definition: fib_table.c:1145
Collection of global DHCP proxy data.
Definition: dhcp_proxy.h:119
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
vnet_sub_interface_t sub
Definition: interface.h:596
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:71
struct _unformat_input_t unformat_input_t
dhcp_proxy_to_server_input_next_t
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
#define PREDICT_FALSE(x)
Definition: clib.h:97
static char * dhcp_proxy_error_strings[]
#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:216
#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:366
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1131
u32 fib_id
VPN-ID.
Definition: dhcp_proxy.h:57
static clib_error_t * dhcp4_proxy_init(vlib_main_t *vm)
fib_node_index_t fib_table_entry_special_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags)
Add a &#39;special&#39; entry to the FIB.
Definition: fib_table.c:371
The IPv4 FIB.
Definition: ip4_fib.h:39
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u16 n_vectors
Definition: node.h:345
static clib_error_t * dhcp_option_82_address_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static ip4_fib_t * ip4_fib_get(u32 index)
Get the FIB at the given index.
Definition: ip4_fib.h:105
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
#define clib_memcpy(a, b, c)
Definition: string.h:69
A representation of a single DHCP Server within a given VRF config.
Definition: dhcp_proxy.h:63
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
int dhcp4_proxy_set_server(ip46_address_t *addr, ip46_address_t *src_addr, u32 rx_table_id, u32 server_table_id, int is_del)
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:460
ip46_address_t dhcp_server
The address of the DHCP server to which to relay the client&#39;s messages.
Definition: dhcp_proxy.h:69
static u8 * format_dhcp_proxy_trace(u8 *s, va_list *args)
unsigned int u32
Definition: types.h:88
#define foreach_dhcp_proxy_to_server_input_next
ip4_address_t gateway_ip_address
Definition: dhcp4_packet.h:34
static clib_error_t * dhcp_option_82_vss_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
IPv4 main type.
Definition: ip4.h:83
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1041
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:201
static clib_error_t * dhcp_vss_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
ip4_address_t trace_ip4_address
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
int dhcp_proxy_set_vss(fib_protocol_t proto, u32 tbl_id, u32 oui, u32 fib_id, int is_del)
Configure/set a new VSS info.
Definition: dhcp_proxy.c:288
A DHCP proxy represenation fpr per-client VRF config.
Definition: dhcp_proxy.h:81
Definition: defs.h:47
int dhcp_proxy_server_del(fib_protocol_t proto, u32 rx_fib_index, ip46_address_t *addr, u32 server_table_id)
Delete a DHCP proxy config.
Definition: dhcp_proxy.c:152
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
DHCP.
Definition: fib_entry.h:82
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:269
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:139
static u8 * format_dhcp_proxy_header_with_length(u8 *s, va_list *args)
#define vnet_buffer(b)
Definition: buffer.h:304
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:144
vnet_sw_interface_type_t type
Definition: interface.h:555
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1168
u8 data[0]
Packet data.
Definition: buffer.h:152
#define vec_foreach(var, vec)
Vector iterator.
vhost_vring_addr_t addr
Definition: vhost-user.h:82
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:488
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:385
ethernet_interface_t * interfaces
Definition: ethernet.h:243
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
#define ip46_address_is_zero(ip46)
Definition: ip6_packet.h:81
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
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
static int dhcp4_proxy_show_walk(dhcp_proxy_t *server, void *ctx)
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:145
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
Definition: defs.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169