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