FD.io VPP  v19.08-27-gf4dcae4
Vector Packet Processing
client.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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 #include <vlib/vlib.h>
16 #include <vlibmemory/api.h>
17 #include <vnet/dhcp/client.h>
18 #include <vnet/dhcp/dhcp_proxy.h>
19 #include <vnet/fib/fib_table.h>
20 #include <vnet/qos/qos_types.h>
21 
23 static u8 *format_dhcp_client_state (u8 * s, va_list * va);
25 
26 #define foreach_dhcp_sent_packet_stat \
27 _(DISCOVER, "DHCP discover packets sent") \
28 _(OFFER, "DHCP offer packets sent") \
29 _(REQUEST, "DHCP request packets sent") \
30 _(ACK, "DHCP ack packets sent")
31 
32 #define foreach_dhcp_error_counter \
33 _(NOT_FOR_US, "DHCP packets for other hosts, dropped") \
34 _(NAK, "DHCP nak packets received") \
35 _(NON_OFFER_DISCOVER, "DHCP non-offer packets in discover state") \
36 _(ODDBALL, "DHCP non-ack, non-offer packets received") \
37 _(BOUND, "DHCP bind success")
38 
39 typedef enum
40 {
41 #define _(sym,str) DHCP_STAT_##sym,
43 #undef _
47 
49 #define _(sym,string) string,
51 #undef _
52  "DHCP unknown packets sent",
53 };
54 
55 static void
57 {
58  /*
59  * Install any/all info gleaned from dhcp, right here
60  */
62  (void *) &c->leased_address,
63  c->subnet_mask_width, 0 /*is_del */ );
64 }
65 
66 static void
68 {
69  /*
70  * Remove any/all info gleaned from dhcp, right here. Caller(s)
71  * have not wiped out the info yet.
72  */
73 
75  (void *) &c->leased_address,
76  c->subnet_mask_width, 1 /*is_del */ );
77 }
78 
79 static void
81 {
83  ASSERT (vlib_get_thread_index () == 0);
85  EVENT_DHCP_CLIENT_WAKEUP, *client_index);
86 }
87 
88 static void
90 {
92 
93  /* disable the feature */
94  vnet_feature_enable_disable ("ip4-unicast",
95  "ip4-dhcp-client-detect",
96  c->sw_if_index, 0 /* disable */ , 0, 0);
98 
99  /* if renewing the lease, the address and route have already been added */
100  if (c->state == DHCP_BOUND)
101  return;
102 
103  /* add the address to the interface */
105 
106  /*
107  * Configure default IP route:
108  */
109  if (c->router_address.as_u32)
110  {
111  fib_prefix_t all_0s = {
112  .fp_len = 0,
113  .fp_addr.ip4.as_u32 = 0x0,
114  .fp_proto = FIB_PROTOCOL_IP4,
115  };
116  ip46_address_t nh = {
117  .ip4 = c->router_address,
118  };
119 
120  /* *INDENT-OFF* */
124  c->sw_if_index),
125  &all_0s,
129  &nh, c->sw_if_index,
130  ~0, 1, NULL, // no label stack
132  /* *INDENT-ON* */
133  }
134  if (c->dhcp_server.as_u32)
135  {
136  ip46_address_t dst = {
137  .ip4 = c->dhcp_server,
138  };
140  VNET_LINK_IP4, &dst, c->sw_if_index);
141  }
142 
143  /*
144  * Call the user's event callback to report DHCP information
145  */
146  if (c->event_callback)
147  c->event_callback (c->client_index, c);
148 }
149 
150 /*
151  * dhcp_client_for_us - server-to-client callback.
152  * Called from proxy_node.c:dhcp_proxy_to_client_input().
153  * This function first decides that the packet in question is
154  * actually for the dhcp client code in case we're also acting as
155  * a dhcp proxy. Ay caramba, what a folly!
156  */
157 int
159  ip4_header_t * ip,
160  udp_header_t * udp, dhcp_header_t * dhcp)
161 {
163  vlib_main_t *vm = dcm->vlib_main;
164  dhcp_client_t *c;
165  uword *p;
166  f64 now = vlib_time_now (dcm->vlib_main);
167  u8 dhcp_message_type = 0;
168  dhcp_option_t *o;
169 
170  /*
171  * Doing dhcp client on this interface?
172  * Presumably we will always receive dhcp clnt for-us pkts on
173  * the interface that's asking for an address.
174  */
177  if (p == 0)
178  return 0; /* no */
179 
180  c = pool_elt_at_index (dcm->clients, p[0]);
181 
182  /* Mixing dhcp relay and dhcp proxy? DGMS... */
183  if (c->state == DHCP_BOUND && c->retry_count == 0)
184  return 0;
185 
186  /* Packet not for us? Turf it... */
187  if (memcmp (dhcp->client_hardware_address, c->client_hardware_address,
188  sizeof (c->client_hardware_address)))
189  {
191  DHCP_STAT_NOT_FOR_US, 1);
192  return 0;
193  }
194 
195  /* parse through the packet, learn what we can */
196  if (dhcp->your_ip_address.as_u32)
198 
200 
201  o = (dhcp_option_t *) dhcp->options;
202 
203  while (o->option != 0xFF /* end of options */ &&
204  (u8 *) o < (b->data + b->current_data + b->current_length))
205  {
206  switch (o->option)
207  {
208  case 53: /* dhcp message type */
209  dhcp_message_type = o->data[0];
210  break;
211 
212  case 51: /* lease time */
213  {
214  u32 lease_time_in_seconds =
215  clib_host_to_net_u32 (o->data_as_u32[0]);
216  // for debug: lease_time_in_seconds = 20; /*$$$$*/
217  c->lease_expires = now + (f64) lease_time_in_seconds;
218  c->lease_lifetime = lease_time_in_seconds;
219  /* Set a sensible default, in case we don't get opt 58 */
220  c->lease_renewal_interval = lease_time_in_seconds / 2;
221  }
222  break;
223 
224  case 58: /* lease renew time in seconds */
225  {
226  u32 lease_renew_time_in_seconds =
227  clib_host_to_net_u32 (o->data_as_u32[0]);
228  c->lease_renewal_interval = lease_renew_time_in_seconds;
229  }
230  break;
231 
232  case 54: /* dhcp server address */
233  c->dhcp_server.as_u32 = o->data_as_u32[0];
234  break;
235 
236  case 1: /* subnet mask */
237  {
238  u32 subnet_mask = clib_host_to_net_u32 (o->data_as_u32[0]);
239  c->subnet_mask_width = count_set_bits (subnet_mask);
240  }
241  break;
242  case 3: /* router address */
243  {
244  u32 router_address = o->data_as_u32[0];
245  c->router_address.as_u32 = router_address;
246  }
247  break;
248  case 6: /* domain server address */
249  {
252  o->length / sizeof (ip4_address_t) - 1);
254  }
255  break;
256  case 12: /* hostname */
257  {
258  /* Replace the existing hostname if necessary */
259  vec_free (c->hostname);
260  vec_validate (c->hostname, o->length - 1);
261  clib_memcpy (c->hostname, o->data, o->length);
262  }
263  break;
264 
265  /* $$$$ Your message in this space, parse more options */
266  default:
267  break;
268  }
269 
270  o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
271  }
272 
273  switch (c->state)
274  {
275  case DHCP_DISCOVER:
276  if (dhcp_message_type != DHCP_PACKET_OFFER)
277  {
279  DHCP_STAT_NON_OFFER_DISCOVER, 1);
280  c->next_transmit = now + 5.0;
281  break;
282  }
283 
284  /* Received an offer, go send a request */
285  c->state = DHCP_REQUEST;
286  c->retry_count = 0;
287  c->next_transmit = 0; /* send right now... */
288  /* Poke the client process, which will send the request */
289  uword client_id = c - dcm->clients;
291  (u8 *) & client_id, sizeof (uword));
292  break;
293 
294  case DHCP_BOUND:
295  case DHCP_REQUEST:
296  if (dhcp_message_type == DHCP_PACKET_NAK)
297  {
299  DHCP_STAT_NAK, 1);
300  /* Probably never happens in bound state, but anyhow... */
301  if (c->state == DHCP_BOUND)
302  {
304  (void *) &c->leased_address,
306  1 /*is_del */ );
307  vnet_feature_enable_disable ("ip4-unicast",
308  "ip4-dhcp-client-detect",
309  c->sw_if_index, 1 /* enable */ ,
310  0, 0);
312  }
313  /* Wipe out any memory of the address we had... */
314  c->state = DHCP_DISCOVER;
315  c->next_transmit = now;
316  c->retry_count = 0;
317  c->leased_address.as_u32 = 0;
318  c->subnet_mask_width = 0;
319  c->router_address.as_u32 = 0;
320  c->lease_renewal_interval = 0;
321  c->dhcp_server.as_u32 = 0;
323  break;
324  }
325 
326  if (dhcp_message_type != DHCP_PACKET_ACK &&
327  dhcp_message_type != DHCP_PACKET_OFFER)
328  {
330  DHCP_STAT_NON_OFFER_DISCOVER, 1);
331  clib_warning ("sw_if_index %d state %U message type %d",
333  c->state, dhcp_message_type);
334  c->next_transmit = now + 5.0;
335  break;
336  }
337  /* OK, we own the address (etc), add to the routing table(s) */
339  (u8 *) c, sizeof (*c));
340 
341  c->state = DHCP_BOUND;
342  c->retry_count = 0;
343  c->next_transmit = now + (f64) c->lease_renewal_interval;
344  c->lease_expires = now + (f64) c->lease_lifetime;
346  DHCP_STAT_BOUND, 1);
347  break;
348 
349  default:
350  clib_warning ("client %d bogus state %d", c - dcm->clients, c->state);
351  break;
352  }
353 
354  /* drop the pkt, return 1 */
355  vlib_buffer_free (vm, &bi, 1);
356  return 1;
357 }
358 
359 static void
361  dhcp_packet_type_t type, int is_broadcast)
362 {
363  vlib_main_t *vm = dcm->vlib_main;
364  vnet_main_t *vnm = dcm->vnet_main;
366  vnet_sw_interface_t *sup_sw
369  vlib_buffer_t *b;
370  u32 bi;
371  ip4_header_t *ip;
372  udp_header_t *udp;
373  dhcp_header_t *dhcp;
374  u32 *to_next;
375  vlib_frame_t *f;
376  dhcp_option_t *o;
377  u16 udp_length, ip_length;
378  u32 counter_index, node_index;
379 
380  /* Interface(s) down? */
381  if ((hw->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) == 0)
382  return;
383  if ((sup_sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0)
384  return;
385  if ((sw->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0)
386  return;
387 
388  if (vlib_buffer_alloc (vm, &bi, 1) != 1)
389  {
390  clib_warning ("buffer allocation failure");
391  c->next_transmit = 0;
392  return;
393  }
394 
395  /* Build a dhcpv4 pkt from whole cloth */
396  b = vlib_get_buffer (vm, bi);
398 
399  ASSERT (b->current_data == 0);
400 
401  vnet_buffer (b)->sw_if_index[VLIB_RX] = c->sw_if_index;
402 
403  if (is_broadcast)
404  {
405  node_index = ip4_rewrite_node.index;
406  vnet_buffer (b)->ip.adj_index[VLIB_TX] = c->ai_bcast;
407  }
408  else
409  {
410  ip_adjacency_t *adj = adj_get (c->ai_ucast);
411 
413  node_index = ip4_arp_node.index;
414  else
415  node_index = ip4_rewrite_node.index;
416  vnet_buffer (b)->ip.adj_index[VLIB_TX] = c->ai_ucast;
417  }
418 
419  /* Enqueue the packet right now */
420  f = vlib_get_frame_to_node (vm, node_index);
421  to_next = vlib_frame_vector_args (f);
422  to_next[0] = bi;
423  f->n_vectors = 1;
424  vlib_put_frame_to_node (vm, node_index, f);
425 
426  /* build the headers */
427  ip = vlib_buffer_get_current (b);
428  udp = (udp_header_t *) (ip + 1);
429  dhcp = (dhcp_header_t *) (udp + 1);
430 
431  /* $$$ optimize, maybe */
432  clib_memset (ip, 0, sizeof (*ip) + sizeof (*udp) + sizeof (*dhcp));
433 
434  ip->ip_version_and_header_length = 0x45;
435  ip->ttl = 128;
436  ip->protocol = IP_PROTOCOL_UDP;
437 
438  ip->tos = c->dscp;
439 
440  if (ip->tos)
441  {
442  /*
443  * Setup the buffer's QoS settings so any QoS marker on the egress
444  * interface, that might set VLAN CoS bits, based on this DSCP setting
445  */
446  vnet_buffer2 (b)->qos.source = QOS_SOURCE_IP;
447  vnet_buffer2 (b)->qos.bits = ip->tos;
448  b->flags |= VNET_BUFFER_F_QOS_DATA_VALID;
449  }
450 
451  if (is_broadcast)
452  {
453  /* src = 0.0.0.0, dst = 255.255.255.255 */
454  ip->dst_address.as_u32 = ~0;
455  }
456  else
457  {
458  /* Renewing an active lease, plain old ip4 src/dst */
461  }
462 
463  udp->src_port = clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_client);
464  udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_dhcp_to_server);
465 
466  /* Send the interface MAC address */
469 
470  /* And remember it for rx-packet-for-us checking */
472  sizeof (c->client_hardware_address));
473 
474  /* Lease renewal, set up client_ip_address */
475  if (is_broadcast == 0)
477 
478  dhcp->opcode = 1; /* request, all we send */
479  dhcp->hardware_type = 1; /* ethernet */
480  dhcp->hardware_address_length = 6;
482  dhcp->flags =
483  clib_host_to_net_u16 (is_broadcast && c->set_broadcast_flag ?
484  DHCP_FLAG_BROADCAST : 0);
486 
487  o = (dhcp_option_t *) dhcp->options;
488 
489  /* Send option 53, the DHCP message type */
491  o->length = 1;
492  o->data[0] = type;
493  o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
494 
495  /* Send option 57, max msg length */
496  if (0 /* not needed, apparently */ )
497  {
498  o->option = 57;
499  o->length = 2;
500  {
501  u16 *o2 = (u16 *) o->data;
502  *o2 = clib_host_to_net_u16 (1152);
503  o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
504  }
505  }
506 
507  /*
508  * If server ip address is available with non-zero value,
509  * option 54 (DHCP Server Identifier) is sent.
510  */
511  if (c->dhcp_server.as_u32)
512  {
513  o->option = 54;
514  o->length = 4;
515  clib_memcpy (o->data, &c->dhcp_server.as_u32, 4);
516  o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
517  }
518 
519  /* send option 50, requested IP address */
520  if (c->leased_address.as_u32)
521  {
522  o->option = 50;
523  o->length = 4;
524  clib_memcpy (o->data, &c->leased_address.as_u32, 4);
525  o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
526  }
527 
528  /* send option 12, host name */
529  if (vec_len (c->hostname))
530  {
531  o->option = 12;
532  o->length = vec_len (c->hostname);
533  clib_memcpy (o->data, c->hostname, vec_len (c->hostname));
534  o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
535  }
536 
537  /* send option 61, client_id */
538  if (vec_len (c->client_identifier))
539  {
540  o->option = 61;
541  o->length = vec_len (c->client_identifier);
544  o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
545  }
546 
547  /* $$ maybe send the client s/w version if anyone cares */
548 
549  /*
550  * send option 55, parameter request list
551  * The current list - see below, matches the Linux dhcp client's list
552  * Any specific dhcp server config and/or dhcp server may or may
553  * not yield specific options.
554  */
555  o->option = 55;
556  o->length = vec_len (c->option_55_data);
558  o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
559 
560  /* End of list */
561  o->option = 0xff;
562  o->length = 0;
563  o++;
564 
565  b->current_length = ((u8 *) o) - b->data;
566 
567  /* fix ip length, checksum and udp length */
568  ip_length = vlib_buffer_length_in_chain (vm, b);
569 
570  ip->length = clib_host_to_net_u16 (ip_length);
571  ip->checksum = ip4_header_checksum (ip);
572 
573  udp_length = ip_length - (sizeof (*ip));
574  udp->length = clib_host_to_net_u16 (udp_length);
575 
576  switch (type)
577  {
578 #define _(a,b) case DHCP_PACKET_##a: {counter_index = DHCP_STAT_##a; break;}
580 #undef _
581  default:
582  counter_index = DHCP_STAT_UNKNOWN;
583  break;
584  }
585 
587  counter_index, 1);
588 }
589 
590 static int
592 {
593  /*
594  * State machine "DISCOVER" state. Send a dhcp discover packet,
595  * eventually back off the retry rate.
596  */
597 
598  if (c->client_detect_feature_enabled == 0)
599  {
600  vnet_feature_enable_disable ("ip4-unicast",
601  "ip4-dhcp-client-detect",
602  c->sw_if_index, 1 /* enable */ , 0, 0);
604  }
605 
606  send_dhcp_pkt (dcm, c, DHCP_PACKET_DISCOVER, 1 /* is_broadcast */ );
607 
608  c->retry_count++;
609  if (c->retry_count > 10)
610  c->next_transmit = now + 5.0;
611  else
612  c->next_transmit = now + 1.0;
613  return 0;
614 }
615 
616 static int
618 {
619  /*
620  * State machine "REQUEST" state. Send a dhcp request packet,
621  * eventually drop back to the discover state.
622  */
623  send_dhcp_pkt (dcm, c, DHCP_PACKET_REQUEST, 1 /* is_broadcast */ );
624 
625  c->retry_count++;
626  if (c->retry_count > 7 /* lucky you */ )
627  {
628  c->state = DHCP_DISCOVER;
629  c->next_transmit = now;
630  c->retry_count = 0;
631  return 1;
632  }
633  c->next_transmit = now + 1.0;
634  return 0;
635 }
636 
637 static int
639 {
640  /*
641  * State machine "BOUND" state. Send a dhcp request packet to renew
642  * the lease.
643  * Eventually, when the lease expires, forget the dhcp data
644  * and go back to the stone age.
645  */
646 
647  /*
648  * We disable the client detect feature when we bind a
649  * DHCP address. Turn it back on again on first renew attempt.
650  * Otherwise, if the DHCP server replies we'll never see it.
651  */
652  if (c->client_detect_feature_enabled == 0)
653  {
654  vnet_feature_enable_disable ("ip4-unicast",
655  "ip4-dhcp-client-detect",
656  c->sw_if_index, 1 /* enable */ , 0, 0);
658  }
659 
660  send_dhcp_pkt (dcm, c, DHCP_PACKET_REQUEST, 0 /* is_broadcast */ );
661 
662  c->retry_count++;
663  if (c->retry_count > 10)
664  c->next_transmit = now + 5.0;
665  else
666  c->next_transmit = now + 1.0;
667 
668  if (now > c->lease_expires)
669  {
670  /* Remove the default route */
671  if (c->router_address.as_u32)
672  {
673  fib_prefix_t all_0s = {
674  .fp_len = 0,
675  .fp_addr.ip4.as_u32 = 0x0,
676  .fp_proto = FIB_PROTOCOL_IP4,
677  };
678  ip46_address_t nh = {
679  .ip4 = c->router_address,
680  };
681 
684  &all_0s, FIB_SOURCE_DHCP,
685  DPO_PROTO_IP4, &nh, c->sw_if_index, ~0,
687  }
688  /* Remove the interface address */
690  c->state = DHCP_DISCOVER;
691  c->next_transmit = now;
692  c->retry_count = 0;
693  /* Wipe out any memory of the address we had... */
694  c->leased_address.as_u32 = 0;
695  c->subnet_mask_width = 0;
696  c->router_address.as_u32 = 0;
697  c->lease_renewal_interval = 0;
698  c->dhcp_server.as_u32 = 0;
699  return 1;
700  }
701  return 0;
702 }
703 
704 static f64
705 dhcp_client_sm (f64 now, f64 timeout, uword pool_index)
706 {
708  dhcp_client_t *c;
709 
710  /* deleted, pooched, yadda yadda yadda */
711  if (pool_is_free_index (dcm->clients, pool_index))
712  return timeout;
713 
714  c = pool_elt_at_index (dcm->clients, pool_index);
715 
716  /* Time for us to do something with this client? */
717  if (now < c->next_transmit)
718  return timeout;
719 
720 again:
721  switch (c->state)
722  {
723  case DHCP_DISCOVER: /* send a discover */
724  if (dhcp_discover_state (dcm, c, now))
725  goto again;
726  break;
727 
728  case DHCP_REQUEST: /* send a request */
729  if (dhcp_request_state (dcm, c, now))
730  goto again;
731  break;
732 
733  case DHCP_BOUND: /* bound, renew needed? */
734  if (dhcp_bound_state (dcm, c, now))
735  goto again;
736  break;
737 
738  default:
739  clib_warning ("dhcp client %d bogus state %d",
740  c - dcm->clients, c->state);
741  break;
742  }
743 
744  if (c->next_transmit < now + timeout)
745  return c->next_transmit - now;
746 
747  return timeout;
748 }
749 
750 static uword
753 {
754  f64 timeout = 100.0;
755  f64 now;
756  uword event_type;
757  uword *event_data = 0;
759  dhcp_client_t *c;
760  int i;
761 
762  while (1)
763  {
765 
766  event_type = vlib_process_get_events (vm, &event_data);
767 
768  now = vlib_time_now (vm);
769 
770  switch (event_type)
771  {
773  for (i = 0; i < vec_len (event_data); i++)
774  timeout = dhcp_client_sm (now, timeout, event_data[i]);
775  break;
776 
777  case ~0:
778  /* *INDENT-OFF* */
779  pool_foreach (c, dcm->clients,
780  ({
781  timeout = dhcp_client_sm (now, timeout,
782  (uword) (c - dcm->clients));
783  }));
784  /* *INDENT-ON* */
785  if (pool_elts (dcm->clients) == 0)
786  timeout = 100.0;
787  break;
788  }
789 
790  vec_reset_length (event_data);
791  }
792 
793  /* NOTREACHED */
794  return 0;
795 }
796 
797 /* *INDENT-OFF* */
799  .function = dhcp_client_process,
800  .type = VLIB_NODE_TYPE_PROCESS,
801  .name = "dhcp-client-process",
802  .process_log2_n_stack_bytes = 16,
804  .error_strings = dhcp_client_process_stat_strings,
805 };
806 /* *INDENT-ON* */
807 
808 static u8 *
809 format_dhcp_client_state (u8 * s, va_list * va)
810 {
812  char *str = "BOGUS!";
813 
814  switch (state)
815  {
816 #define _(a) \
817  case a: \
818  str = #a; \
819  break;
821 #undef _
822  default:
823  break;
824  }
825 
826  s = format (s, "%s", str);
827  return s;
828 }
829 
830 static u8 *
831 format_dhcp_client (u8 * s, va_list * va)
832 {
833  dhcp_client_main_t *dcm = va_arg (*va, dhcp_client_main_t *);
834  dhcp_client_t *c = va_arg (*va, dhcp_client_t *);
835  int verbose = va_arg (*va, int);
837 
838  s = format (s, "[%d] %U state %U ", c - dcm->clients,
841 
842  if (0 != c->dscp)
843  s = format (s, "dscp %d ", c->dscp);
844 
845  if (c->leased_address.as_u32)
846  {
847  s = format (s, "addr %U/%d gw %U",
850  &c->router_address);
851 
853  s = format (s, " dns %U", format_ip4_address, addr);
854  }
855  else
856  {
857  s = format (s, "no address\n");
858  }
859 
860  if (verbose)
861  {
862  s =
863  format (s,
864  "\n lease: lifetime:%d renewal-interval:%d expires:%.2f (now:%.2f)",
867  s =
868  format (s, "\n retry-count:%d, next-xmt:%.2f", c->retry_count,
869  c->next_transmit);
870  s =
871  format (s, "\n adjacencies:[unicast:%d broadcast:%d]", c->ai_ucast,
872  c->ai_bcast);
873  }
874  return s;
875 }
876 
877 static clib_error_t *
879  unformat_input_t * input,
880  vlib_cli_command_t * cmd)
881 {
883  dhcp_client_t *c;
884  int verbose = 0;
885  u32 sw_if_index = ~0;
886  uword *p;
887 
889  {
890  if (unformat (input, "intfc %U",
891  unformat_vnet_sw_interface, dcm->vnet_main, &sw_if_index))
892  ;
893  else if (unformat (input, "verbose"))
894  verbose = 1;
895  else
896  break;
897  }
898 
899  if (sw_if_index != ~0)
900  {
901  p = hash_get (dcm->client_by_sw_if_index, sw_if_index);
902  if (p == 0)
903  return clib_error_return (0, "dhcp client not configured");
904  c = pool_elt_at_index (dcm->clients, p[0]);
905  vlib_cli_output (vm, "%U", format_dhcp_client, dcm, c, verbose);
906  return 0;
907  }
908 
909  /* *INDENT-OFF* */
910  pool_foreach (c, dcm->clients,
911  ({
912  vlib_cli_output (vm, "%U",
913  format_dhcp_client, dcm,
914  c, verbose);
915  }));
916  /* *INDENT-ON* */
917 
918  return 0;
919 }
920 
921 /* *INDENT-OFF* */
922 VLIB_CLI_COMMAND (show_dhcp_client_command, static) = {
923  .path = "show dhcp client",
924  .short_help = "show dhcp client [intfc <intfc>][verbose]",
925  .function = show_dhcp_client_command_fn,
926 };
927 /* *INDENT-ON* */
928 
929 
930 int
932 {
934  vlib_main_t *vm = dcm->vlib_main;
935  dhcp_client_t *c;
936  uword *p;
937  fib_prefix_t all_0s = {
938  .fp_len = 0,
939  .fp_addr.ip4.as_u32 = 0x0,
940  .fp_proto = FIB_PROTOCOL_IP4,
941  };
942 
944 
945  if ((p && a->is_add) || (!p && a->is_add == 0))
946  return VNET_API_ERROR_INVALID_VALUE;
947 
948  if (a->is_add)
949  {
951  pool_get (dcm->clients, c);
952  clib_memset (c, 0, sizeof (*c));
953  c->state = DHCP_DISCOVER;
954  c->sw_if_index = a->sw_if_index;
955  c->client_index = a->client_index;
956  c->pid = a->pid;
959  c->hostname = a->hostname;
962  c->dscp = a->dscp;
967 
968  do
969  {
970  c->transaction_id = random_u32 (&dcm->seed);
971  }
972  while (c->transaction_id == 0);
973 
974  hash_set (dcm->client_by_sw_if_index, a->sw_if_index, c - dcm->clients);
975 
976  /*
977  * In order to accept any OFFER, whether broadcasted or unicasted, we
978  * need to configure the dhcp-client-detect feature as an input feature
979  * so the DHCP OFFER is sent to the ip4-local node. Without this a
980  * broadcasted OFFER hits the 255.255.255.255/32 address and a unicast
981  * hits 0.0.0.0/0 both of which default to drop and the latter may forward
982  * of box - not what we want. Nor to we want to change these route for
983  * all interfaces in this table
984  */
985  vnet_feature_enable_disable ("ip4-unicast",
986  "ip4-dhcp-client-detect",
987  c->sw_if_index, 1 /* enable */ , 0, 0);
989 
992  }
993  else
994  {
995  c = pool_elt_at_index (dcm->clients, p[0]);
996 
997  if (c->router_address.as_u32)
998  {
999  ip46_address_t nh = {
1000  .ip4 = c->router_address,
1001  };
1002 
1005  &all_0s, FIB_SOURCE_DHCP,
1006  DPO_PROTO_IP4, &nh, c->sw_if_index, ~0,
1008  }
1009  dhcp_client_release_address (dcm, c);
1010 
1011  adj_unlock (c->ai_ucast);
1012  adj_unlock (c->ai_bcast);
1013 
1015  vec_free (c->option_55_data);
1016  vec_free (c->hostname);
1019  pool_put (dcm->clients, c);
1020  }
1021  return 0;
1022 }
1023 
1024 int
1026  u32 client_index,
1027  vlib_main_t * vm,
1028  u32 sw_if_index,
1029  u8 * hostname,
1030  u8 * client_id,
1031  dhcp_event_cb_t event_callback,
1032  u8 set_broadcast_flag, ip_dscp_t dscp, u32 pid)
1033 {
1034  dhcp_client_add_del_args_t _a, *a = &_a;
1035  int rv;
1036 
1037  clib_memset (a, 0, sizeof (*a));
1038  a->is_add = is_add;
1039  a->sw_if_index = sw_if_index;
1040  a->client_index = client_index;
1041  a->pid = pid;
1042  a->event_callback = event_callback;
1043  a->set_broadcast_flag = set_broadcast_flag;
1044  a->dscp = dscp;
1045  vec_validate (a->hostname, strlen ((char *) hostname) - 1);
1046  strncpy ((char *) a->hostname, (char *) hostname, vec_len (a->hostname));
1047  vec_validate (a->client_identifier, strlen ((char *) client_id) - 1);
1048  strncpy ((char *) a->client_identifier, (char *) client_id,
1049  vec_len (a->client_identifier));
1050 
1051  /*
1052  * Option 55 request list. These data precisely match
1053  * the Ubuntu dhcp client. YMMV.
1054  */
1055 
1056  /* Subnet Mask */
1057  vec_add1 (a->option_55_data, 1);
1058  /* Broadcast address */
1059  vec_add1 (a->option_55_data, 28);
1060  /* time offset */
1061  vec_add1 (a->option_55_data, 2);
1062  /* Router */
1063  vec_add1 (a->option_55_data, 3);
1064  /* Domain Name */
1065  vec_add1 (a->option_55_data, 15);
1066  /* DNS */
1067  vec_add1 (a->option_55_data, 6);
1068  /* Domain search */
1069  vec_add1 (a->option_55_data, 119);
1070  /* Host name */
1071  vec_add1 (a->option_55_data, 12);
1072  /* NetBIOS name server */
1073  vec_add1 (a->option_55_data, 44);
1074  /* NetBIOS Scope */
1075  vec_add1 (a->option_55_data, 47);
1076  /* MTU */
1077  vec_add1 (a->option_55_data, 26);
1078  /* Classless static route */
1079  vec_add1 (a->option_55_data, 121);
1080  /* NTP servers */
1081  vec_add1 (a->option_55_data, 42);
1082 
1083  rv = dhcp_client_add_del (a);
1084 
1085  switch (rv)
1086  {
1087  case 0:
1088  break;
1089 
1090  case VNET_API_ERROR_INVALID_VALUE:
1091 
1092  vec_free (a->hostname);
1094  vec_free (a->option_55_data);
1095 
1096  if (is_add)
1097  clib_warning ("dhcp client already enabled on intf_idx %d",
1098  sw_if_index);
1099  else
1100  clib_warning ("dhcp client not enabled on on intf_idx %d",
1101  sw_if_index);
1102  break;
1103 
1104  default:
1105  clib_warning ("dhcp_client_add_del returned %d", rv);
1106  }
1107 
1108  return rv;
1109 }
1110 
1111 void
1113 {
1115  dhcp_client_t *c;
1116 
1117  /* *INDENT-OFF* */
1118  pool_foreach (c, dcm->clients,
1119  ({
1120  if (!cb(c, ctx))
1121  break;
1122  }));
1123  /* *INDENT-ON* */
1124 
1125 }
1126 
1127 static clib_error_t *
1129  unformat_input_t * input,
1130  vlib_cli_command_t * cmd)
1131 {
1132 
1134  u32 sw_if_index;
1135  u8 *hostname = 0;
1136  u8 sw_if_index_set = 0;
1137  u8 set_broadcast_flag = 1;
1138  int is_add = 1;
1139  dhcp_client_add_del_args_t _a, *a = &_a;
1140  int rv;
1141 
1142  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1143  {
1144  if (unformat (input, "intfc %U",
1145  unformat_vnet_sw_interface, dcm->vnet_main, &sw_if_index))
1146  sw_if_index_set = 1;
1147  else if (unformat (input, "hostname %v", &hostname))
1148  ;
1149  else if (unformat (input, "del"))
1150  is_add = 0;
1151  else if (unformat (input, "broadcast", &set_broadcast_flag))
1152  is_add = 0;
1153  else
1154  break;
1155  }
1156 
1157  if (sw_if_index_set == 0)
1158  return clib_error_return (0, "interface not specified");
1159 
1160  clib_memset (a, 0, sizeof (*a));
1161  a->is_add = is_add;
1162  a->sw_if_index = sw_if_index;
1163  a->hostname = hostname;
1164  a->client_identifier = format (0, "vpe 1.0%c", 0);
1165  a->set_broadcast_flag = set_broadcast_flag;
1166 
1167  /*
1168  * Option 55 request list. These data precisely match
1169  * the Ubuntu dhcp client. YMMV.
1170  */
1171 
1172  /* Subnet Mask */
1173  vec_add1 (a->option_55_data, 1);
1174  /* Broadcast address */
1175  vec_add1 (a->option_55_data, 28);
1176  /* time offset */
1177  vec_add1 (a->option_55_data, 2);
1178  /* Router */
1179  vec_add1 (a->option_55_data, 3);
1180  /* Domain Name */
1181  vec_add1 (a->option_55_data, 15);
1182  /* DNS */
1183  vec_add1 (a->option_55_data, 6);
1184  /* Domain search */
1185  vec_add1 (a->option_55_data, 119);
1186  /* Host name */
1187  vec_add1 (a->option_55_data, 12);
1188  /* NetBIOS name server */
1189  vec_add1 (a->option_55_data, 44);
1190  /* NetBIOS Scope */
1191  vec_add1 (a->option_55_data, 47);
1192  /* MTU */
1193  vec_add1 (a->option_55_data, 26);
1194  /* Classless static route */
1195  vec_add1 (a->option_55_data, 121);
1196  /* NTP servers */
1197  vec_add1 (a->option_55_data, 42);
1198 
1199  rv = dhcp_client_add_del (a);
1200 
1201  switch (rv)
1202  {
1203  case 0:
1204  break;
1205 
1206  case VNET_API_ERROR_INVALID_VALUE:
1207 
1208  vec_free (a->hostname);
1210  vec_free (a->option_55_data);
1211  if (is_add)
1212  return clib_error_return (0, "dhcp client already enabled on %U",
1214  dcm->vnet_main, sw_if_index);
1215  else
1216  return clib_error_return (0, "dhcp client not enabled on %U",
1218  dcm->vnet_main, sw_if_index);
1219  break;
1220 
1221  default:
1222  vlib_cli_output (vm, "dhcp_client_add_del returned %d", rv);
1223  }
1224 
1225  return 0;
1226 }
1227 
1228 /* *INDENT-OFF* */
1229 VLIB_CLI_COMMAND (dhcp_client_set_command, static) = {
1230  .path = "set dhcp client",
1231  .short_help = "set dhcp client [del] intfc <interface> [hostname <name>]",
1232  .function = dhcp_client_set_command_fn,
1233 };
1234 /* *INDENT-ON* */
1235 
1236 static clib_error_t *
1238 {
1240 
1241  dcm->vlib_main = vm;
1242  dcm->vnet_main = vnet_get_main ();
1243  dcm->seed = (u32) clib_cpu_time_now ();
1244  return 0;
1245 }
1246 
1248 
1249 /*
1250  * fd.io coding-style-patch-verification: ON
1251  *
1252  * Local Variables:
1253  * eval: (c-set-style "gnu")
1254  * End:
1255  */
static u8 * format_dhcp_client(u8 *s, va_list *va)
Definition: client.c:831
u8 client_detect_feature_enabled
Definition: client.h:86
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
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
u8 client_hardware_address[16]
Definition: dhcp4_packet.h:47
fib_node_index_t fib_table_entry_path_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Add one path to an entry (aka route) in the FIB.
Definition: fib_table.c:532
#define hash_set(h, key, value)
Definition: hash.h:255
adj_index_t ai_ucast
Definition: client.h:89
static void dhcp_client_addr_callback(dhcp_client_t *c)
Definition: client.c:89
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:673
#define hash_unset(h, key)
Definition: hash.h:261
a
Definition: bitmap.h:538
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:865
u32 retry_count
Definition: client.h:53
ip4_address_t src_address
Definition: ip4_packet.h:170
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)
#define vnet_buffer2(b)
Definition: buffer.h:420
vl_api_fib_path_nh_t nh
Definition: fib_types.api:126
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
u32 lease_lifetime
Definition: client.h:69
ip_dscp_t dscp
Definition: client.h:93
static void send_dhcp_pkt(dhcp_client_main_t *dcm, dhcp_client_t *c, dhcp_packet_type_t type, int is_broadcast)
Definition: client.c:360
#define NULL
Definition: clib.h:58
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:258
IP unicast adjacency.
Definition: adj.h:221
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
Definition: fib_table.c:967
u8 * option_55_data
Definition: client.h:72
static void dhcp_client_release_address(dhcp_client_main_t *dcm, dhcp_client_t *c)
Definition: client.c:67
static int dhcp_discover_state(dhcp_client_main_t *dcm, dhcp_client_t *c, f64 now)
Definition: client.c:591
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
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
static u64 clib_cpu_time_now(void)
Definition: time.h:75
dhcp_client_t * clients
Definition: client.h:101
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:158
int i
u32 sw_if_index
Definition: client.h:50
#define DHCP_MAGIC
Definition: dhcp4_packet.h:70
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
void dhcp_client_walk(dhcp_client_walk_cb_t cb, void *ctx)
Walk (visit each) DHCP client configuration.
Definition: client.c:1112
void vlib_cli_output(struct vlib_main_t *vm, char *fmt,...)
Definition: client.c:147
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
static int dhcp_request_state(dhcp_client_main_t *dcm, dhcp_client_t *c, f64 now)
Definition: client.c:617
ip4_address_t server_ip_address
Definition: dhcp4_packet.h:45
static u8 * format_dhcp_client_state(u8 *s, va_list *va)
Definition: client.c:809
dhcp_event_cb_t event_callback
Definition: client.h:127
dhcp_client_state_t state
Definition: client.h:47
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:366
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
vhost_vring_addr_t addr
Definition: vhost_user.h:147
static char * dhcp_client_process_stat_strings[]
Definition: client.c:48
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
u32 transaction_id
Definition: client.h:60
u32 data_as_u32[0]
Definition: dhcp4_packet.h:29
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
int dhcp_client_config(u32 is_add, u32 client_index, vlib_main_t *vm, u32 sw_if_index, u8 *hostname, u8 *client_id, dhcp_event_cb_t event_callback, u8 set_broadcast_flag, ip_dscp_t dscp, u32 pid)
Add/Delete DHCP clients.
Definition: client.c:1025
#define clib_memcpy(d, s, n)
Definition: string.h:180
format_function_t format_ip4_address
Definition: format.h:75
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:433
static vlib_node_registration_t dhcp_client_process_node
(constructor) VLIB_REGISTER_NODE (dhcp_client_process_node)
Definition: client.c:24
u32 lease_renewal_interval
Definition: client.h:68
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
vl_api_interface_index_t sw_if_index
Definition: gre.api:50
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:516
ip4_address_t dst_address
Definition: ip4_packet.h:170
dhcp_event_cb_t event_callback
Definition: client.h:95
vnet_hw_interface_flags_t flags
Definition: interface.h:505
static uword dhcp_client_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: client.c:751
static vnet_sw_interface_t * vnet_get_sup_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
Aggregrate type for a prefix.
Definition: fib_types.h:203
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
#define clib_error_return(e, args...)
Definition: error.h:99
static int dhcp_bound_state(dhcp_client_main_t *dcm, dhcp_client_t *c, f64 now)
Definition: client.c:638
adj_index_t ai_bcast
Definition: client.h:91
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: vlib_api.c:600
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:318
vhost_vring_state_t state
Definition: vhost_user.h:146
unsigned int u32
Definition: types.h:88
u16 fp_len
The mask length.
Definition: fib_types.h:207
static const u8 * vnet_sw_interface_get_hw_address(vnet_main_t *vnm, u32 sw_if_index)
Definition: fib_entry.h:281
vlib_node_registration_t ip4_arp_node
(constructor) VLIB_REGISTER_NODE (ip4_arp_node)
Definition: ip4_forward.c:1995
u8 set_broadcast_flag
Definition: client.h:83
vl_api_fib_path_type_t type
Definition: fib_types.api:123
clib_error_t * ip4_add_del_interface_address(vlib_main_t *vm, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 is_del)
Definition: ip4_forward.c:637
ip4_address_t leased_address
Definition: client.h:63
static void dhcp_client_acquire_address(dhcp_client_main_t *dcm, dhcp_client_t *c)
Definition: client.c:56
#define hash_get(h, key)
Definition: hash.h:249
dhcp_client_state_t
Definition: client.h:30
#define ADJ_INDEX_INVALID
Invalid ADJ index - used when no adj is known likewise blazoned capitals INVALID speak volumes where ...
Definition: adj_types.h:36
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:934
vlib_main_t * vlib_main
Definition: client.h:106
long ctx[MAX_CONNS]
Definition: main.c:144
static clib_error_t * dhcp_client_init(vlib_main_t *vm)
Definition: client.c:1237
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
static f64 dhcp_client_sm(f64 now, f64 timeout, uword pool_index)
Definition: client.c:705
void(* dhcp_event_cb_t)(u32 client_index, const struct dhcp_client_t_ *client)
Callback function for DHCP complete events.
Definition: client.h:42
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
vnet_sw_interface_flags_t flags
Definition: interface.h:699
dhcp_client_main_t dhcp_client_main
Definition: client.c:22
vl_api_address_t dst
Definition: gre.api:52
u8 client_hardware_address[6]
Definition: client.h:85
static u32 counter_index(vlib_main_t *vm, vlib_error_t e)
Definition: drop.c:67
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
static clib_error_t * show_dhcp_client_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: client.c:878
dhcp_option_t options[0]
Definition: dhcp4_packet.h:51
ip4_address_t client_ip_address
Definition: dhcp4_packet.h:43
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
svmdb_client_t * c
u16 n_vectors
Definition: node.h:395
vlib_node_registration_t ip4_rewrite_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_node)
Definition: ip4_forward.c:2660
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:213
vlib_main_t * vm
Definition: buffer.c:312
f64 next_transmit
Definition: client.h:56
ip4_address_t * domain_server_address
Definition: client.h:67
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
#define clib_warning(format, args...)
Definition: error.h:59
static void dhcp_client_proc_callback(uword *client_index)
Definition: client.c:80
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
#define ARRAY_LEN(x)
Definition: clib.h:62
u32 client_index
Definition: client.h:79
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
#define EVENT_DHCP_CLIENT_WAKEUP
Definition: client.h:132
#define ASSERT(truth)
enum ip_dscp_t_ ip_dscp_t
ip_dscp_t tos
Definition: ip4_packet.h:141
u32 transaction_identifier
Definition: dhcp4_packet.h:39
u8 hardware_address_length
Definition: dhcp4_packet.h:37
u32 subnet_mask_width
Definition: client.h:65
void fib_table_entry_path_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_route_path_flags_t path_flags)
remove one path to an entry (aka route) in the FIB.
Definition: fib_table.c:693
#define DHCP_FLAG_BROADCAST
Definition: dhcp4_packet.h:42
ip4_address_t router_address
Definition: client.h:66
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
struct _vlib_node_registration vlib_node_registration_t
Definition: defs.h:47
u8 * client_identifier
Definition: client.h:76
vl_api_address_t ip
Definition: l2.api:489
ip4_address_t magic_cookie
Definition: dhcp4_packet.h:50
int(* dhcp_client_walk_cb_t)(const dhcp_client_t *client, void *data)
callback function for clients walking the DHCP client configurations
Definition: client.h:159
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:236
DHCP.
Definition: fib_entry.h:99
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:489
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:244
void dhcp_maybe_register_udp_ports(dhcp_port_reg_flags_t ports)
Register the dhcp client and/or server ports, if not already done.
uword * client_by_sw_if_index
Definition: client.h:102
sample_error_t
Definition: client.c:39
int dhcp_client_add_del(dhcp_client_add_del_args_t *a)
Definition: client.c:931
#define vnet_buffer(b)
Definition: buffer.h:361
u8 * hostname
Definition: client.h:75
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
adj_index_t adj_nbr_add_or_lock(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index)
Neighbour Adjacency sub-type.
Definition: adj_nbr.c:218
#define vec_foreach(var, vec)
Vector iterator.
static uword count_set_bits(uword x)
Definition: bitops.h:45
static clib_error_t * dhcp_client_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: client.c:1128
f64 lease_expires
Definition: client.h:57
vnet_main_t * vnet_main
Definition: client.h:107
u8 ip_version_and_header_length
Definition: ip4_packet.h:138
dhcp_packet_type_t
Definition: dhcp4_packet.h:54
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:612
ip4_address_t dhcp_server
Definition: client.h:64
#define foreach_dhcp_sent_packet_stat
Definition: client.c:26
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
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
const ip46_address_t ADJ_BCAST_ADDR
The special broadcast address (to construct a broadcast adjacency.
Definition: adj.c:41
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
Definition: defs.h:46
ip4_address_t your_ip_address
Definition: dhcp4_packet.h:44
#define foreach_dhcp_error_counter
Definition: client.c:32
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:274
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128