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