FD.io VPP  v20.05-21-gb1500e9ff
Vector Packet Processing
dhcp6_pd_client_cp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 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 
16 #include <vnet/vnet.h>
17 #include <vlibmemory/api.h>
18 #include <dhcp/dhcp6_packet.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/ip/ip6.h>
22 #include <vnet/ip/ip6_link.h>
23 #include <vnet/ip6-nd/ip6_ra.h>
24 #include <float.h>
25 #include <math.h>
26 #include <string.h>
27 #include <vnet/ip/ip_types_api.h>
28 
29 typedef struct
30 {
32  uword opaque_data; // used by prefix publisher
33  ip6_address_t prefix;
39 
40 typedef struct
41 {
42  u8 enabled;
44  u32 server_index;
45  u32 T1;
46  u32 T2;
47  f64 T1_due_time;
48  f64 T2_due_time;
50  u8 rebinding;
52 
53 typedef struct
54 {
59 
60  /* convenience */
66 
68 
69 typedef struct
70 {
73  /* vector of active prefix pool indicies, prep-H for pool_foreach(..) */
76 
78 
79 typedef struct
80 {
81  /* config */
84  ip6_address_t address;
86 
87  /* state */
90 
91 typedef struct
92 {
96 
98 
99 enum
100 {
103 };
104 
107 {
109 
110  if (prefix_group_index >=
112  return ~0;
113 
114  return apm->active_prefix_index_by_prefix_group_index[prefix_group_index];
115 }
116 
119  u32 prefix_index)
120 {
122  static const u32 empty = ~0;
123 
124  ASSERT (prefix_group_index != ~0);
125 
126  if (prefix_index == ~0
127  && prefix_group_index >=
129  return;
130 
132  prefix_group_index, empty);
133  apm->active_prefix_index_by_prefix_group_index[prefix_group_index] =
134  prefix_index;
135 }
136 
139 {
142  u32 prefix_index;
143 
144  prefix_index = prefix_info - pm->prefix_pool;
145  return clib_bitmap_get (rm->prefix_ownership_bitmap, prefix_index);
146 }
147 
150 {
153  u32 prefix_index;
154 
155  prefix_index = prefix_info - pm->prefix_pool;
157  clib_bitmap_set (rm->prefix_ownership_bitmap, prefix_index, value);
158 }
159 
160 static void
161 cp_ip6_address_prefix_add_del_handler (u32 prefix_index, u8 is_add);
162 
163 static void
164 notify_prefix_add_del (u32 prefix_index, u8 is_add)
165 {
166  // TODO: use registries
167  cp_ip6_address_prefix_add_del_handler (prefix_index, is_add);
168 }
169 
170 static void
172  u8 msg_type, prefix_info_t * prefix_list,
173  u8 start)
174 {
178  u32 i;
179 
180  ASSERT (sw_if_index < vec_len (rm->client_state_by_sw_if_index) &&
181  rm->client_state_by_sw_if_index[sw_if_index].enabled);
182  client_state_t *client_state =
184 
185  params.sw_if_index = sw_if_index;
186  params.server_index = server_index;
187  params.msg_type = msg_type;
188  if (start)
189  {
190  if (msg_type == DHCPV6_MSG_SOLICIT)
191  {
192  params.irt = 1;
193  params.mrt = 120;
194  }
195  else if (msg_type == DHCPV6_MSG_REQUEST)
196  {
197  params.irt = 1;
198  params.mrt = 30;
199  params.mrc = 10;
200  }
201  else if (msg_type == DHCPV6_MSG_RENEW)
202  {
203  params.irt = 10;
204  params.mrt = 600;
205  f64 current_time = vlib_time_now (rm->vlib_main);
206  i32 diff_time = client_state->T2 - current_time;
207  if (diff_time < 0)
208  diff_time = 0;
209  params.mrd = diff_time;
210  }
211  else if (msg_type == DHCPV6_MSG_REBIND)
212  {
213  params.irt = 10;
214  params.mrt = 600;
215  f64 current_time = vlib_time_now (rm->vlib_main);
216  i32 diff_time = rm->max_valid_due_time - current_time;
217  if (diff_time < 0)
218  diff_time = 0;
219  params.mrd = diff_time;
220  }
221  else if (msg_type == DHCPV6_MSG_RELEASE)
222  {
223  params.mrc = 1;
224  }
225  }
226 
227  params.T1 = 0;
228  params.T2 = 0;
229  if (vec_len (prefix_list) != 0)
230  vec_validate (prefixes, vec_len (prefix_list) - 1);
231  for (i = 0; i < vec_len (prefix_list); i++)
232  {
233  prefix_info_t *prefix = &prefix_list[i];
234  pref = &prefixes[i];
235  pref->valid_lt = prefix->valid_lt;
236  pref->preferred_lt = prefix->preferred_lt;
237  pref->prefix = prefix->prefix;
238  pref->prefix_length = prefix->prefix_length;
239  }
240  params.prefixes = prefixes;
241 
242  dhcp6_pd_send_client_message (rm->vlib_main, sw_if_index, !start, &params);
243 
244  vec_free (params.prefixes);
245 }
246 
247 static void interrupt_process (void);
248 
249 static u8
250 ip6_prefixes_equal (ip6_address_t * prefix1, ip6_address_t * prefix2, u8 len)
251 {
252  if (len >= 64)
253  {
254  if (prefix1->as_u64[0] != prefix2->as_u64[0])
255  return 0;
256  if (len == 64)
257  return 1;
258  return clib_net_to_host_u64 (prefix1->as_u64[1]) >> (128 - len) ==
259  clib_net_to_host_u64 (prefix2->as_u64[1]) >> (128 - len);
260  }
261  return clib_net_to_host_u64 (prefix1->as_u64[0]) >> (64 - len) ==
262  clib_net_to_host_u64 (prefix2->as_u64[0]) >> (64 - len);
263 }
264 
265 static clib_error_t *
267 {
270  vlib_main_t *vm = rm->vlib_main;
271  client_state_t *client_state;
272  ip6_address_t *prefix;
274  u32 n_prefixes;
275  vl_api_dhcp6_pd_prefix_info_t *api_prefix;
276  u32 inner_status_code;
277  u32 status_code;
278  u32 server_index;
279  f64 current_time;
280  clib_error_t *error = 0;
281  u32 i;
282  prefix_info_t *prefix_info;
283 
284  current_time = vlib_time_now (vm);
285 
286  sw_if_index = ntohl (mp->sw_if_index);
287 
288  if (sw_if_index >= vec_len (rm->client_state_by_sw_if_index))
289  return 0;
290 
291  client_state = &rm->client_state_by_sw_if_index[sw_if_index];
292 
293  if (!client_state->enabled)
294  return 0;
295 
296  server_index = ntohl (mp->server_index);
297 
298  n_prefixes = ntohl (mp->n_prefixes);
299 
300  inner_status_code = ntohs (mp->inner_status_code);
301  status_code = ntohs (mp->status_code);
302 
304  && client_state->server_index == ~0)
305  {
306  prefix_info_t *prefix_list = 0, *prefix_info;
307  u8 prefix_length;
308 
309  if (inner_status_code == DHCPV6_STATUS_NOPREFIX_AVAIL)
310  {
312  ("Advertise message arrived with NoPrefixAvail status code");
313  return 0;
314  }
315 
316  if (n_prefixes > 0)
317  vec_validate (prefix_list, n_prefixes - 1);
318  for (i = 0; i < n_prefixes; i++)
319  {
320  api_prefix = &mp->prefixes[i];
321  prefix = (ip6_address_t *) api_prefix->prefix.address;
322  prefix_length = api_prefix->prefix.len;
323 
324  prefix_info = &prefix_list[i];
325  prefix_info->prefix = *prefix;
326  prefix_info->prefix_length = prefix_length;
327  prefix_info->preferred_lt = 0;
328  prefix_info->valid_lt = 0;
329  }
330 
331  client_state->server_index = server_index;
332 
333  send_client_message_start_stop (sw_if_index, server_index,
334  DHCPV6_MSG_REQUEST, prefix_list, 1);
335  vec_free (prefix_list);
336  }
337 
338  if (mp->msg_type != DHCPV6_MSG_API_REPLY)
339  return 0;
340 
341  if (!client_state->rebinding && client_state->server_index != server_index)
342  {
343  clib_warning ("Reply message arrived with Server ID different "
344  "from that in Request or Renew message");
345  return 0;
346  }
347 
348  if (inner_status_code == DHCPV6_STATUS_NOPREFIX_AVAIL)
349  {
350  clib_warning ("Reply message arrived with NoPrefixAvail status code");
351  if (n_prefixes > 0)
352  {
354  ("Invalid Reply message arrived: It contains NoPrefixAvail "
355  "status code but also contains prefixes");
356  return 0;
357  }
358  }
359 
360  if (status_code == DHCPV6_STATUS_UNSPEC_FAIL)
361  {
362  clib_warning ("Reply message arrived with UnspecFail status code");
363  return 0;
364  }
365 
366  send_client_message_start_stop (sw_if_index, server_index,
367  mp->msg_type, 0, 0);
368 
370  /*
371  * We're going to loop through the pool multiple times,
372  * so collect active indices.
373  */
374  /* *INDENT-OFF* */
375  pool_foreach (prefix_info, pm->prefix_pool,
376  ({
377  vec_add1 (pm->indices, prefix_info - pm->prefix_pool);
378  }));
379  /* *INDENT-ON* */
380 
381  for (i = 0; i < n_prefixes; i++)
382  {
383  u8 prefix_length;
384  u32 valid_time;
386  int j;
387 
388  prefix_info = 0;
389  api_prefix = &mp->prefixes[i];
390 
391  prefix = (ip6_address_t *) api_prefix->prefix.address;
392  prefix_length = api_prefix->prefix.len;
393 
395  continue;
396 
397  valid_time = ntohl (api_prefix->valid_time);
398  preferred_time = ntohl (api_prefix->preferred_time);
399  prefix_length = api_prefix->prefix.len;
400 
401  if (preferred_time > valid_time)
402  continue;
403 
404  u8 address_prefix_present = 0;
405 
406  /* Look for a matching prefix_info */
407  for (j = 0; j < vec_len (pm->indices); j++)
408  {
409  prefix_info = pool_elt_at_index (pm->prefix_pool, pm->indices[j]);
410 
411  if (is_dhcpv6_pd_prefix (prefix_info) &&
412  prefix_info->opaque_data == sw_if_index &&
413  prefix_info->prefix_length == prefix_length &&
414  ip6_prefixes_equal (&prefix_info->prefix, prefix,
415  prefix_length))
416  {
417  address_prefix_present = 1;
418  break;
419  }
420  }
421 
422  if (address_prefix_present)
423  {
424  /* Found the (primary) prefix, update prefix timers */
425  prefix_info->preferred_lt = preferred_time;
426  prefix_info->valid_lt = valid_time;
427  prefix_info->due_time = current_time + valid_time;
428  if (prefix_info->due_time > rm->max_valid_due_time)
429  rm->max_valid_due_time = prefix_info->due_time;
430 
431  /*
432  * Tell the RA code to update any secondary per-interface
433  * timers that it might be hoarding.
434  */
436  (prefix, prefix_length,
437  prefix_info->opaque_data /* sw_if_index */ ,
438  valid_time, preferred_time);
439  continue;
440  }
441 
442  if (valid_time == 0)
443  continue;
444 
445  pool_get (pm->prefix_pool, prefix_info);
446  vec_add1 (pm->indices, prefix_info - pm->prefix_pool);
447  prefix_info->prefix_group_index = client_state->prefix_group_index;
448  set_is_dhcpv6_pd_prefix (prefix_info, 1);
449  prefix_info->opaque_data = sw_if_index;
450  prefix_info->prefix_length = prefix_length;
451  prefix_info->prefix = *prefix;
452  prefix_info->preferred_lt = preferred_time;
453  prefix_info->valid_lt = valid_time;
454  prefix_info->due_time = current_time + valid_time;
455  if (prefix_info->due_time > rm->max_valid_due_time)
456  rm->max_valid_due_time = prefix_info->due_time;
458 
459  u32 prefix_index = prefix_info - pm->prefix_pool;
460  notify_prefix_add_del (prefix_index, 1);
461  }
462 
463  client_state->server_index = server_index;
464  client_state->T1 = ntohl (mp->T1);
465  client_state->T2 = ntohl (mp->T2);
466  if (client_state->T1 != 0)
467  client_state->T1_due_time = current_time + client_state->T1;
468  if (client_state->T2 != 0)
469  client_state->T2_due_time = current_time + client_state->T2;
470  client_state->rebinding = 0;
471 
473 
474  return error;
475 }
476 
477 static prefix_info_t *
479 {
481  prefix_info_t *prefix_info, *prefix_list = 0;;
482 
483  /* *INDENT-OFF* */
484  pool_foreach (prefix_info, pm->prefix_pool,
485  ({
486  if (is_dhcpv6_pd_prefix (prefix_info) &&
487  prefix_info->opaque_data == sw_if_index)
488  {
489  u32 pos = vec_len (prefix_list);
490  vec_validate (prefix_list, pos);
491  clib_memcpy (&prefix_list[pos], prefix_info, sizeof (*prefix_info));
492  }
493  }));
494  /* *INDENT-ON* */
495 
496  return prefix_list;
497 }
498 
500 
501 static uword
503  vlib_frame_t * f)
504 {
507  prefix_info_t *prefix_info;
508  client_state_t *client_state;
509  f64 sleep_time = 1e9;
510  f64 current_time;
511  f64 due_time;
512  uword event_type;
513  uword *event_data = 0;
514  int i;
515 
516  while (1)
517  {
518  vlib_process_wait_for_event_or_clock (vm, sleep_time);
519  event_type = vlib_process_get_events (vm, &event_data);
520  vec_reset_length (event_data);
521 
522  if (event_type == DHCPV6_PD_EVENT_DISABLE)
523  {
524  vlib_node_set_state (vm, rm->node_index, VLIB_NODE_STATE_DISABLED);
525  sleep_time = 1e9;
526  continue;
527  }
528 
529  current_time = vlib_time_now (vm);
530  do
531  {
532  due_time = current_time + 1e9;
533  /* *INDENT-OFF* */
534  pool_foreach (prefix_info, pm->prefix_pool,
535  ({
536  if (is_dhcpv6_pd_prefix (prefix_info))
537  {
538  if (prefix_info->due_time > current_time)
539  {
540  if (prefix_info->due_time < due_time)
541  due_time = prefix_info->due_time;
542  }
543  else
544  {
545  u32 prefix_index = prefix_info - pm->prefix_pool;
546  notify_prefix_add_del (prefix_index, 0);
547  u32 sw_if_index = prefix_info->opaque_data;
548  set_is_dhcpv6_pd_prefix (prefix_info, 0);
549  pool_put (pm->prefix_pool, prefix_info);
550  client_state = &rm->client_state_by_sw_if_index[sw_if_index];
551  if (--client_state->prefix_count == 0)
552  {
553  client_state->rebinding = 0;
554  client_state->server_index = ~0;
555  send_client_message_start_stop (sw_if_index, ~0,
556  DHCPV6_MSG_SOLICIT,
557  0, 1);
558  }
559  }
560  }
561  }));
562  /* *INDENT-ON* */
563  for (i = 0; i < vec_len (rm->client_state_by_sw_if_index); i++)
564  {
566  if (cs->enabled && cs->server_index != ~0)
567  {
568  if (cs->T2_due_time > current_time)
569  {
570  if (cs->T2_due_time < due_time)
571  due_time = cs->T2_due_time;
572  if (cs->T1_due_time > current_time)
573  {
574  if (cs->T1_due_time < due_time)
575  due_time = cs->T1_due_time;
576  }
577  else
578  {
579  cs->T1_due_time = DBL_MAX;
580  prefix_info_t *prefix_list;
581  prefix_list = create_prefix_list (i);
584  prefix_list, 1);
585  vec_free (prefix_list);
586  }
587  }
588  else
589  {
590  cs->T2_due_time = DBL_MAX;
591  prefix_info_t *prefix_list;
592  prefix_list = create_prefix_list (i);
593  cs->rebinding = 1;
596  prefix_list, 1);
597  vec_free (prefix_list);
598  }
599  }
600  }
601  current_time = vlib_time_now (vm);
602  }
603  while (due_time < current_time);
604 
605  sleep_time = due_time - current_time;
606  }
607 
608  return 0;
609 }
610 
611 /* *INDENT-OFF* */
613  .function = dhcp6_pd_client_cp_process,
614  .type = VLIB_NODE_TYPE_PROCESS,
615  .name = "dhcp6-pd-client-cp-process",
616 };
617 /* *INDENT-ON* */
618 
619 static void
621 {
623  vlib_main_t *vm = rm->vlib_main;
624 
627 }
628 
629 static void
631 {
633  vlib_main_t *vm = rm->vlib_main;
634 
637 }
638 
639 static void
641 {
643  vlib_main_t *vm = rm->vlib_main;
644  vlib_node_t *node;
645 
646  node = vec_elt (vm->node_main.nodes, rm->node_index);
647 
648  vlib_node_set_state (vm, rm->node_index, VLIB_NODE_STATE_POLLING);
649  vlib_start_process (vm, node->runtime_index);
650 }
651 
652 static u32
653 cp_ip6_construct_address (ip6_address_info_t * address_info, u32 prefix_index,
654  ip6_address_t * r_addr)
655 {
658  u64 mask, addr0, pref;
659 
660  addr0 = clib_net_to_host_u64 (address_info->address.as_u64[0]);
661  prefix = &pm->prefix_pool[prefix_index];
662  if (prefix->prefix_length > 64)
663  {
664  clib_warning ("Prefix length is bigger that 64 bits");
665  return 1;
666  }
667  mask = ((u64) 1 << (64 - prefix->prefix_length)) - 1;
668  addr0 &= mask;
669  pref = clib_host_to_net_u64 (prefix->prefix.as_u64[0]);
670  pref &= ~mask;
671  addr0 |= pref;
672  r_addr->as_u64[0] = clib_host_to_net_u64 (addr0);
673  r_addr->as_u64[1] = address_info->address.as_u64[1];
674 
675  return 0;
676 }
677 
678 static void
680 {
682  u32 prefix_index;
683  ip6_address_t addr;
684  clib_error_t *error;
685 
686  if (address_info->prefix_group_index != ~0)
687  prefix_index =
689  (address_info->prefix_group_index);
690  else
691  prefix_index = ~0;
692 
693  if (is_add && !address_info->configured_in_data_plane)
694  {
695  if (prefix_index != ~0)
696  {
697  if (cp_ip6_construct_address (address_info, prefix_index, &addr) !=
698  0)
699  return;
700  error =
701  ip6_add_del_interface_address (vm, address_info->sw_if_index,
702  &addr, address_info->prefix_length,
703  0 /* add */ );
704  if (error)
705  clib_warning ("Failed adding IPv6 address: %U",
706  format_clib_error, error);
707  else
708  {
709  if (CLIB_DEBUG > 0)
710  clib_warning ("Add address %U on %U",
712  &addr, address_info->prefix_length,
714  vnet_get_main (), address_info->sw_if_index);
715 
716  address_info->configured_in_data_plane = 1;
717  }
718  }
719  else
720  {
721  if (address_info->prefix_group_index == ~0)
722  {
723  error =
724  ip6_add_del_interface_address (vm, address_info->sw_if_index,
725  &address_info->address,
726  address_info->prefix_length,
727  0 /* add */ );
728  if (error)
729  clib_warning ("Failed adding IPv6 address: %U",
730  format_clib_error, error);
731  else
732  {
733  if (CLIB_DEBUG > 0)
734  clib_warning ("Add address %U on %U",
736  &addr, address_info->prefix_length,
738  vnet_get_main (),
739  address_info->sw_if_index);
740 
741  address_info->configured_in_data_plane = 1;
742  }
743  }
744  }
745  }
746  else if (!is_add && address_info->configured_in_data_plane)
747  {
748  if (prefix_index == ~0)
749  {
750  if (address_info->prefix_group_index == ~0)
751  {
752  error =
753  ip6_add_del_interface_address (vm, address_info->sw_if_index,
754  &address_info->address,
755  address_info->prefix_length,
756  1 /* del */ );
757  if (error)
758  clib_warning ("Failed deleting IPv6 address: %U",
759  format_clib_error, error);
760  address_info->configured_in_data_plane = 0;
761  }
762  else
763  clib_warning ("Deleting address with prefix "
764  "but active prefix index is not set");
765  }
766  else
767  {
768  if (cp_ip6_construct_address (address_info, prefix_index, &addr) !=
769  0)
770  return;
771  error =
772  ip6_add_del_interface_address (vm, address_info->sw_if_index,
773  &addr, address_info->prefix_length,
774  1 /* del */ );
775  if (error)
776  clib_warning ("Failed deleting IPv6 address: %U",
777  format_clib_error, error);
778  address_info->configured_in_data_plane = 0;
779  }
780  }
781 }
782 
783 static u32
785  u32 ignore_prefix_index)
786 {
788  prefix_info_t *prefix_info;
789 
790  /* *INDENT-OFF* */
791  pool_foreach (prefix_info, pm->prefix_pool,
792  ({
793  if (prefix_info->prefix_group_index == prefix_group_index &&
794  prefix_info - pm->prefix_pool != ignore_prefix_index)
795  return prefix_info - pm->prefix_pool;
796  }));
797  /* *INDENT-ON* */
798  return ~0;
799 }
800 
801 static void
803  ip6_address_info_t * address_info, int enable)
804 {
806  ip6_main_t *im = &ip6_main;
807  u32 prefix_index;
808  ip6_address_t addr;
809  int rv;
810 
811  prefix_index =
813  (address_info->prefix_group_index);
814 
815  if (cp_ip6_construct_address (address_info, prefix_index, &addr) != 0)
816  {
817  clib_warning ("address construction FAIL");
818  return;
819  }
820 
821  /* The RA code assumes that host bits are zero, so clear them */
822  addr.as_u64[0] &= im->fib_masks[address_info->prefix_length].as_u64[0];
823  addr.as_u64[1] &= im->fib_masks[address_info->prefix_length].as_u64[1];
824 
825  rv = ip6_ra_prefix (vm, address_info->sw_if_index,
826  &addr, address_info->prefix_length,
827  0 /* use_default */ ,
828  prefix_info->valid_lt,
829  prefix_info->preferred_lt, 0 /* no_advertise */ ,
830  0 /* off_link */ ,
831  0 /* no_autoconfig */ ,
832  0 /* no_onlink */ ,
833  enable == 0 /* is_no */ );
834  if (rv != 0)
835  {
836  clib_warning ("ip6_neighbor_ra_prefix returned %d", rv);
837  return;
838  }
839 
840  if (CLIB_DEBUG > 0)
841  clib_warning ("Advertise prefix %U valid lt %u preferred lt %u",
843  address_info->prefix_length, prefix_info->valid_lt,
844  prefix_info->preferred_lt);
845 }
846 
847 
848 static void
850 {
853  ip6_address_info_t *address_info;
855  u32 new_prefix_index;
856  u32 prefix_group_index;
857  u32 i;
858 
859  prefix = &pm->prefix_pool[prefix_index];
860  prefix_group_index = prefix->prefix_group_index;
861 
862  if (is_add)
863  {
865  (prefix_group_index) == ~0)
866  {
868  (prefix_group_index, prefix_index);
869  for (i = 0; i < vec_len (apm->addresses); i++)
870  {
871  address_info = &apm->addresses[i];
872  if (address_info->prefix_group_index == prefix_group_index)
873  {
874  /* Add the prefix to the interface */
875  cp_ip6_address_add_del_now (address_info, 1 /* add */ );
876  /* And advertise the prefix on the interface */
877  cp_ip6_advertise_prefix (prefix, address_info,
878  1 /* enable */ );
879  }
880  }
881  }
882  }
883  else
884  {
886  (prefix_group_index) == prefix_index)
887  {
888  for (i = 0; i < vec_len (apm->addresses); i++)
889  {
890  address_info = &apm->addresses[i];
891  if (address_info->prefix_group_index == prefix_group_index)
892  {
893  cp_ip6_advertise_prefix (prefix, address_info,
894  0 /* enable */ );
895  cp_ip6_address_add_del_now (address_info, 0 /* del */ );
896  }
897  }
899  (prefix_group_index, ~0);
900  new_prefix_index =
901  cp_ip6_address_find_new_active_prefix (prefix_group_index,
902  prefix_index);
903  if (new_prefix_index != ~0)
904  {
906  (prefix_group_index, new_prefix_index);
907  for (i = 0; i < vec_len (apm->addresses); i++)
908  {
909  address_info = &apm->addresses[i];
910  if (address_info->prefix_group_index == prefix_group_index)
911  {
912  cp_ip6_address_add_del_now (address_info, 1 /* add */ );
913  cp_ip6_advertise_prefix (prefix, address_info,
914  1 /* enable */ );
915  }
916  }
917  }
918  }
919  }
920 }
921 
922 static u32
924 {
926  u32 free_index = ~0;
927  u8 *name_dup;
928  u32 i;
929 
930  for (i = 0; i < vec_len (pm->prefix_group_name_by_index); i++)
931  {
932  if (pm->prefix_group_name_by_index[i] == 0)
933  free_index = i;
934  else if (0 ==
935  strcmp ((const char *) pm->prefix_group_name_by_index[i],
936  (const char *) name))
937  return i;
938  }
939  if (!create)
940  return ~0;
941  name_dup = (u8 *) strdup ((const char *) name);
942  if (free_index != ~0)
943  {
944  pm->prefix_group_name_by_index[free_index] = name_dup;
945  return free_index;
946  }
947  else
948  {
949  vec_add1 (pm->prefix_group_name_by_index, name_dup);
950  return vec_len (pm->prefix_group_name_by_index) - 1;
951  }
952 }
953 
954 int
956  ip6_address_t address, u8 prefix_length,
957  u8 is_add)
958 {
959 
961  vnet_main_t *vnm = vnet_get_main ();
962  ip6_address_info_t *address_info;
963  u32 prefix_group_index;
964  u32 n;
965 
966  if (!vnet_sw_interface_is_api_valid (vnm, sw_if_index))
967  {
968  clib_warning ("Invalid sw_if_index");
969  return VNET_API_ERROR_INVALID_VALUE;
970  }
971 
972  if (prefix_group != 0 && prefix_group[0] != '\0')
973  {
974  if (strnlen ((const char *) prefix_group, 64) == 64)
975  return VNET_API_ERROR_INVALID_VALUE;
976 
977  prefix_group_index = prefix_group_find_or_create (prefix_group, 1);
978  }
979  else
980  prefix_group_index = ~0;
981 
982  n = vec_len (apm->addresses);
983 
984  vec_foreach (address_info, apm->addresses)
985  {
986  if (address_info->sw_if_index == sw_if_index &&
987  address_info->prefix_group_index == prefix_group_index &&
988  address_info->prefix_length == prefix_length &&
989  0 == memcmp (&address_info->address, &address, 16))
990  {
991  if (is_add)
992  return VNET_API_ERROR_DUPLICATE_IF_ADDRESS;
993  cp_ip6_address_add_del_now (address_info, 0 /* del */ );
994  *address_info = apm->addresses[n - 1];
995  _vec_len (apm->addresses) = n - 1;
996  return 0;
997  }
998  }
999 
1000  if (!is_add)
1001  return VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
1002 
1003  vec_validate (apm->addresses, n);
1004  address_info = &apm->addresses[n];
1005  address_info->sw_if_index = sw_if_index;
1006  address_info->prefix_group_index = prefix_group_index;
1007  address_info->address = address;
1008  address_info->prefix_length = prefix_length;
1009  cp_ip6_address_add_del_now (address_info, 1 /* add */ );
1010 
1011  return 0;
1012 }
1013 
1014 static clib_error_t *
1016  unformat_input_t * input,
1017  vlib_cli_command_t * cmd)
1018 {
1019  vnet_main_t *vnm = vnet_get_main ();
1020  clib_error_t *error = 0;
1021  u32 sw_if_index = ~0;
1022  u8 *prefix_group = 0;
1023  ip6_address_t address;
1024  u32 prefix_length;
1025  u8 address_set = 0;
1026  u8 add = 1;
1027  unformat_input_t _line_input, *line_input = &_line_input;
1028 
1029  if (!unformat_user (input, unformat_line_input, line_input))
1030  return 0;
1031 
1032  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1033  {
1034  if (unformat
1035  (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index));
1036  else if (unformat (line_input, "prefix group %s", &prefix_group));
1037  else
1038  if (unformat (line_input, "%U/%d", unformat_ip6_address,
1039  &address, &prefix_length))
1040  address_set = 1;
1041  else if (unformat (line_input, "del"))
1042  add = 0;
1043  else
1044  {
1045  error = clib_error_return (0, "unexpected input `%U'",
1046  format_unformat_error, line_input);
1047  unformat_free (line_input);
1048  goto done;
1049  }
1050  }
1051 
1052  unformat_free (line_input);
1053 
1054  if (sw_if_index == ~0)
1055  error = clib_error_return (0, "Missing sw_if_index");
1056  else if (address_set == 0)
1057  error = clib_error_return (0, "Missing address");
1058  else
1059  {
1061  (sw_if_index, prefix_group, address, prefix_length, add) != 0)
1062  error = clib_error_return (0, "Error adding or removing address");
1063  }
1064 
1065 done:
1066  return error;
1067 }
1068 
1069 /*?
1070  * This command is used to add/delete IPv6 address
1071  * potentially using available prefix from specified prefix group
1072  *
1073  * @cliexpar
1074  * @parblock
1075  * Example of how to add IPv6 address:
1076  * @cliexcmd{set ip6 address GigabitEthernet2/0/0
1077  * prefix group my-prefix-group ::7/64}
1078  * Example of how to delete IPv6 address:
1079  * @cliexcmd{set ip6 address GigabitEthernet2/0/0
1080  * prefix group my-prefix-group ::7/64 del}
1081  * @endparblock
1082 ?*/
1083 /* *INDENT-OFF* */
1084 VLIB_CLI_COMMAND (ip6_address_add_del_command, static) = {
1085  .path = "set ip6 address",
1086  .short_help = "set ip6 address <interface> [prefix group <string>] "
1087  "<address> [del]",
1089 };
1090 /* *INDENT-ON* */
1091 
1092 static clib_error_t *
1094  unformat_input_t * input,
1095  vlib_cli_command_t * cmd)
1096 {
1099  ip6_address_info_t *address_info;
1100  const u8 *prefix_group;
1101  clib_error_t *error = 0;
1102  int i;
1103 
1104  for (i = 0; i < vec_len (apm->addresses); i++)
1105  {
1106  address_info = &apm->addresses[i];
1107  if (address_info->prefix_group_index == ~0)
1108  prefix_group = (const u8 *) "NONE";
1109  else
1110  prefix_group =
1112  vlib_cli_output (vm,
1113  "sw_if_index: %u, prefix_group: %s, address: %U/%d",
1114  address_info->sw_if_index, prefix_group,
1115  format_ip6_address, &address_info->address,
1116  address_info->prefix_length);
1117  }
1118 
1119  return error;
1120 }
1121 
1122 /* *INDENT-OFF* */
1123 VLIB_CLI_COMMAND (ip6_addresses_show_command, static) = {
1124  .path = "show ip6 addresses",
1125  .short_help = "show ip6 addresses",
1127 };
1128 /* *INDENT-ON* */
1129 
1130 static clib_error_t *
1132  unformat_input_t * input,
1133  vlib_cli_command_t * cmd)
1134 {
1136  clib_error_t *error = 0;
1137  prefix_info_t *prefix_info;
1138  const u8 *prefix_group;
1139  f64 current_time = vlib_time_now (vm);
1140 
1141  /* *INDENT-OFF* */
1142  pool_foreach (prefix_info, pm->prefix_pool,
1143  ({
1144  prefix_group =
1145  pm->prefix_group_name_by_index[prefix_info->prefix_group_index];
1146  vlib_cli_output (vm, "opaque_data: %lu, prefix: %U/%d, prefix group: %s, "
1147  "preferred lifetime: %u, valid lifetime: %u "
1148  "(%f remaining)",
1149  prefix_info->opaque_data, format_ip6_address,
1150  &prefix_info->prefix, prefix_info->prefix_length,
1151  prefix_group,
1152  prefix_info->preferred_lt, prefix_info->valid_lt,
1153  prefix_info->due_time - current_time);
1154  }));
1155  /* *INDENT-ON* */
1156 
1157  return error;
1158 }
1159 
1160 /* *INDENT-OFF* */
1161 VLIB_CLI_COMMAND (ip6_prefixes_show_command, static) = {
1162  .path = "show ip6 prefixes",
1163  .short_help = "show ip6 prefixes",
1165 };
1166 /* *INDENT-ON* */
1167 
1168 static clib_error_t *
1170  unformat_input_t * input,
1171  vlib_cli_command_t * cmd)
1172 {
1175  clib_error_t *error = 0;
1176  client_state_t *cs;
1177  f64 current_time = vlib_time_now (vm);
1178  const u8 *prefix_group;
1179  u8 *buf1 = 0;
1180  u8 *buf2 = 0;
1181  const char *rebinding;
1182  u32 i;
1183 
1184  for (i = 0; i < vec_len (rm->client_state_by_sw_if_index); i++)
1185  {
1186  cs = &rm->client_state_by_sw_if_index[i];
1187  if (cs->enabled)
1188  {
1189  vec_reset_length (buf1);
1190  vec_reset_length (buf2);
1191  if (cs->T1_due_time != DBL_MAX && cs->T1_due_time > current_time)
1192  {
1193  buf1 = format (buf1, "%u remaining",
1194  (u32) round (cs->T1_due_time - current_time));
1195  }
1196  else
1197  buf1 = format (buf1, "timeout");
1198  if (cs->T2_due_time != DBL_MAX && cs->T2_due_time > current_time)
1199  buf2 = format (buf2, "%u remaining",
1200  (u32) round (cs->T2_due_time - current_time));
1201  else
1202  buf2 = format (buf2, "timeout");
1203  if (cs->rebinding)
1204  rebinding = ", REBINDING";
1205  else
1206  rebinding = "";
1207  prefix_group =
1209  if (cs->T1)
1210  vlib_cli_output (vm,
1211  "sw_if_index: %u, prefix group: %s, T1: %u (%v), "
1212  "T2: %u (%v), server index: %d%s", i,
1213  prefix_group, cs->T1, buf1, cs->T2, buf2,
1214  cs->server_index, rebinding);
1215  else
1216  vlib_cli_output (vm, "sw_if_index: %u, prefix group: %s%s", i,
1217  prefix_group, rebinding);
1218  }
1219  }
1220 
1221  vec_free (buf1);
1222  vec_free (buf2);
1223 
1224  return error;
1225 }
1226 
1227 /* *INDENT-OFF* */
1228 VLIB_CLI_COMMAND (ip6_pd_clients_show_command, static) = {
1229  .path = "show ip6 pd clients",
1230  .short_help = "show ip6 pd clients",
1232 };
1233 /* *INDENT-ON* */
1234 
1235 
1236 
1237 int
1239  const u8 * prefix_group, u8 enable)
1240 {
1243  vnet_main_t *vnm = rm->vnet_main;
1244  client_state_t *client_state;
1245  static client_state_t empty_config = {
1246  0
1247  };
1248  prefix_info_t *prefix_info;
1249  prefix_info_t *prefix_list = 0;
1250  u32 prefix_group_index;
1251 
1252  if (!vnet_sw_interface_is_api_valid (vnm, sw_if_index))
1253  {
1254  clib_warning ("Invalid sw_if_index");
1255  return VNET_API_ERROR_INVALID_VALUE;
1256  }
1257 
1259  empty_config);
1260  client_state = &rm->client_state_by_sw_if_index[sw_if_index];
1261 
1262  u8 old_enabled = client_state->enabled;
1263 
1264  if (enable)
1265  {
1266  if (strnlen ((const char *) prefix_group, 64) == 64
1267  || prefix_group[0] == '\0')
1268  return VNET_API_ERROR_INVALID_VALUE;
1269  prefix_group_index =
1270  prefix_group_find_or_create (prefix_group, !old_enabled);
1271  if (old_enabled
1272  && prefix_group_index != client_state->prefix_group_index)
1273  return VNET_API_ERROR_INVALID_VALUE;
1274  }
1275 
1276  if (!old_enabled && enable)
1277  {
1278  client_state->enabled = 1;
1279  client_state->prefix_group_index = prefix_group_index;
1280  ASSERT (client_state->prefix_group_index != ~0);
1281  client_state->server_index = ~0;
1282 
1283  rm->n_clients++;
1284  if (rm->n_clients == 1)
1285  {
1286  enable_process ();
1288  }
1289 
1290  ip6_link_enable (sw_if_index, NULL);
1292  0, 1);
1293  }
1294  else if (old_enabled && !enable)
1295  {
1296  send_client_message_start_stop (sw_if_index, ~0, ~0, 0, 0);
1297 
1298  rm->n_clients--;
1299  if (rm->n_clients == 0)
1300  {
1302  disable_process ();
1303  }
1304 
1305  vec_validate (prefix_list, 0);
1306 
1307  /* *INDENT-OFF* */
1308  pool_foreach (prefix_info, pm->prefix_pool,
1309  ({
1310  if (is_dhcpv6_pd_prefix (prefix_info) &&
1311  prefix_info->opaque_data == sw_if_index)
1312  {
1313  ASSERT (sw_if_index < vec_len (rm->client_state_by_sw_if_index) &&
1314  rm->client_state_by_sw_if_index[sw_if_index].enabled);
1315  client_state_t *client_state =
1316  &rm->client_state_by_sw_if_index[sw_if_index];
1317  prefix_list[0] = *prefix_info;
1318  send_client_message_start_stop (sw_if_index,
1319  client_state->server_index,
1320  DHCPV6_MSG_RELEASE, prefix_list,
1321  1);
1322  u32 prefix_index = prefix_info - pm->prefix_pool;
1323  notify_prefix_add_del (prefix_index, 0);
1324  set_is_dhcpv6_pd_prefix (prefix_info, 0);
1325  pool_put (pm->prefix_pool, prefix_info);
1326  }
1327  }));
1328  /* *INDENT-ON* */
1329 
1330  vec_free (prefix_list);
1331 
1332  clib_memset (client_state, 0, sizeof (*client_state));
1333  }
1334 
1335  return 0;
1336 }
1337 
1338 static clib_error_t *
1340  vm,
1342  * input, vlib_cli_command_t * cmd)
1343 {
1345  vnet_main_t *vnm = rm->vnet_main;
1346  clib_error_t *error = 0;
1347  u8 *prefix_group = 0;
1348  u32 sw_if_index = ~0;
1349  u8 enable = 1;
1350  unformat_input_t _line_input, *line_input = &_line_input;
1351 
1352  if (!unformat_user (input, unformat_line_input, line_input))
1353  return 0;
1354 
1355  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1356  {
1357  if (unformat
1358  (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1359  ;
1360  else if (unformat (line_input, "prefix group %s", &prefix_group));
1361  else if (unformat (line_input, "disable"))
1362  enable = 0;
1363  else
1364  {
1365  error = clib_error_return (0, "unexpected input `%U'",
1366  format_unformat_error, line_input);
1367  goto done;
1368  }
1369  }
1370 
1371  if (prefix_group == 0 && enable)
1372  error = clib_error_return (0, "Prefix group must be set when enabling");
1373  else if (sw_if_index != ~0)
1374  {
1375  if (dhcp6_pd_client_enable_disable (sw_if_index, prefix_group, enable)
1376  != 0)
1377  error = clib_error_return (0, "Invalid sw_if_index or prefix group");
1378  }
1379  else
1380  error = clib_error_return (0, "Missing sw_if_index");
1381 
1382 done:
1383  vec_free (prefix_group);
1384  unformat_free (line_input);
1385 
1386  return error;
1387 }
1388 
1389 /*?
1390  * This command is used to enable/disable DHCPv6 PD client
1391  * on particular interface.
1392  *
1393  * @cliexpar
1394  * @parblock
1395  * Example of how to enable DHCPv6 PD client:
1396  * @cliexcmd{dhcp6 pd client GigabitEthernet2/0/0 prefix group my-pd-group}
1397  * Example of how to disable DHCPv6 PD client:
1398  * @cliexcmd{dhcp6 pd client GigabitEthernet2/0/0 disable}
1399  * @endparblock
1400 ?*/
1401 /* *INDENT-OFF* */
1403  .path = "dhcp6 pd client",
1404  .short_help = "dhcp6 pd client <interface> (prefix group <string> | disable)",
1406 };
1407 /* *INDENT-ON* */
1408 
1409 #include <vlib/unix/plugin.h>
1410 
1411 static clib_error_t *
1413 {
1415 
1416  rm->vlib_main = vm;
1417  rm->vnet_main = vnet_get_main ();
1418  rm->api_main = vlibapi_get_main ();
1420 
1421  return (NULL);
1422 }
1423 
1425 
1426 /*
1427  * fd.io coding-style-patch-verification: ON
1428  *
1429  * Local Variables:
1430  * eval: (c-set-style "gnu")
1431  * End:
1432  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:507
u8 * format_clib_error(u8 *s, va_list *va)
Definition: error.c:191
static void notify_prefix_add_del(u32 prefix_index, u8 is_add)
vlib_node_registration_t dhcp6_pd_client_cp_process_node
(constructor) VLIB_REGISTER_NODE (dhcp6_pd_client_cp_process_node)
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
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vl_api_dhcp6_pd_prefix_info_t prefixes[n_prefixes]
Definition: dhcp.api:503
static void cp_ip6_address_prefix_add_del_handler(u32 prefix_index, u8 is_add)
int dhcp6_pd_client_enable_disable(u32 sw_if_index, const u8 *prefix_group, u8 enable)
Optimized string handling code, including c11-compliant "safe C library" variants.
ip6_address_t prefix
static u32 cp_ip6_address_find_new_active_prefix(u32 prefix_group_index, u32 ignore_prefix_index)
unsigned long u64
Definition: types.h:89
static_always_inline u8 is_dhcpv6_pd_prefix(prefix_info_t *prefix_info)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static void send_client_message_start_stop(u32 sw_if_index, u32 server_index, u8 msg_type, prefix_info_t *prefix_list, u8 start)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:291
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:590
dhcp6_pd_send_client_message_params_prefix_t * prefixes
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
void dhcp6_pd_send_client_message(vlib_main_t *vm, u32 sw_if_index, u8 stop, dhcp6_pd_send_client_message_params_t *params)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
vl_api_prefix_t prefix
Definition: ip.api:144
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:252
vhost_vring_addr_t addr
Definition: vhost_user.h:254
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
static ip6_address_with_prefix_main_t ip6_address_with_prefix_main
const u8 ** prefix_group_name_by_index
static void cp_ip6_address_add_del_now(ip6_address_info_t *address_info, u8 is_add)
#define static_always_inline
Definition: clib.h:106
#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
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
format_function_t format_ip6_address_and_length
Definition: format.h:92
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
vlib_node_t ** nodes
Definition: node.h:701
#define clib_error_return(e, args...)
Definition: error.h:99
vl_api_dhcpv6_msg_type_t msg_type
Definition: dhcp.api:496
unsigned int u32
Definition: types.h:88
static_always_inline void active_prefix_index_by_prefix_group_index_set(u32 prefix_group_index, u32 prefix_index)
unformat_function_t unformat_line_input
Definition: format.h:283
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
VNET_DHCP6_PD_REPLY_EVENT_FUNCTION(dhcp6_pd_reply_event_handler)
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:934
struct _unformat_input_t unformat_input_t
ip6_main_t ip6_main
Definition: ip6_forward.c:2784
vlib_main_t * vm
Definition: in2out_ed.c:1599
static void interrupt_process(void)
static void disable_process(void)
u8 len
Definition: ip_types.api:92
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:226
unformat_function_t unformat_ip6_address
Definition: format.h:89
ip6_address_t fib_masks[129]
Definition: ip6.h:193
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 valid_time
Definition: dhcp.api:312
u32 runtime_index
Definition: node.h:285
static clib_error_t * cp_ip6_prefixes_show_command_function(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static clib_error_t * ip6_pd_clients_show_command_function(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
format_function_t format_ip6_address
Definition: format.h:91
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
vl_api_interface_index_t sw_if_index
Definition: dhcp.api:494
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
static prefix_info_t * create_prefix_list(u32 sw_if_index)
#define clib_warning(format, args...)
Definition: error.h:59
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
string name[64]
Definition: ip.api:44
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1599
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
signed int i32
Definition: types.h:77
u8 value
Definition: qos.api:54
#define ASSERT(truth)
static u32 cp_ip6_construct_address(ip6_address_info_t *address_info, u32 prefix_index, ip6_address_t *r_addr)
void ip6_ra_update_secondary_radv_info(ip6_address_t *address, u8 prefix_len, u32 primary_sw_if_index, u32 valid_time, u32 preferred_time)
Definition: ip6_ra.c:1426
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
manual_print typedef address
Definition: ip_types.api:85
static_always_inline u32 active_prefix_index_by_prefix_group_index_get(u32 prefix_group_index)
static u8 ip6_prefixes_equal(ip6_address_t *prefix1, ip6_address_t *prefix2, u8 len)
Tell client about a DHCPv6 PD server reply event.
Definition: dhcp.api:490
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
Definition: node_funcs.h:148
static uword ip6_address_is_link_local_unicast(const ip6_address_t *a)
Definition: ip6_packet.h:253
static clib_error_t * dhcp6_pd_reply_event_handler(vl_api_dhcp6_pd_reply_event_t *mp)
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
#define vec_elt(v, i)
Get vector value at index i.
static dhcp6_pd_client_cp_main_t dhcp6_pd_client_cp_main
prefix_info_t * prefix_pool
static_always_inline void set_is_dhcpv6_pd_prefix(prefix_info_t *prefix_info, u8 value)
static uword vnet_sw_interface_is_api_valid(vnet_main_t *vnm, u32 sw_if_index)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static clib_error_t * cp_ip6_addresses_show_command_function(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
vlib_node_main_t node_main
Definition: main.h:158
static clib_error_t * dhcp_pd_client_cp_init(vlib_main_t *vm)
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
static uword dhcp6_pd_client_cp_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
static u32 prefix_group_find_or_create(const u8 *name, u8 create)
void dhcp6_clients_enable_disable(u8 enable)
static api_main_t * vlibapi_get_main(void)
Definition: api_common.h:379
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
int ip6_ra_prefix(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *prefix_addr, u8 prefix_len, u8 use_default, u32 val_lifetime, u32 pref_lifetime, u8 no_advertise, u8 off_link, u8 no_autoconfig, u8 no_onlink, u8 is_no)
Definition: ip6_ra.c:1765
uword clib_bitmap_t
Definition: bitmap.h:50
clib_bitmap_t * prefix_ownership_bitmap
u32 preferred_time
Definition: dhcp.api:313
#define vec_foreach(var, vec)
Vector iterator.
clib_error_t * ip6_add_del_interface_address(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *address, u32 address_length, u32 is_del)
Definition: ip6_forward.c:297
static vlib_cli_command_t dhcp6_pd_client_enable_disable_command
(constructor) VLIB_CLI_COMMAND (dhcp6_pd_client_enable_disable_command)
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:554
static void cp_ip6_advertise_prefix(prefix_info_t *prefix_info, ip6_address_info_t *address_info, int enable)
int dhcp6_cp_ip6_address_add_del(u32 sw_if_index, const u8 *prefix_group, ip6_address_t address, u8 prefix_length, u8 is_add)
void vlib_start_process(vlib_main_t *vm, uword process_index)
Definition: main.c:1617
static void enable_process(void)
static ip6_prefix_main_t ip6_prefix_main
static clib_error_t * dhcp6_pd_client_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t() *input, vlib_cli_command_t *cmd)
static clib_error_t * cp_ip6_address_add_del_command_function(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
client_state_t * client_state_by_sw_if_index