FD.io VPP  v20.05-21-gb1500e9ff
Vector Packet Processing
dhcp_api.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * dhcp_api.c - dhcp api
4  *
5  * Copyright (c) 2016 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #include <vnet/vnet.h>
21 #include <vlibmemory/api.h>
22 
23 #include <vnet/interface.h>
24 #include <vnet/api_errno.h>
25 #include <dhcp/dhcp_proxy.h>
26 #include <dhcp/client.h>
30 #include <vnet/fib/fib_table.h>
31 #include <vnet/ip/ip_types_api.h>
32 
33 /* define message IDs */
34 #include <vnet/format_fns.h>
35 #include <dhcp/dhcp.api_enum.h>
36 #include <dhcp/dhcp.api_types.h>
37 
38 /**
39  * Base message ID fot the plugin
40  */
42 #define REPLY_MSG_ID_BASE dhcp_base_msg_id
43 
45 
46 #define DHCP_PLUGIN_VERSION_MAJOR 1
47 #define DHCP_PLUGIN_VERSION_MINOR 0
48 
49 static void
51  mp)
52 {
54  int msg_size = sizeof (*rmp);
56 
58  if (!reg)
59  return;
60 
61  rmp = vl_msg_api_alloc (msg_size);
62  clib_memset (rmp, 0, msg_size);
63  rmp->_vl_msg_id =
64  ntohs (VL_API_DHCP_PLUGIN_GET_VERSION_REPLY + REPLY_MSG_ID_BASE);
65  rmp->context = mp->context;
66  rmp->major = htonl (DHCP_PLUGIN_VERSION_MAJOR);
67  rmp->minor = htonl (DHCP_PLUGIN_VERSION_MINOR);
68 
69  vl_api_send_msg (reg, (u8 *) rmp);
70 }
71 
72 static void
74  mp)
75 {
77  int rv = 0;
78 
79  /* *INDENT-OFF* */
80  REPLY_MACRO2 (VL_API_DHCP_PLUGIN_CONTROL_PING_REPLY,
81  ({
82  rmp->vpe_pid = ntohl (getpid ());
83  }));
84  /* *INDENT-ON* */
85 }
86 
87 static void
89 {
90  vl_api_dhcp6_duid_ll_set_reply_t *rmp;
92  int rv = 0;
93 
94  duid = (dhcpv6_duid_ll_string_t *) mp->duid_ll;
95  if (duid->duid_type != htonl (DHCPV6_DUID_LL))
96  {
97  rv = VNET_API_ERROR_INVALID_VALUE;
98  goto reply;
99  }
100  clib_memcpy (&client_duid, &duid, sizeof (client_duid));
101 
102 reply:
103  REPLY_MACRO (VL_API_DHCP6_DUID_LL_SET_REPLY);
104 }
105 
106 static void
108 {
109  vl_api_dhcp_proxy_set_vss_reply_t *rmp;
110  u8 *vpn_ascii_id;
111  int rv;
112 
113  mp->vpn_ascii_id[sizeof (mp->vpn_ascii_id) - 1] = 0;
114  vpn_ascii_id = format (0, "%s", mp->vpn_ascii_id);
115  rv =
117  ntohl (mp->tbl_id), ntohl (mp->vss_type),
118  vpn_ascii_id, ntohl (mp->oui), ntohl (mp->vpn_index),
119  mp->is_add == 0);
120 
121  REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
122 }
123 
124 
127 {
128  vl_api_dhcp_proxy_set_vss_reply_t *rmp;
129  ip46_address_t src, server;
130  int rv = -1;
131 
132  if (mp->dhcp_src_address.af != mp->dhcp_server.af)
133  {
134  rv = VNET_API_ERROR_INVALID_ARGUMENT;
135  goto reply;
136  }
137 
138  ip_address_decode (&mp->dhcp_src_address, &src);
139  ip_address_decode (&mp->dhcp_server, &server);
140 
141  if (mp->dhcp_src_address.af == ADDRESS_IP4)
142  {
143  rv = dhcp4_proxy_set_server (&server,
144  &src,
145  (u32) ntohl (mp->rx_vrf_id),
146  (u32) ntohl (mp->server_vrf_id),
147  (int) (mp->is_add == 0));
148  }
149  else
150  {
151  rv = dhcp6_proxy_set_server (&server,
152  &src,
153  (u32) ntohl (mp->rx_vrf_id),
154  (u32) ntohl (mp->server_vrf_id),
155  (int) (mp->is_add == 0));
156  }
157 
158 reply:
159  REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
160 }
161 
162 static void
164 {
166 
168  if (!reg)
169  return;;
170 
171  dhcp_proxy_dump ((mp->is_ip6 == 1 ?
173 }
174 
175 void
177  void *opaque, u32 context, dhcp_proxy_t * proxy)
178 {
180  vl_api_registration_t *reg = opaque;
181  vl_api_dhcp_server_t *v_server;
182  dhcp_server_t *server;
183  fib_table_t *s_fib;
184  dhcp_vss_t *vss;
185  u32 count;
186  size_t n;
187 
188  count = vec_len (proxy->dhcp_servers);
189  n = sizeof (*mp) + (count * sizeof (vl_api_dhcp_server_t));
190  mp = vl_msg_api_alloc (n);
191  if (!mp)
192  return;
193  clib_memset (mp, 0, n);
194  mp->_vl_msg_id = ntohs (VL_API_DHCP_PROXY_DETAILS + REPLY_MSG_ID_BASE);
195  mp->context = context;
196  mp->count = count;
197 
198  mp->is_ipv6 = (proto == FIB_PROTOCOL_IP6);
199  mp->rx_vrf_id =
200  htonl (dhcp_proxy_rx_table_get_table_id (proto, proxy->rx_fib_index));
201 
202  vss = dhcp_get_vss_info (&dhcp_proxy_main, proxy->rx_fib_index, proto);
203 
204  if (vss)
205  {
206  mp->vss_type = ntohl (vss->vss_type);
207  if (vss->vss_type == VSS_TYPE_ASCII)
208  {
209  u32 id_len = vec_len (vss->vpn_ascii_id);
210  clib_memcpy (mp->vss_vpn_ascii_id, vss->vpn_ascii_id, id_len);
211  }
212  else if (vss->vss_type == VSS_TYPE_VPN_ID)
213  {
214  u32 oui = ((u32) vss->vpn_id[0] << 16) + ((u32) vss->vpn_id[1] << 8)
215  + ((u32) vss->vpn_id[2]);
216  u32 fib_id = ((u32) vss->vpn_id[3] << 24) +
217  ((u32) vss->vpn_id[4] << 16) + ((u32) vss->vpn_id[5] << 8) +
218  ((u32) vss->vpn_id[6]);
219  mp->vss_oui = htonl (oui);
220  mp->vss_fib_id = htonl (fib_id);
221  }
222  }
223  else
225 
226  vec_foreach_index (count, proxy->dhcp_servers)
227  {
228  server = &proxy->dhcp_servers[count];
229  v_server = &mp->servers[count];
230 
231  s_fib = fib_table_get (server->server_fib_index, proto);
232 
233  v_server->server_vrf_id = htonl (s_fib->ft_table_id);
234 
235  if (mp->is_ipv6)
236  {
237  memcpy (&v_server->dhcp_server.un, &server->dhcp_server.ip6, 16);
238  }
239  else
240  {
241  /* put the address in the first bytes */
242  memcpy (&v_server->dhcp_server.un, &server->dhcp_server.ip4, 4);
243  }
244  }
245 
246  if (mp->is_ipv6)
247  {
248  memcpy (&mp->dhcp_src_address.un, &proxy->dhcp_src_address.ip6, 16);
249  }
250  else
251  {
252  /* put the address in the first bytes */
253  memcpy (&mp->dhcp_src_address.un, &proxy->dhcp_src_address.ip4, 4);
254  }
255  vl_api_send_msg (reg, (u8 *) mp);
256 }
257 
258 static void
259 dhcp_client_lease_encode (vl_api_dhcp_lease_t * lease,
260  const dhcp_client_t * client)
261 {
262  size_t len;
263  u8 i;
264 
265  lease->is_ipv6 = 0; // only support IPv6 clients
266  lease->sw_if_index = ntohl (client->sw_if_index);
267  lease->state = ntohl (client->state);
268  len = clib_min (sizeof (lease->hostname) - 1, vec_len (client->hostname));
269  clib_memcpy (&lease->hostname, client->hostname, len);
270  lease->hostname[len] = 0;
271 
272  lease->mask_width = client->installed.subnet_mask_width;
273  clib_memcpy (&lease->host_address.un,
274  (u8 *) & client->installed.leased_address,
275  sizeof (ip4_address_t));
276  clib_memcpy (&lease->router_address.un,
277  (u8 *) & client->installed.router_address,
278  sizeof (ip4_address_t));
279 
280  lease->count = vec_len (client->domain_server_address);
281  for (i = 0; i < lease->count; i++)
282  clib_memcpy (&lease->domain_server[i].address,
283  (u8 *) & client->domain_server_address[i],
284  sizeof (ip4_address_t));
285 
286  clib_memcpy (&lease->host_mac[0], client->client_hardware_address, 6);
287 }
288 
289 static void
290 dhcp_client_data_encode (vl_api_dhcp_client_t * vclient,
291  const dhcp_client_t * client)
292 {
293  size_t len;
294 
295  vclient->sw_if_index = ntohl (client->sw_if_index);
296  len = clib_min (sizeof (vclient->hostname) - 1, vec_len (client->hostname));
297  clib_memcpy (&vclient->hostname, client->hostname, len);
298  vclient->hostname[len] = 0;
299 
300  len = clib_min (sizeof (vclient->id) - 1,
301  vec_len (client->client_identifier));
302  clib_memcpy (&vclient->id, client->client_identifier, len);
303  vclient->id[len] = 0;
304 
305  if (NULL != client->event_callback)
306  vclient->want_dhcp_event = 1;
307  else
308  vclient->want_dhcp_event = 0;
309  vclient->set_broadcast_flag = client->set_broadcast_flag;
310  vclient->dscp = ip_dscp_encode (client->dscp);
311  vclient->pid = client->pid;
312 }
313 
314 static void
315 dhcp_compl_event_callback (u32 client_index, const dhcp_client_t * client)
316 {
319 
320  reg = vl_api_client_index_to_registration (client_index);
321  if (!reg)
322  return;
323 
324  mp = vl_msg_api_alloc (sizeof (*mp));
325  mp->client_index = client_index;
326  mp->pid = client->pid;
327  dhcp_client_lease_encode (&mp->lease, client);
328 
329  mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT + REPLY_MSG_ID_BASE);
330 
331  vl_api_send_msg (reg, (u8 *) mp);
332 }
333 
336 {
338  vl_api_dhcp_client_config_reply_t *rmp;
340  ip_dscp_t dscp;
341  int rv = 0;
342 
343  VALIDATE_SW_IF_INDEX (&(mp->client));
344 
345  sw_if_index = ntohl (mp->client.sw_if_index);
346  dscp = ip_dscp_decode (mp->client.dscp);
347 
348  rv = dhcp_client_config (mp->is_add,
349  mp->client_index,
350  vm,
351  sw_if_index,
352  mp->client.hostname,
353  mp->client.id,
354  (mp->client.want_dhcp_event ?
356  NULL),
357  mp->client.set_broadcast_flag,
358  dscp, mp->client.pid);
359 
361  REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
362 }
363 
365 {
369 
370 static int
371 send_dhcp_client_entry (const dhcp_client_t * client, void *arg)
372 {
375  u32 count;
376  size_t n;
377 
378  ctx = arg;
379 
380  count = vec_len (client->domain_server_address);
381  n = sizeof (*mp) + (count * sizeof (vl_api_domain_server_t));
382  mp = vl_msg_api_alloc (n);
383  if (!mp)
384  return 0;
385  clib_memset (mp, 0, n);
386 
387  mp->_vl_msg_id = ntohs (VL_API_DHCP_CLIENT_DETAILS + REPLY_MSG_ID_BASE);
388  mp->context = ctx->context;
389 
390  dhcp_client_data_encode (&mp->client, client);
391  dhcp_client_lease_encode (&mp->lease, client);
392 
393  vl_api_send_msg (ctx->reg, (u8 *) mp);
394 
395  return (1);
396 }
397 
398 static void
400 {
402 
404  if (!reg)
405  return;
406 
408  .reg = reg,
409  .context = mp->context,
410  };
412 }
413 
414 static void
417 {
418  vl_api_dhcp6_clients_enable_disable_reply_t *rmp;
419  int rv = 0;
420 
422 
423  REPLY_MACRO (VL_API_DHCP6_CLIENTS_ENABLE_DISABLE_REPLY);
424 }
425 
426 void
429 {
431  vl_api_want_dhcp6_reply_events_reply_t *rmp;
432  int rv = 0;
433 
434  uword *p =
435  hash_get (am->dhcp6_reply_events_registration_hash, mp->client_index);
437  if (p)
438  {
439  if (mp->enable_disable)
440  {
441  clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
442  rv = VNET_API_ERROR_INVALID_REGISTRATION;
443  goto reply;
444  }
445  else
446  {
447  rp = pool_elt_at_index (am->dhcp6_reply_events_registrations, p[0]);
448  pool_put (am->dhcp6_reply_events_registrations, rp);
449  hash_unset (am->dhcp6_reply_events_registration_hash,
450  mp->client_index);
451  if (pool_elts (am->dhcp6_reply_events_registrations) == 0)
453  goto reply;
454  }
455  }
456  if (mp->enable_disable == 0)
457  {
458  clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
459  rv = VNET_API_ERROR_INVALID_REGISTRATION;
460  goto reply;
461  }
462  pool_get (am->dhcp6_reply_events_registrations, rp);
463  rp->client_index = mp->client_index;
464  rp->client_pid = ntohl (mp->pid);
465  hash_set (am->dhcp6_reply_events_registration_hash, rp->client_index,
466  rp - am->dhcp6_reply_events_registrations);
469 
470 reply:
471  REPLY_MACRO (VL_API_WANT_DHCP6_REPLY_EVENTS_REPLY);
472 }
473 
474 void
477 {
479  vl_api_want_dhcp6_pd_reply_events_reply_t *rmp;
480  int rv = 0;
481 
482  uword *p =
483  hash_get (am->dhcp6_pd_reply_events_registration_hash, mp->client_index);
485  if (p)
486  {
487  if (mp->enable_disable)
488  {
489  clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
490  rv = VNET_API_ERROR_INVALID_REGISTRATION;
491  goto reply;
492  }
493  else
494  {
495  rp =
496  pool_elt_at_index (am->dhcp6_pd_reply_events_registrations, p[0]);
497  pool_put (am->dhcp6_pd_reply_events_registrations, rp);
498  hash_unset (am->dhcp6_pd_reply_events_registration_hash,
499  mp->client_index);
500  if (pool_elts (am->dhcp6_pd_reply_events_registrations) == 0)
502  goto reply;
503  }
504  }
505  if (mp->enable_disable == 0)
506  {
507  clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
508  rv = VNET_API_ERROR_INVALID_REGISTRATION;
509  goto reply;
510  }
511  pool_get (am->dhcp6_pd_reply_events_registrations, rp);
512  rp->client_index = mp->client_index;
513  rp->client_pid = ntohl (mp->pid);
514  hash_set (am->dhcp6_pd_reply_events_registration_hash, rp->client_index,
515  rp - am->dhcp6_pd_reply_events_registrations);
516  dhcp6_pd_set_publisher_node (dhcp6_pd_reply_process_node.index,
518 
519 reply:
520  REPLY_MACRO (VL_API_WANT_DHCP6_PD_REPLY_EVENTS_REPLY);
521 }
522 
523 void
526 {
527  vl_api_dhcp6_send_client_message_reply_t *rmp;
530  u32 n_addresses;
531  u32 i;
532  int rv = 0;
533 
535 
537  REPLY_MACRO (VL_API_DHCP6_SEND_CLIENT_MESSAGE_REPLY);
538 
539  if (rv != 0)
540  return;
541 
542  params.sw_if_index = ntohl (mp->sw_if_index);
543  params.server_index = ntohl (mp->server_index);
544  params.irt = ntohl (mp->irt);
545  params.mrt = ntohl (mp->mrt);
546  params.mrc = ntohl (mp->mrc);
547  params.mrd = ntohl (mp->mrd);
548  params.msg_type = ntohl (mp->msg_type);
549  params.T1 = ntohl (mp->T1);
550  params.T2 = ntohl (mp->T2);
551  n_addresses = ntohl (mp->n_addresses);
552  /* Make sure that the number of addresses is sane */
553  if (n_addresses * sizeof (params.addresses) > vl_msg_api_max_length (mp))
554  {
555  rv = VNET_API_ERROR_INVALID_VALUE;
556  goto bad_sw_if_index;
557  }
558  params.addresses = 0;
559  if (n_addresses > 0)
560  vec_validate (params.addresses, n_addresses - 1);
561  for (i = 0; i < n_addresses; i++)
562  {
563  vl_api_dhcp6_address_info_t *ai = &mp->addresses[i];
565  addr->preferred_lt = ntohl (ai->preferred_time);
566  addr->valid_lt = ntohl (ai->valid_time);
567  ip6_address_decode (ai->address, &addr->address);
568  }
569 
570  dhcp6_send_client_message (vm, ntohl (mp->sw_if_index), mp->stop, &params);
571 }
572 
573 void
576 {
577  vl_api_dhcp6_pd_send_client_message_reply_t *rmp;
580  u32 n_prefixes;
581  u32 i;
582  int rv = 0;
583 
585 
587  REPLY_MACRO (VL_API_DHCP6_PD_SEND_CLIENT_MESSAGE_REPLY);
588 
589  if (rv != 0)
590  return;
591 
592  params.sw_if_index = ntohl (mp->sw_if_index);
593  params.server_index = ntohl (mp->server_index);
594  params.irt = ntohl (mp->irt);
595  params.mrt = ntohl (mp->mrt);
596  params.mrc = ntohl (mp->mrc);
597  params.mrd = ntohl (mp->mrd);
598  params.msg_type = ntohl (mp->msg_type);
599  params.T1 = ntohl (mp->T1);
600  params.T2 = ntohl (mp->T2);
601  n_prefixes = ntohl (mp->n_prefixes);
602 
603  /* Minimal check to see that the number of prefixes is sane */
604  if (n_prefixes * sizeof (params.prefixes) > vl_msg_api_max_length (mp))
605  {
606  rv = VNET_API_ERROR_INVALID_VALUE;
607  goto bad_sw_if_index;
608  }
609 
610  params.prefixes = 0;
611  if (n_prefixes > 0)
612  vec_validate (params.prefixes, n_prefixes - 1);
613  for (i = 0; i < n_prefixes; i++)
614  {
615  vl_api_dhcp6_pd_prefix_info_t *pi = &mp->prefixes[i];
617  &params.prefixes[i];
618  pref->preferred_lt = ntohl (pi->preferred_time);
619  pref->valid_lt = ntohl (pi->valid_time);
620  ip6_address_decode (pi->prefix.address, &pref->prefix);
621  pref->prefix_length = pi->prefix.len;
622  }
623 
624  dhcp6_pd_send_client_message (vm, ntohl (mp->sw_if_index), mp->stop,
625  &params);
626 }
627 
628 static clib_error_t *
630  _vnet_dhcp6_reply_event_function_list_elt_t
631  * elt)
632 {
633  clib_error_t *error = 0;
634 
635  while (elt)
636  {
637  error = elt->fp (data);
638  if (error)
639  return error;
640  elt = elt->next_dhcp6_reply_event_function;
641  }
642 
643  return error;
644 }
645 
646 static uword
648  vlib_frame_t * f)
649 {
650  /* These cross the longjmp boundary (vlib_process_wait_for_event)
651  * and need to be volatile - to prevent them from being optimized into
652  * a register - which could change during suspension */
653 
654  while (1)
655  {
657  uword event_type = DHCP6_DP_REPLY_REPORT;
658  void *event_data = vlib_process_get_event_data (vm, &event_type);
659 
660  int i;
661  if (event_type == DHCP6_DP_REPLY_REPORT)
662  {
663  address_report_t *events = event_data;
664  for (i = 0; i < vec_len (events); i++)
665  {
666  u32 event_size =
667  sizeof (vl_api_dhcp6_reply_event_t) +
668  vec_len (events[i].addresses) *
669  sizeof (vl_api_dhcp6_address_info_t);
670  vl_api_dhcp6_reply_event_t *event = clib_mem_alloc (event_size);
671  clib_memset (event, 0, event_size);
672 
673  event->sw_if_index = htonl (events[i].body.sw_if_index);
674  event->server_index = htonl (events[i].body.server_index);
675  event->msg_type = events[i].body.msg_type;
676  event->T1 = htonl (events[i].body.T1);
677  event->T2 = htonl (events[i].body.T2);
678  event->inner_status_code =
679  htons (events[i].body.inner_status_code);
680  event->status_code = htons (events[i].body.status_code);
681  event->preference = events[i].body.preference;
682 
683  event->n_addresses = htonl (vec_len (events[i].addresses));
684  vl_api_dhcp6_address_info_t *address =
685  (typeof (address)) event->addresses;
686  u32 j;
687  for (j = 0; j < vec_len (events[i].addresses); j++)
688  {
689  dhcp6_address_info_t *info = &events[i].addresses[j];
690  ip6_address_encode (&info->address, address->address);
691  address->valid_time = htonl (info->valid_time);
692  address->preferred_time = htonl (info->preferred_time);
693  address++;
694  }
695  vec_free (events[i].addresses);
696 
700 
702  /* *INDENT-OFF* */
703  pool_foreach(reg, vpe_api_main.dhcp6_reply_events_registrations,
704  ({
705  vl_api_registration_t *vl_reg;
706  vl_reg =
707  vl_api_client_index_to_registration (reg->client_index);
708  if (vl_reg && vl_api_can_send_msg (vl_reg))
709  {
710  vl_api_dhcp6_reply_event_t *msg =
711  vl_msg_api_alloc (event_size);
712  clib_memcpy (msg, event, event_size);
713  msg->_vl_msg_id = htons (VL_API_DHCP6_REPLY_EVENT + REPLY_MSG_ID_BASE);
714  msg->client_index = reg->client_index;
715  msg->pid = reg->client_pid;
716  vl_api_send_msg (vl_reg, (u8 *) msg);
717  }
718  }));
719  /* *INDENT-ON* */
720 
721  clib_mem_free (event);
722  }
723  }
724  vlib_process_put_event_data (vm, event_data);
725  }
726 
727  return 0;
728 }
729 
730 /* *INDENT-OFF* */
732  .function = dhcp6_reply_process,
733  .type = VLIB_NODE_TYPE_PROCESS,
734  .name = "dhcp6-reply-publisher-process",
735 };
736 /* *INDENT-ON* */
737 
738 static clib_error_t *
740  _vnet_dhcp6_pd_reply_event_function_list_elt_t
741  * elt)
742 {
743  clib_error_t *error = 0;
744 
745  while (elt)
746  {
747  error = elt->fp (data);
748  if (error)
749  return error;
750  elt = elt->next_dhcp6_pd_reply_event_function;
751  }
752 
753  return error;
754 }
755 
756 static uword
758  vlib_frame_t * f)
759 {
760  /* These cross the longjmp boundary (vlib_process_wait_for_event)
761  * and need to be volatile - to prevent them from being optimized into
762  * a register - which could change during suspension */
763 
764  while (1)
765  {
767  uword event_type = DHCP6_PD_DP_REPLY_REPORT;
768  void *event_data = vlib_process_get_event_data (vm, &event_type);
769 
770  int i;
771  if (event_type == DHCP6_PD_DP_REPLY_REPORT)
772  {
773  prefix_report_t *events = event_data;
774  for (i = 0; i < vec_len (events); i++)
775  {
776  u32 event_size =
778  vec_len (events[i].prefixes) *
779  sizeof (vl_api_dhcp6_pd_prefix_info_t);
781  clib_mem_alloc (event_size);
782  clib_memset (event, 0, event_size);
783 
784  event->sw_if_index = htonl (events[i].body.sw_if_index);
785  event->server_index = htonl (events[i].body.server_index);
786  event->msg_type = events[i].body.msg_type;
787  event->T1 = htonl (events[i].body.T1);
788  event->T2 = htonl (events[i].body.T2);
789  event->inner_status_code =
790  htons (events[i].body.inner_status_code);
791  event->status_code = htons (events[i].body.status_code);
792  event->preference = events[i].body.preference;
793 
794  event->n_prefixes = htonl (vec_len (events[i].prefixes));
795  vl_api_dhcp6_pd_prefix_info_t *prefix =
796  (typeof (prefix)) event->prefixes;
797  u32 j;
798  for (j = 0; j < vec_len (events[i].prefixes); j++)
799  {
800  dhcp6_prefix_info_t *info = &events[i].prefixes[j];
801  ip6_address_encode (&info->prefix, prefix->prefix.address);
802  prefix->prefix.len = info->prefix_length;
803  prefix->valid_time = htonl (info->valid_time);
804  prefix->preferred_time = htonl (info->preferred_time);
805  prefix++;
806  }
807  vec_free (events[i].prefixes);
808 
812 
814  /* *INDENT-OFF* */
815  pool_foreach(reg, vpe_api_main.dhcp6_pd_reply_events_registrations,
816  ({
817  vl_api_registration_t *vl_reg;
818  vl_reg =
819  vl_api_client_index_to_registration (reg->client_index);
820  if (vl_reg && vl_api_can_send_msg (vl_reg))
821  {
822  vl_api_dhcp6_pd_reply_event_t *msg =
823  vl_msg_api_alloc (event_size);
824  clib_memcpy (msg, event, event_size);
825  msg->_vl_msg_id = htons (VL_API_DHCP6_PD_REPLY_EVENT + REPLY_MSG_ID_BASE);
826  msg->client_index = reg->client_index;
827  msg->pid = reg->client_pid;
828  vl_api_send_msg (vl_reg, (u8 *) msg);
829  }
830  }));
831  /* *INDENT-ON* */
832 
833  clib_mem_free (event);
834  }
835  }
836  vlib_process_put_event_data (vm, event_data);
837  }
838 
839  return 0;
840 }
841 
842 /* *INDENT-OFF* */
843 VLIB_REGISTER_NODE (dhcp6_pd_reply_process_node) = {
844  .function = dhcp6_pd_reply_process,
845  .type = VLIB_NODE_TYPE_PROCESS,
846  .name = "dhcp6-pd-reply-publisher-process",
847 };
848 /* *INDENT-ON* */
849 
850 /*
851  * dhcp_api_hookup
852  * Add vpe's API message handlers to the table.
853  * vlib has already mapped shared memory and
854  * added the client registration handlers.
855  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
856  */
857 #include <dhcp/dhcp.api.c>
858 
859 static clib_error_t *
861 {
862  /*
863  * Set up the (msg_name, crc, message-id) table
864  */
865  dhcp_base_msg_id = setup_message_id_table ();
866 
867  dhcp6_pd_set_publisher_node (dhcp6_pd_reply_process_node.index,
871 
872  return 0;
873 }
874 
876 
877 #include <vlib/unix/plugin.h>
878 #include <vpp/app/version.h>
879 
880 /* *INDENT-OFF* */
882  .version = VPP_BUILD_VER,
883  .description = "Dynamic Host Configuration Protocol (DHCP)",
884 };
885 /* *INDENT-ON* */
886 
887 /*
888  * fd.io coding-style-patch-verification: ON
889  *
890  * Local Variables:
891  * eval: (c-set-style "gnu")
892  * End:
893  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:507
Send DHCPv6 PD client message of specified type.
Definition: dhcp.api:388
Enable/disable listening on DHCPv6 client port.
Definition: dhcp.api:297
u8 count
Definition: dhcp.api:208
DHCP Proxy set / unset vss request.
Definition: dhcp.api:132
Set DHCPv6 DUID-LL.
Definition: dhcp.api:286
vl_api_dhcp_lease_t lease
Definition: dhcp.api:244
#define vec_foreach_index(var, v)
Iterate over vector indices.
static dhcp_vss_t * dhcp_get_vss_info(dhcp_proxy_main_t *dm, u32 rx_fib_index, fib_protocol_t proto)
Get the VSS data for the FIB index.
Definition: dhcp_proxy.h:255
#define hash_set(h, key, value)
Definition: hash.h:255
#define clib_min(x, y)
Definition: clib.h:319
vl_api_address_t dhcp_src_address
Definition: dhcp.api:118
vl_api_dhcpv6_msg_type_t msg_type
Definition: dhcp.api:399
#define hash_unset(h, key)
Definition: hash.h:261
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:593
static clib_error_t * dhcp_api_hookup(vlib_main_t *vm)
Definition: dhcp_api.c:860
#define VSS_TYPE_INVALID
Definition: dhcp_proxy.h:68
ip4_address_t router_address
The address of this client&#39;s default gateway - may not be present.
Definition: client.h:60
DHCP Client details returned from dump.
Definition: dhcp.api:240
static void vl_api_dhcp6_duid_ll_set_t_handler(vl_api_dhcp6_duid_ll_set_t *mp)
Definition: dhcp_api.c:88
dhcp_server_t * dhcp_servers
The set of DHCP servers to which messages are relayed.
Definition: dhcp_proxy.h:111
ip_dscp_t dscp
Definition: client.h:114
#define REPLY_MACRO2(t, body)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
dhcp_proxy_main_t dhcp_proxy_main
Shard 4/6 instance of DHCP main.
Definition: dhcp_proxy.c:25
_vnet_dhcp6_reply_event_function_list_elt_t * functions
int dhcp6_proxy_set_server(ip46_address_t *addr, ip46_address_t *src_addr, u32 rx_table_id, u32 server_table_id, int is_del)
static void vl_api_send_msg(vl_api_registration_t *rp, u8 *elem)
Definition: api.h:35
void ip6_address_decode(const vl_api_ip6_address_t in, ip6_address_t *out)
Definition: ip_types_api.c:117
ip46_address_t dhcp_src_address
The source address to use in relayed messaes.
Definition: dhcp_proxy.h:126
The Virtual Sub-net Selection information for a given RX FIB.
Definition: dhcp_proxy.h:57
vl_api_address_t src
Definition: gre.api:54
dhcp6_pd_send_client_message_params_prefix_t * prefixes
for(i=1;i<=collision_buckets;i++)
u32 sw_if_index
Definition: client.h:68
void dhcp_send_details(fib_protocol_t proto, void *opaque, u32 context, dhcp_proxy_t *proxy)
Send the details of a proxy session to the API client during a dump.
Definition: dhcp_api.c:176
u32 rx_fib_index
The FIB index (not the external Table-ID) in which the client is resides.
Definition: dhcp_proxy.h:132
void dhcp6_pd_send_client_message(vlib_main_t *vm, u32 sw_if_index, u8 stop, dhcp6_pd_send_client_message_params_t *params)
static uword dhcp6_reply_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: dhcp_api.c:647
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
void vl_api_dhcp6_pd_send_client_message_t_handler(vl_api_dhcp6_pd_send_client_message_t *mp)
Definition: dhcp_api.c:575
static u32 dhcp_base_msg_id
Base message ID fot the plugin.
Definition: dhcp_api.c:41
dhcp_client_fwd_addresses_t installed
Definition: client.h:86
vl_api_prefix_t prefix
Definition: ip.api:144
u8 vss_type
VSS type as defined in RFC 6607: 0 for NVT ASCII VPN Identifier 1 for RFC 2685 VPN-ID of 7 octects - ...
Definition: dhcp_proxy.h:65
static void vl_api_dhcp_client_dump_t_handler(vl_api_dhcp_client_dump_t *mp)
Definition: dhcp_api.c:399
dhcp_client_state_t state
Definition: client.h:65
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:252
void * vl_msg_api_alloc(int nbytes)
vhost_vring_addr_t addr
Definition: vhost_user.h:254
unsigned char u8
Definition: types.h:56
void dhcp6_set_publisher_node(uword node_index, uword event_type)
static clib_error_t * call_dhcp6_reply_event_callbacks(void *data, _vnet_dhcp6_reply_event_function_list_elt_t *elt)
Definition: dhcp_api.c:629
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
ip_dscp_t ip_dscp_decode(vl_api_ip_dscp_t in)
Definition: ip_types_api.c:99
Dump the DHCP client configurations.
Definition: dhcp.api:230
#define clib_memcpy(d, s, n)
Definition: string.h:180
void dhcp_proxy_dump(fib_protocol_t proto, void *opaque, u32 context)
Dump the proxy configs to the API.
Definition: dhcp_proxy.c:248
void vl_api_want_dhcp6_reply_events_t_handler(vl_api_want_dhcp6_reply_events_t *mp)
Definition: dhcp_api.c:428
vl_api_dhcp_client_t client
Definition: dhcp.api:243
u32 vl_msg_api_max_length(void *mp)
Definition: api_shared.c:880
vl_api_dhcp_server_t servers[count]
Definition: dhcp.api:278
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
static void vl_api_dhcp_proxy_config_t_handler(vl_api_dhcp_proxy_config_t *mp)
Definition: dhcp_api.c:126
#define DHCP_PLUGIN_VERSION_MINOR
Definition: dhcp_api.c:47
static int send_dhcp_client_entry(const dhcp_client_t *client, void *arg)
Definition: dhcp_api.c:371
Send DHCPv6 client message of specified type.
Definition: dhcp.api:349
dhcp_event_cb_t event_callback
Definition: client.h:116
static void vl_api_dhcp_plugin_get_version_t_handler(vl_api_dhcp_plugin_get_version_t *mp)
Definition: dhcp_api.c:50
void dhcp6_pd_set_publisher_node(uword node_index, uword event_type)
#define VSS_TYPE_ASCII
Definition: dhcp_proxy.h:66
unsigned int u32
Definition: types.h:88
void vl_api_dhcp6_send_client_message_t_handler(vl_api_dhcp6_send_client_message_t *mp)
Definition: dhcp_api.c:525
ip46_type_t ip_address_decode(const vl_api_address_t *in, ip46_address_t *out)
Decode/Encode for struct/union types.
Definition: ip_types_api.c:160
u8 set_broadcast_flag
Definition: client.h:106
u32 server_fib_index
The FIB index (not the external Table-ID) in which the server is reachable.
Definition: dhcp_proxy.h:95
vl_api_ip_dscp_t dscp
Definition: dhcp.api:163
#define hash_get(h, key)
Definition: hash.h:249
#define DHCP_PLUGIN_VERSION_MAJOR
Definition: dhcp_api.c:46
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
struct dhcp_client_send_walk_ctx_t_ dhcp_client_send_walk_ctx_t
vl_api_ip_proto_t proto
Definition: acl_types.api:50
long ctx[MAX_CONNS]
Definition: main.c:144
ip4_address_t leased_address
the address assigned to this client and it&#39;s mask
Definition: client.h:52
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
dhcp6_pd_client_public_main_t dhcp6_pd_client_public_main
vl_api_dhcpv6_msg_type_t msg_type
Definition: dhcp.api:360
#define REPLY_MACRO(t)
static void vl_api_dhcp_proxy_dump_t_handler(vl_api_dhcp_proxy_dump_t *mp)
Definition: dhcp_api.c:163
int dhcp_proxy_set_vss(fib_protocol_t proto, u32 tbl_id, u8 vss_type, u8 *vpn_ascii_id, u32 oui, u32 vpn_index, u8 is_del)
Configure/set a new VSS info.
Definition: dhcp_proxy.c:309
Control ping from client to api server request.
Definition: dhcp.api:80
static void dhcp_client_data_encode(vl_api_dhcp_client_t *vclient, const dhcp_client_t *client)
Definition: dhcp_api.c:290
vlib_main_t * vm
Definition: in2out_ed.c:1599
u8 client_hardware_address[6]
Definition: client.h:108
dhcpv6_duid_ll_string_t client_duid
static clib_error_t * call_dhcp6_pd_reply_event_callbacks(void *data, _vnet_dhcp6_pd_reply_event_function_list_elt_t *elt)
Definition: dhcp_api.c:739
u8 len
Definition: ip_types.api:92
dhcp6_ia_na_client_public_main_t dhcp6_ia_na_client_public_main
_vnet_dhcp6_pd_reply_event_function_list_elt_t * functions
static void vl_api_dhcp_plugin_control_ping_t_handler(vl_api_dhcp_plugin_control_ping_t *mp)
Definition: dhcp_api.c:73
An API client registration, only in vpp/vlib.
Definition: api_common.h:47
#define BAD_SW_IF_INDEX_LABEL
vl_api_vss_type_t vss_type
Definition: dhcp.api:137
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u8 * vpn_ascii_id
Type 0 ASCII VPN Identifier.
Definition: dhcp_proxy.h:77
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:92
dhcp6_send_client_message_params_address_t * addresses
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
ip4_address_t * domain_server_address
Definition: client.h:90
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
static void dhcp_compl_event_callback(u32 client_index, const dhcp_client_t *client)
Definition: dhcp_api.c:315
#define clib_warning(format, args...)
Definition: error.h:59
string vss_vpn_ascii_id[129]
Definition: dhcp.api:275
vl_api_registration_t * reg
Definition: dhcp_api.c:366
A representation of a single DHCP Server within a given VRF config.
Definition: dhcp_proxy.h:83
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:57
int dhcp4_proxy_set_server(ip46_address_t *addr, ip46_address_t *src_addr, u32 rx_table_id, u32 server_table_id, int is_del)
ip46_address_t dhcp_server
The address of the DHCP server to which to relay the client&#39;s messages.
Definition: dhcp_proxy.h:89
manual_print typedef address
Definition: ip_types.api:85
vl_api_ip_dscp_t ip_dscp_encode(ip_dscp_t dscp)
Definition: ip_types_api.c:105
u8 data[128]
Definition: ipsec_types.api:89
enum ip_dscp_t_ ip_dscp_t
dhcp6_report_common_t body
VLIB_API_INIT_FUNCTION(dhcp_api_hookup)
static void clib_mem_free(void *p)
Definition: mem.h:215
static void vl_api_dhcp6_clients_enable_disable_t_handler(vl_api_dhcp6_clients_enable_disable_t *mp)
Definition: dhcp_api.c:416
#define REPLY_MSG_ID_BASE
Definition: dhcp_api.c:42
void dhcp_client_walk(dhcp_client_walk_cb_t cb, void *ctx)
Walk (visit each) DHCP client configuration.
Definition: client.c:1111
Tell client about a DHCPv6 PD server reply event.
Definition: dhcp.api:490
void ip6_address_encode(const ip6_address_t *in, vl_api_ip6_address_t out)
Definition: ip_types_api.c:111
void dhcp6_send_client_message(vlib_main_t *vm, u32 sw_if_index, u8 stop, dhcp6_send_client_message_params_t *params)
vl_api_dhcp_lease_t lease
Definition: dhcp.api:221
static void * clib_mem_alloc(uword size)
Definition: mem.h:157
vl_api_dhcp6_pd_prefix_info_t prefixes[n_prefixes]
Definition: dhcp.api:403
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static uword dhcp6_pd_reply_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: dhcp_api.c:757
Tell client about a DHCP completion event.
Definition: dhcp.api:267
Register for DHCPv6 PD reply events.
Definition: dhcp.api:436
Tell client about a DHCPv6 server reply event.
Definition: dhcp.api:459
vl_api_address_t dhcp_src_address
Definition: dhcp.api:276
A DHCP proxy representation fpr per-client VRF config.
Definition: dhcp_proxy.h:101
Reply to get the plugin version.
Definition: dhcp.api:69
vl_api_interface_index_t sw_if_index
Definition: dhcp.api:353
u8 * client_identifier
Definition: client.h:99
static void * vlib_process_get_event_data(vlib_main_t *vm, uword *return_event_type_opaque)
Definition: node_funcs.h:463
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u8 vpn_id[7]
Type 1 VPN-ID.
Definition: dhcp_proxy.h:73
vl_api_address_t dhcp_server
Definition: dhcp.api:117
Get the plugin version.
Definition: dhcp.api:57
vl_api_interface_index_t sw_if_index
Definition: dhcp.api:392
u64 uword
Definition: types.h:112
dhcp6_address_info_t * addresses
vl_api_dhcp6_address_info_t addresses[n_addresses]
Definition: dhcp.api:364
vl_api_dhcp_client_t client
Definition: dhcp.api:178
#define VSS_TYPE_VPN_ID
Definition: dhcp_proxy.h:67
static void vl_api_dhcp_client_config_t_handler(vl_api_dhcp_client_config_t *mp)
Definition: dhcp_api.c:335
Register for DHCPv6 reply events.
Definition: dhcp.api:422
fib_table_t * fib_table_get(fib_node_index_t index, fib_protocol_t proto)
Get a pointer to a FIB table.
Definition: fib_table.c:29
void vl_api_want_dhcp6_pd_reply_events_t_handler(vl_api_want_dhcp6_pd_reply_events_t *mp)
Definition: dhcp_api.c:476
static void vl_api_dhcp_proxy_set_vss_t_handler(vl_api_dhcp_proxy_set_vss_t *mp)
Definition: dhcp_api.c:107
void dhcp6_clients_enable_disable(u8 enable)
VLIB_PLUGIN_REGISTER()
Dump DHCP proxy table.
Definition: dhcp.api:251
u8 * hostname
Definition: client.h:98
Control ping from the client to the server response.
Definition: dhcp.api:92
static void vlib_process_put_event_data(vlib_main_t *vm, void *event_data)
Definition: node_funcs.h:500
vlib_node_registration_t dhcp6_reply_process_node
(constructor) VLIB_REGISTER_NODE (dhcp6_reply_process_node)
Definition: dhcp_api.c:731
static void setup_message_id_table(snat_main_t *sm, api_main_t *am)
Definition: nat_api.c:3256
string vpn_ascii_id[129]
Definition: dhcp.api:138
u32 dhcp_proxy_rx_table_get_table_id(fib_protocol_t proto, u32 fib_index)
Definition: dhcp_proxy.c:46
static void dhcp_client_lease_encode(vl_api_dhcp_lease_t *lease, const dhcp_client_t *client)
Definition: dhcp_api.c:259
vl_api_vss_type_t vss_type
Definition: dhcp.api:273
dhcp6_report_common_t body
vpe_api_main_t vpe_api_main
Definition: interface_api.c:54
Tell client about a DHCP completion event.
Definition: dhcp.api:217
dhcp6_prefix_info_t * prefixes
DHCP Client config add / del request.
Definition: dhcp.api:173
DHCP Proxy config add / del request.
Definition: dhcp.api:110
#define VALIDATE_SW_IF_INDEX(mp)
A protocol Independent FIB table.
Definition: fib_table.h:71
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 uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128