FD.io VPP  v18.04-17-g3a0d853
Vector Packet Processing
rd_cp.c
Go to the documentation of this file.
1 #include <vnet/vnet.h>
2 #include <vlibmemory/api.h>
3 #include <vnet/vnet_msg_enum.h>
4 #include <vnet/ip/ip6.h>
5 #include <signal.h>
6 #include <math.h>
7 
8 #define vl_typedefs /* define message structures */
9 #include <vnet/vnet_all_api_h.h>
10 #undef vl_typedefs
11 
12 #define vl_endianfun /* define message structures */
13 #include <vnet/vnet_all_api_h.h>
14 #undef vl_endianfun
15 
17 
18 #define foreach_rd_cp_msg \
19 _(IP6_ND_ADDRESS_AUTOCONFIG, ip6_nd_address_autoconfig)
20 
21 #define foreach_client_rd_cp_msg \
22 _(IP6_RA_EVENT, ip6_ra_event) \
23 _(IP6ND_SEND_ROUTER_SOLICITATION_REPLY, ip6nd_send_router_solicitation_reply) \
24 _(WANT_IP6_RA_EVENTS_REPLY, want_ip6_ra_events_reply) \
25 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY, sw_interface_add_del_address_reply) \
26 _(IP_ADD_DEL_ROUTE_REPLY, ip_add_del_route_reply) \
27 _(SW_INTERFACE_GET_MAC_ADDRESS_REPLY, sw_interface_get_mac_address_reply) \
28 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY, sw_interface_ip6_enable_disable_reply)
29 
30 typedef struct
31 {
37 
38 typedef struct
39 {
44 
45 typedef struct
46 {
50 
51 typedef struct
52 {
55 
59 
60  /* binary API client */
64  void (**msg_handlers) (void *);
65  struct
66  {
69  union
70  {
71  u8 mac_address[6];
72  };
73  } api_reply;
74 
75  /* convenience */
80 } rd_cp_main_t;
81 
83 
84 enum
85 {
87 };
88 
89 #define vl_api_ip6_nd_address_autoconfig_t_print vl_noop_handler
90 
91 static void
93 {
94  rd_cp_main_t *rm = &rd_cp_main;
95 
96  vec_validate (rm->msg_handlers, c->id);
97 
98  if (rm->msg_handlers[c->id] && rm->msg_handlers[c->id] != c->handler)
100  ("BUG: re-registering 'vl_api_%s_t_handler'."
101  "Handler was %llx, replaced by %llx",
102  c->name, rm->msg_handlers[c->id], c->handler);
103 
104  rm->msg_handlers[c->id] = c->handler;
105 }
106 
107 static void
108 set_handler (int id, char *name, void *handler)
109 {
111  vl_msg_api_msg_config_t *c = &cfg;
112 
113  memset (c, 0, sizeof (*c));
114 
115  c->id = id;
116  c->name = name;
117  c->handler = handler;
118  c->replay = 1;
119  c->message_bounce = 0;
120  c->is_mp_safe = 0;
121  msg_api_config (c);
122 }
123 
126 {
127  rd_cp_main_t *rm = &rd_cp_main;
128  uword msgp;
129 
130  if (!rm->api_connected)
131  return;
132 
133  if (svm_queue_sub2 (rm->vl_input_queue, (u8 *) & msgp))
134  return;
135 
136  u16 id = ntohs (*((u16 *) msgp));
137  u8 *(*handler) (void *);
138 
139  if (id < vec_len (rm->msg_handlers) && rm->msg_handlers[id])
140  {
141  handler = (void *) rm->msg_handlers[id];
142  (*handler) ((void *) msgp);
143  }
144  else
145  {
146  if (id != VL_API_MEMCLNT_KEEPALIVE)
147  clib_warning ("no handler for msg id %d", id);
148  }
149 }
150 
153 {
154  rd_cp_main_t *rm = &rd_cp_main;
155  vlib_main_t *vm = rm->vlib_main;
156  f64 timeout;
157 
158  timeout = vlib_time_now (vm) + 1.0;
159  while (vlib_time_now (vm) < timeout)
160  {
161  check_queue ();
162  if (rm->api_reply.arrived)
163  break;
164  vlib_process_suspend (vm, 1e-5);
165  }
166 
167  if (!rm->api_reply.arrived)
168  return 1;
169 
170  return rm->api_reply.retval;
171 }
172 
174 send_msg (void *msg)
175 {
176  rd_cp_main_t *rm = &rd_cp_main;
177 
179  (u8 *) & msg);
180 }
181 
184 {
185  rd_cp_main_t *rm = &rd_cp_main;
186 
187  rm->api_reply.arrived = 0;
188  send_msg (msg);
189  return wait_for_reply ();
190 }
191 
192 static int
194 {
195  rd_cp_main_t *rm = &rd_cp_main;
197  int rv;
198 
199  mp = vl_msg_api_alloc (sizeof (*mp));
200  memset (mp, 0, sizeof (*mp));
201  mp->_vl_msg_id = htons (VL_API_IP6ND_SEND_ROUTER_SOLICITATION);
202  mp->client_index = rm->my_client_index;
203  mp->sw_if_index = htonl (sw_if_index);
204  if (start)
205  {
206  mp->irt = htonl (1);
207  mp->mrt = htonl (120);
208  }
209  else
210  mp->stop = 1;
211 
212  rv = send_msg_and_wait_for_reply (mp);
213 
214  return rv;
215 }
216 
217 static void
219  (vl_api_ip6nd_send_router_solicitation_reply_t * mp)
220 {
221  rd_cp_main_t *rm = &rd_cp_main;
222 
223  rm->api_reply.arrived = 1;
224  rm->api_reply.retval = ntohl (mp->retval);
225 }
226 
227 static int
229 {
230  rd_cp_main_t *rm = &rd_cp_main;
232  int rv;
233 
234  mp = vl_msg_api_alloc (sizeof (*mp));
235  memset (mp, 0, sizeof (*mp));
236  mp->_vl_msg_id = htons (VL_API_WANT_IP6_RA_EVENTS);
237  mp->client_index = rm->my_client_index;
238  mp->enable_disable = enable;
239  mp->pid = htonl (getpid ());
240 
241  rv = send_msg_and_wait_for_reply (mp);
242 
243  if (!rv)
244  rm->events_on = enable;
245 
246  return rv;
247 }
248 
249 static void
250 vl_api_want_ip6_ra_events_reply_t_handler (vl_api_want_ip6_ra_events_reply_t *
251  mp)
252 {
253  rd_cp_main_t *rm = &rd_cp_main;
254 
255  rm->api_reply.arrived = 1;
256  rm->api_reply.retval = ntohl (mp->retval);
257 }
258 
259 static void interrupt_process (void);
260 
261 static int
262 add_slaac_address (vlib_main_t * vm, u32 sw_if_index, u8 address_length,
263  ip6_address_t * address, f64 due_time)
264 {
265  rd_cp_main_t *rm = &rd_cp_main;
266  slaac_address_t *slaac_address;
268  int rv;
269 
270  pool_get (rm->slaac_address_pool, slaac_address);
271 
272  slaac_address->sw_if_index = sw_if_index;
273  slaac_address->address_length = address_length;
274  slaac_address->address = *address;
275  slaac_address->due_time = due_time;
276 
277  mp = vl_msg_api_alloc (sizeof (*mp));
278  memset (mp, 0, sizeof (*mp));
279  mp->_vl_msg_id = htons (VL_API_SW_INTERFACE_ADD_DEL_ADDRESS);
280  mp->client_index = rm->my_client_index;
281  mp->is_add = 1;
282  mp->is_ipv6 = 1;
283  mp->sw_if_index = htonl (sw_if_index);
284  mp->address_length = slaac_address->address_length;
285  clib_memcpy (mp->address, slaac_address->address.as_u8, 16);
286 
287  rv = send_msg_and_wait_for_reply (mp);
288 
289  return rv;
290 }
291 
292 static void
294  (vl_api_sw_interface_add_del_address_reply_t * mp)
295 {
296  rd_cp_main_t *rm = &rd_cp_main;
297 
298  rm->api_reply.arrived = 1;
299  rm->api_reply.retval = ntohl (mp->retval);
300 }
301 
302 static int
304  ip6_address_t * next_hop_address, f64 due_time)
305 {
306  rd_cp_main_t *rm = &rd_cp_main;
307  default_route_t *default_route;
309  int rv;
310 
311  pool_get (rm->default_route_pool, default_route);
312 
313  default_route->sw_if_index = sw_if_index;
314  default_route->router_address = *next_hop_address;
315  default_route->due_time = due_time;
316 
317  mp = vl_msg_api_alloc (sizeof (*mp));
318  memset (mp, 0, sizeof (*mp));
319  mp->_vl_msg_id = htons (VL_API_IP_ADD_DEL_ROUTE);
320  mp->client_index = rm->my_client_index;
321  mp->is_add = 1;
322  mp->is_ipv6 = 1;
323  mp->dst_address_length = 0;
324  mp->next_hop_sw_if_index = htonl (default_route->sw_if_index);
325  clib_memcpy (mp->next_hop_address, default_route->router_address.as_u8, 16);
326 
327  rv = send_msg_and_wait_for_reply (mp);
328 
329  return rv;
330 }
331 
332 static void
333 vl_api_ip_add_del_route_reply_t_handler (vl_api_ip_add_del_route_reply_t * mp)
334 {
335  rd_cp_main_t *rm = &rd_cp_main;
336 
337  rm->api_reply.arrived = 1;
338  rm->api_reply.retval = ntohl (mp->retval);
339 }
340 
341 static int
343 {
344  rd_cp_main_t *rm = &rd_cp_main;
346 
347  mp = vl_msg_api_alloc (sizeof (*mp));
348  memset (mp, 0, sizeof (*mp));
349  mp->_vl_msg_id = htons (VL_API_SW_INTERFACE_ADD_DEL_ADDRESS);
350  mp->client_index = rm->my_client_index;
351  mp->is_add = 0;
352  mp->is_ipv6 = 1;
353  mp->sw_if_index = htonl (slaac_address->sw_if_index);
354  mp->address_length = slaac_address->address_length;
355  clib_memcpy (mp->address, slaac_address->address.as_u8, 16);
356 
358 
359  pool_put (rm->slaac_address_pool, slaac_address);
360 
361  return 0;
362 }
363 
364 static int
366 {
367  rd_cp_main_t *rm = &rd_cp_main;
369 
370  mp = vl_msg_api_alloc (sizeof (*mp));
371  memset (mp, 0, sizeof (*mp));
372  mp->_vl_msg_id = htons (VL_API_IP_ADD_DEL_ROUTE);
373  mp->client_index = rm->my_client_index;
374  mp->is_add = 0;
375  mp->is_ipv6 = 1;
376  mp->dst_address_length = 0;
377  mp->next_hop_sw_if_index = htonl (default_route->sw_if_index);
378  clib_memcpy (mp->next_hop_address, default_route->router_address.as_u8, 16);
379 
381 
382  pool_put (rm->default_route_pool, default_route);
383 
384  return 0;
385 }
386 
387 static u32
388 get_interface_mac_address (u32 sw_if_index, u8 mac[])
389 {
390  rd_cp_main_t *rm = &rd_cp_main;
392  int rv;
393 
394  mp = vl_msg_api_alloc (sizeof (*mp));
395  memset (mp, 0, sizeof (*mp));
396  mp->_vl_msg_id = htons (VL_API_SW_INTERFACE_GET_MAC_ADDRESS);
397  mp->client_index = rm->my_client_index;
398  mp->sw_if_index = htonl (sw_if_index);
399 
400  rv = send_msg_and_wait_for_reply (mp);
401 
402  if (!rv)
403  clib_memcpy (mac, rm->api_reply.mac_address, 6);
404 
405  return rv;
406 }
407 
408 static void
411 {
412  rd_cp_main_t *rm = &rd_cp_main;
413 
414  rm->api_reply.arrived = 1;
415  rm->api_reply.retval = ntohl (mp->retval);
416 
417  if (rm->api_reply.retval == 0)
419 }
420 
421 static u32
422 ip6_enable (u32 sw_if_index)
423 {
424  rd_cp_main_t *rm = &rd_cp_main;
426  int rv;
427 
428  mp = vl_msg_api_alloc (sizeof (*mp));
429  memset (mp, 0, sizeof (*mp));
430  mp->_vl_msg_id = htons (VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE);
431  mp->client_index = rm->my_client_index;
432  mp->sw_if_index = htonl (sw_if_index);
433  mp->enable = 1;
434 
435  rv = send_msg_and_wait_for_reply (mp);
436 
437  return rv;
438 }
439 
440 static void
442  (vl_api_sw_interface_ip6_enable_disable_reply_t * mp)
443 {
444  rd_cp_main_t *rm = &rd_cp_main;
445 
446  rm->api_reply.arrived = 1;
447  rm->api_reply.retval = ntohl (mp->retval);
448 }
449 
450 static u8
452 {
453  if (len >= 64)
454  {
455  if (prefix1->as_u64[0] != prefix2->as_u64[0])
456  return 0;
457  if (len == 64)
458  return 1;
459  return prefix1->as_u64[1] >> (128 - len) ==
460  prefix2->as_u64[1] >> (128 - len);
461  }
462  return prefix1->as_u64[0] >> (64 - len) == prefix2->as_u64[0] >> (64 - len);
463 }
464 
465 #define PREFIX_FLAG_A (1 << 6)
466 #define PREFIX_FLAG_L (1 << 7)
467 
468 static void
470 {
471  rd_cp_main_t *rm = &rd_cp_main;
472  vlib_main_t *vm = rm->vlib_main;
473  interface_config_t *if_config;
474  default_route_t *default_route;
475  slaac_address_t *slaac_address;
476  u32 sw_if_index;
477  u16 router_lifetime_in_sec;
478  u32 n_prefixes;
480  u8 mac[6];
481  f64 current_time;
482  u32 i;
483 
484  current_time = vlib_time_now (vm);
485 
486  sw_if_index = ntohl (mp->sw_if_index);
487 
488  if_config = &rm->config_by_sw_if_index[sw_if_index];
489 
490  if (if_config->install_default_routes)
491  {
492  router_lifetime_in_sec = ntohs (mp->router_lifetime_in_sec);
493  u8 route_already_present = 0;
494  /* *INDENT-OFF* */
495  pool_foreach (default_route, rm->default_route_pool,
496  ({
497  if (default_route->sw_if_index != sw_if_index)
498  ;
499  else if (0 != memcmp (&default_route->router_address,
500  mp->router_address, 16))
501  ;
502  else
503  {
504  route_already_present = 1;
505  goto default_route_pool_foreach_out;
506  }
507  }));
508  /* *INDENT-ON* */
509  default_route_pool_foreach_out:
510 
511  if (!route_already_present)
512  {
513  if (router_lifetime_in_sec != 0)
514  add_default_route (vm, sw_if_index, (void *) mp->router_address,
515  current_time + router_lifetime_in_sec);
516  }
517  else
518  {
519  if (router_lifetime_in_sec != 0)
520  default_route->due_time = current_time + router_lifetime_in_sec;
521  else
522  remove_default_route (vm, default_route);
523  }
524  }
525 
526  if (get_interface_mac_address (sw_if_index, mac) != 0)
527  {
528  clib_warning ("Error getting MAC address");
529  return;
530  }
531 
532  if (!if_config->enabled)
533  return;
534 
535  n_prefixes = ntohl (mp->n_prefixes);
536  for (i = 0; i < n_prefixes; i++)
537  {
538  ip6_address_t *dst_address;
539  u8 prefix_length;
540  u32 valid_time;
541  u32 preferred_time;
542  f64 due_time;
543 
544  prefix = &mp->prefixes[i];
545 
546  if (!(prefix->flags & PREFIX_FLAG_A))
547  continue;
548 
549  dst_address = (ip6_address_t *) prefix->dst_address;
550  prefix_length = prefix->dst_address_length;
551 
552  if (ip6_address_is_link_local_unicast (dst_address))
553  continue;
554 
555  valid_time = ntohl (prefix->valid_time);
556  preferred_time = ntohl (prefix->preferred_time);
557 
558  if (preferred_time > valid_time)
559  continue;
560 
561  if (prefix_length != 64)
562  continue;
563 
564  u8 address_already_present = 0;
565  /* *INDENT-OFF* */
566  pool_foreach (slaac_address, rm->slaac_address_pool,
567  ({
568  if (slaac_address->sw_if_index != sw_if_index)
569  ;
570  else if (slaac_address->address_length != prefix_length)
571  ;
572  else if (!ip6_prefixes_equal (&slaac_address->address, dst_address,
573  prefix_length))
574  ;
575  else
576  {
577  address_already_present = 1;
578  goto slaac_address_pool_foreach_out;
579  }
580  }));
581  /* *INDENT-ON* */
582  slaac_address_pool_foreach_out:
583 
584  if (address_already_present)
585  {
586  f64 remaining_life_time = slaac_address->due_time - current_time;
587  if (valid_time > 2 * 60 * 60 || valid_time > remaining_life_time)
588  slaac_address->due_time = current_time + valid_time;
589  else if (remaining_life_time > 2 * 60 * 60)
590  slaac_address->due_time = current_time + 2 * 60 * 60;
591  continue;
592  }
593 
594  if (valid_time == 0)
595  continue;
596 
597  due_time = current_time + valid_time;
598 
600  addr.as_u64[0] = dst_address->as_u64[0];
601  /* Invert the "u" bit */
602  addr.as_u8[8] = mac[0] ^ (1 << 1);
603  addr.as_u8[9] = mac[1];
604  addr.as_u8[10] = mac[2];
605  addr.as_u8[11] = 0xFF;
606  addr.as_u8[12] = 0xFE;
607  addr.as_u8[13] = mac[3];
608  addr.as_u8[14] = mac[4];
609  addr.as_u8[15] = mac[5];
610 
611  add_slaac_address (vm, sw_if_index, prefix_length, &addr, due_time);
612  }
613 
615 }
616 
617 static uword
619 {
620  uword event_type;
621  uword *event_data = 0;
622  rd_cp_main_t *rm = &rd_cp_main;
623  slaac_address_t *slaac_address;
624  default_route_t *default_route;
625  f64 sleep_time = 1e9;
626  const f64 micro_sleep_time = 1e-5;
627  f64 start_time;
628  f64 current_time;
629  f64 due_time;
630 
631  while (1)
632  {
633  start_time = vlib_time_now (vm);
634 
635  while (1)
636  {
637  check_queue ();
638  vlib_process_wait_for_event_or_clock (vm, micro_sleep_time);
639  event_type = vlib_process_get_events (vm, &event_data);
640  if (event_type != ~0
641  || vlib_time_now (vm) > start_time + sleep_time)
642  break;
643  }
644 
645  vec_reset_length (event_data);
646 
647  current_time = vlib_time_now (vm);
648  do
649  {
650  due_time = current_time + 1e9;
651  /* *INDENT-OFF* */
652  pool_foreach (slaac_address, rm->slaac_address_pool,
653  ({
654  if (slaac_address->due_time > current_time)
655  {
656  if (slaac_address->due_time < due_time)
657  due_time = slaac_address->due_time;
658  }
659  else
660  {
661  remove_slaac_address (vm, slaac_address);
662  /* make sure ip6 stays enabled */
663  ip6_enable (slaac_address->sw_if_index);
664  }
665  }));
666  pool_foreach (default_route, rm->default_route_pool,
667  ({
668  if (default_route->due_time > current_time)
669  {
670  if (default_route->due_time < due_time)
671  due_time = default_route->due_time;
672  }
673  else
674  remove_default_route (vm, default_route);
675  }));
676  /* *INDENT-ON* */
677  current_time = vlib_time_now (vm);
678  }
679  while (due_time < current_time);
680 
681  sleep_time = due_time - current_time;
682  }
683 
684  return 0;
685 }
686 
687 /* *INDENT-OFF* */
689  .function = rd_cp_process,
690  .type = VLIB_NODE_TYPE_PROCESS,
691  .name = "rd-cp-process",
692 };
693 /* *INDENT-ON* */
694 
695 static void
697 {
698  rd_cp_main_t *rm = &rd_cp_main;
699  vlib_main_t *vm = rm->vlib_main;
700 
703 }
704 
705 static int
707 {
708  rd_cp_main_t *rm = &rd_cp_main;
709  api_main_t *am = &api_main;
710  svm_region_t *svm;
711 
712  svm = am->vlib_rp;
713 
714  pthread_mutex_lock (&svm->mutex);
715  rd_cp_main.vl_input_queue =
716  svm_queue_init (1024, sizeof (uword), getpid (), 0);
717  pthread_mutex_unlock (&svm->mutex);
718 
719  rd_cp_main.my_client_index =
720  vl_api_memclnt_create_internal ("ndp_rd_client",
721  rd_cp_main.vl_input_queue);
722 
723  rm->api_connected = 1;
724 
725  return 0;
726 }
727 
728 static int
729 set_address_autoconfig (u32 sw_if_index, u8 enable, u8 install_default_routes)
730 {
731  rd_cp_main_t *rm = &rd_cp_main;
732  vlib_main_t *vm = rm->vlib_main;
733  vnet_main_t *vnm = rm->vnet_main;
734  interface_config_t *if_config;
735  interface_config_t empty_config = { 0, 0 };
736  slaac_address_t *slaac_address;
737  default_route_t *default_route;
738 
739  if (!enable)
740  install_default_routes = 0;
741 
742  // TODO: makes direct interaction with data plane
743  if (!vnet_sw_interface_is_api_valid (vnm, sw_if_index))
744  {
745  clib_warning ("Invalid sw_if_index");
746  return 1;
747  }
748 
749  if (!rm->enabled)
750  {
752  /* process kickoff */
755  rm->enabled = 1;
756  }
757 
759  empty_config);
760  if_config = &rm->config_by_sw_if_index[sw_if_index];
761 
762  if (!if_config->enabled && enable)
763  ip6_enable (sw_if_index);
764 
765  if ((!if_config->enabled && enable)
766  || (!if_config->install_default_routes && install_default_routes))
767  router_solicitation_start_stop (sw_if_index, 1);
768  else if (if_config->enabled && !enable)
769  router_solicitation_start_stop (sw_if_index, 0);
770 
771  if (if_config->enabled && !enable)
772  {
773  /* *INDENT-OFF* */
774  pool_foreach (slaac_address, rm->slaac_address_pool,
775  ({
776  remove_slaac_address (vm, slaac_address);
777  }));
778  /* *INDENT-ON* */
779  }
780  if (if_config->install_default_routes && !install_default_routes)
781  {
782  /* *INDENT-OFF* */
783  pool_foreach (default_route, rm->default_route_pool,
784  ({
785  remove_default_route (vm, default_route);
786  }));
787  /* *INDENT-ON* */
788  }
789 
790  if_config->enabled = enable;
791  if_config->install_default_routes = install_default_routes;
792 
793  return 0;
794 }
795 
796 static clib_error_t *
798  unformat_input_t * input, vlib_cli_command_t * cmd)
799 {
800  rd_cp_main_t *rm = &rd_cp_main;
801  vnet_main_t *vnm = rm->vnet_main;
802  clib_error_t *error = 0;
803  u32 sw_if_index = ~0;
804  u8 enable = 1;
805  u8 default_route = 0;
806 
808  {
809  if (unformat
810  (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
811  ;
812  if (unformat (input, "default-route"))
813  default_route = 1;
814  if (unformat (input, "disable"))
815  enable = 0;
816  else
817  break;
818  }
819 
820  if (sw_if_index != ~0)
821  {
822  if (set_address_autoconfig (sw_if_index, enable, default_route) != 0)
823  error = clib_error_return (0, "Invalid sw_if_index");
824  }
825  else
826  error = clib_error_return (0, "Missing sw_if_index");
827 
828  return error;
829 }
830 
831 /*?
832  * This command is used to enable ND address autoconfiguration
833  * on particular interface including setting up default routes.
834  *
835  * @cliexpar
836  * @parblock
837  * Example of how to enable ND address autoconfiguration:
838  * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0}
839  * Example of how to enable ND address autoconfiguration
840  * with setting up default routes:
841  * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0 default-route}
842  * Example of how to disable ND address autoconfiguration:
843  * @cliexcmd{ip6 nd address autoconfig GigabitEthernet2/0/0 disable}
844  * @endparblock
845 ?*/
846 /* *INDENT-OFF* */
847 VLIB_CLI_COMMAND (ip6_nd_address_autoconfig_command, static) = {
848  .path = "ip6 nd address autoconfig",
849  .short_help = "ip6 nd address autoconfig <interface> [default-route|disable]",
850  .function = ip6_nd_address_autoconfig,
851 };
852 /* *INDENT-ON* */
853 
854 static void
856  * mp)
857 {
858  vl_api_ip6_nd_address_autoconfig_reply_t *rmp;
859  u32 sw_if_index;
860  int rv = 0;
861 
863 
864  sw_if_index = ntohl (mp->sw_if_index);
865 
866  rv =
867  set_address_autoconfig (sw_if_index, mp->enable,
869 
871 
872  REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
873 }
874 
875 #define vl_msg_name_crc_list
876 #include <vnet/ip/rd_cp.api.h>
877 #undef vl_msg_name_crc_list
878 
879 static void
881 {
882 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
883  foreach_vl_msg_name_crc_rd_cp;
884 #undef _
885 }
886 
887 static clib_error_t *
889 {
890  rd_cp_main_t *rm = &rd_cp_main;
891  api_main_t *am = &api_main;
892 
893  rm->vlib_main = vm;
894  rm->vnet_main = vnet_get_main ();
895  rm->api_main = am;
896  rm->node_index = rd_cp_process_node.index;
897 
898 #define _(N,n) \
899  vl_msg_api_set_handlers(VL_API_##N, #n, \
900  vl_api_##n##_t_handler, \
901  vl_noop_handler, \
902  vl_api_##n##_t_endian, \
903  vl_api_##n##_t_print, \
904  sizeof(vl_api_##n##_t), 0/* do NOT trace! */);
906 #undef _
907 
908 #define _(N,n) \
909  set_handler(VL_API_##N, #n, vl_api_##n##_t_handler);
911 #undef _
912 
913  /*
914  * Set up the (msg_name, crc, message-id) table
915  */
917 
918  return 0;
919 }
920 
922 
923 /*
924  * fd.io coding-style-patch-verification: ON
925  *
926  * Local Variables:
927  * eval: (c-set-style "gnu")
928  * End:
929  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:434
static void vl_api_sw_interface_ip6_enable_disable_reply_t_handler(vl_api_sw_interface_ip6_enable_disable_reply_t *mp)
Definition: rd_cp.c:442
#define PREFIX_FLAG_A
Definition: rd_cp.c:465
int id
the message ID
Definition: api_common.h:120
static u8 ip6_prefixes_equal(ip6_address_t *prefix1, ip6_address_t *prefix2, u8 len)
Definition: rd_cp.c:451
static int add_slaac_address(vlib_main_t *vm, u32 sw_if_index, u8 address_length, ip6_address_t *address, f64 due_time)
Definition: rd_cp.c:262
Register for ip6 router advertisement events.
Definition: ip.api:737
u32 vl_api_memclnt_create_internal(char *name, svm_queue_t *q)
Definition: memory_api.c:112
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:699
static void vl_api_ip6_ra_event_t_handler(vl_api_ip6_ra_event_t *mp)
Definition: rd_cp.c:469
Get interface&#39;s MAC address.
Definition: interface.api:368
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
u16 router_lifetime_in_sec
Definition: ip.api:781
u8 as_u8[16]
Definition: ip6_packet.h:48
u64 as_u64[2]
Definition: ip6_packet.h:51
slaac_address_t * slaac_address_pool
Definition: rd_cp.c:57
static int router_solicitation_start_stop(u32 sw_if_index, u8 start)
Definition: rd_cp.c:193
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:227
vlib_main_t * vlib_main
Definition: rd_cp.c:76
int svm_queue_sub2(svm_queue_t *q, u8 *elem)
Definition: queue.c:374
Message configuration definition.
Definition: api_common.h:118
static void vl_api_ip6_nd_address_autoconfig_t_handler(vl_api_ip6_nd_address_autoconfig_t *mp)
Definition: rd_cp.c:855
ip6_address_t address
Definition: rd_cp.c:34
#define foreach_rd_cp_msg
Definition: rd_cp.c:18
u8 install_default_routes
Definition: rd_cp.c:48
static void vl_api_ip_add_del_route_reply_t_handler(vl_api_ip_add_del_route_reply_t *mp)
Definition: rd_cp.c:333
int i
static int add_default_route(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *next_hop_address, f64 due_time)
Definition: rd_cp.c:303
unformat_function_t unformat_vnet_sw_interface
ip6_address_t router_address
Definition: rd_cp.c:41
static u32 ip6_enable(u32 sw_if_index)
Definition: rd_cp.c:422
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:227
void * vl_msg_api_alloc(int nbytes)
static void msg_api_config(vl_msg_api_msg_config_t *c)
Definition: rd_cp.c:92
static clib_error_t * rd_cp_init(vlib_main_t *vm)
Definition: rd_cp.c:888
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static void setup_message_id_table(api_main_t *am)
Definition: rd_cp.c:880
svm_queue_t * svm_queue_init(int nels, int elsize, int consumer_pid, int signal_when_queue_non_empty)
Definition: queue.c:51
static uword vlib_process_suspend(vlib_main_t *vm, f64 dt)
Suspend a vlib cooperative multi-tasking thread for a period of time.
Definition: node_funcs.h:448
#define static_always_inline
Definition: clib.h:93
svm_queue_t * vl_input_queue
Definition: rd_cp.c:62
static void vl_api_want_ip6_ra_events_reply_t_handler(vl_api_want_ip6_ra_events_reply_t *mp)
Definition: rd_cp.c:250
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:440
static int create_api_loopback(void)
Definition: rd_cp.c:706
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
Start / stop sending router solicitation.
Definition: ip.api:319
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:542
int i32
Definition: types.h:81
#define clib_error_return(e, args...)
Definition: error.h:99
svm_region_t * vlib_rp
Current binary api segment descriptor.
Definition: api_common.h:252
Enable/disable IPv6 ND address autoconfiguration and setting up default routes.
Definition: rd_cp.api:29
IPv6 interface enable / disable request.
Definition: ip.api:337
static_always_inline void check_queue(void)
Definition: rd_cp.c:125
struct vl_shmem_hdr_ * shmem_hdr
Binary API shared-memory segment header pointer.
Definition: api_common.h:262
i32 retval
Definition: rd_cp.c:68
u8 arrived
Definition: rd_cp.c:67
static_always_inline void send_msg(void *msg)
Definition: rd_cp.c:174
struct rd_cp_main_t::@222 api_reply
vnet_main_t * vnet_main
Definition: rd_cp.c:77
static uword rd_cp_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: rd_cp.c:618
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:952
f64 due_time
Definition: rd_cp.c:42
struct _unformat_input_t unformat_input_t
api_main_t * api_main
Definition: rd_cp.c:78
int message_bounce
do not free message after processing
Definition: api_common.h:130
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:273
#define REPLY_MACRO(t)
u8 events_on
Definition: rd_cp.c:54
Set or delete one or all ip addresses on a specified interface.
Definition: interface.api:179
u8 address_length
Definition: rd_cp.c:33
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:199
#define BAD_SW_IF_INDEX_LABEL
void vl_msg_api_send_shmem(svm_queue_t *q, u8 *elem)
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
svmdb_client_t * c
vlib_main_t * vm
Definition: buffer.c:294
u8 enabled
Definition: rd_cp.c:53
#define clib_warning(format, args...)
Definition: error.h:59
#define clib_memcpy(a, b, c)
Definition: string.h:75
u8 router_address[16]
Definition: ip.api:778
static void vl_api_sw_interface_get_mac_address_reply_t_handler(vl_api_sw_interface_get_mac_address_reply_t *mp)
Definition: rd_cp.c:410
vlib_node_registration_t rd_cp_process_node
(constructor) VLIB_REGISTER_NODE (rd_cp_process_node)
Definition: rd_cp.c:688
svm_queue_t * vl_input_queue
Definition: memory_shared.h:84
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
int replay
is this message to be replayed?
Definition: api_common.h:129
interface_config_t * config_by_sw_if_index
Definition: rd_cp.c:56
Tell client about a router advertisement event.
Definition: ip.api:773
unsigned int u32
Definition: types.h:88
rd_cp_main_t rd_cp_main
Definition: rd_cp.c:82
Reply for get interface&#39;s MAC address request.
Definition: interface.api:380
u32 my_client_index
Definition: rd_cp.c:63
default_route_t * default_route_pool
Definition: rd_cp.c:58
u8 mac_address[6]
Definition: rd_cp.c:71
static_always_inline int wait_for_reply(void)
Definition: rd_cp.c:152
static int remove_default_route(vlib_main_t *vm, default_route_t *default_route)
Definition: rd_cp.c:365
static uword ip6_address_is_link_local_unicast(const ip6_address_t *a)
Definition: ip6_packet.h:297
#define foreach_client_rd_cp_msg
Definition: rd_cp.c:21
u64 uword
Definition: types.h:112
Add / del route request.
Definition: ip.api:391
static uword vnet_sw_interface_is_api_valid(vnet_main_t *vnm, u32 sw_if_index)
static_always_inline int send_msg_and_wait_for_reply(void *msg)
Definition: rd_cp.c:183
unsigned short u16
Definition: types.h:57
Struct representing RA prefix info.
Definition: ip.api:752
static int remove_slaac_address(vlib_main_t *vm, slaac_address_t *slaac_address)
Definition: rd_cp.c:342
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
static int ip6_ra_events_enable_disable(int enable)
Definition: rd_cp.c:228
static void interrupt_process(void)
Definition: rd_cp.c:696
static void vl_api_sw_interface_add_del_address_reply_t_handler(vl_api_sw_interface_add_del_address_reply_t *mp)
Definition: rd_cp.c:294
struct _svm_queue svm_queue_t
u32 node_index
Definition: rd_cp.c:79
static u32 get_interface_mac_address(u32 sw_if_index, u8 mac[])
Definition: rd_cp.c:388
static void vl_api_ip6nd_send_router_solicitation_reply_t_handler(vl_api_ip6nd_send_router_solicitation_reply_t *mp)
Definition: rd_cp.c:219
static int set_address_autoconfig(u32 sw_if_index, u8 enable, u8 install_default_routes)
Definition: rd_cp.c:729
u32 sw_if_index
Definition: rd_cp.c:40
int is_mp_safe
worker thread barrier required?
Definition: api_common.h:131
vhost_vring_addr_t addr
Definition: vhost-user.h:83
f64 due_time
Definition: rd_cp.c:35
#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:483
u32 sw_if_index
Definition: rd_cp.c:32
u8 api_connected
Definition: rd_cp.c:61
static clib_error_t * ip6_nd_address_autoconfig(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: rd_cp.c:797
char * name
the message name
Definition: api_common.h:121
api_main_t api_main
Definition: api_shared.c:35
static void set_handler(int id, char *name, void *handler)
Definition: rd_cp.c:108
void * handler
the message handler
Definition: api_common.h:123
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
pthread_mutex_t mutex
Definition: svm_common.h:37
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
#define VALIDATE_SW_IF_INDEX(mp)
void(** msg_handlers)(void *)
Definition: rd_cp.c:64