FD.io VPP  v21.01.1
Vector Packet Processing
vrrp_packet.c
Go to the documentation of this file.
1 /*
2  * vrrp.c - vrrp plugin action functions
3  *
4  * Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  */
9 
10 #include <vnet/vnet.h>
11 #include <vnet/plugin/plugin.h>
12 #include <vnet/mfib/mfib_entry.h>
13 #include <vnet/mfib/mfib_table.h>
14 #include <vnet/adj/adj.h>
15 #include <vnet/adj/adj_mcast.h>
16 #include <vnet/fib/fib_table.h>
17 #include <vnet/fib/fib_sas.h>
18 #include <vnet/ip/igmp_packet.h>
19 #include <vnet/ip/ip6_link.h>
21 
22 #include <vrrp/vrrp.h>
23 #include <vrrp/vrrp_packet.h>
24 
25 #include <vpp/app/version.h>
26 
27 static const u8 vrrp4_dst_mac[6] = { 0x1, 0x0, 0x5e, 0x0, 0x0, 0x12 };
28 static const u8 vrrp6_dst_mac[6] = { 0x33, 0x33, 0x0, 0x0, 0x0, 0x12 };
29 static const u8 vrrp_src_mac_prefix[4] = { 0x0, 0x0, 0x5e, 0x0 };
30 
31 static int
33 {
34  vnet_main_t *vnm = vnet_get_main ();
35  vnet_link_t link_type;
36  ethernet_header_t *eth;
37  int n_bytes = 0;
38  const void *dst_mac;
39  u8 mac_byte_ipver;
40  u8 *rewrite;
41 
42  eth = vlib_buffer_get_current (b);
43 
44  if (vrrp_vr_is_ipv6 (vr))
45  {
46  dst_mac = vrrp6_dst_mac;
47  link_type = VNET_LINK_IP6;
48  mac_byte_ipver = 0x2;
49  }
50  else
51  {
52  dst_mac = vrrp4_dst_mac;
53  link_type = VNET_LINK_IP4;
54  mac_byte_ipver = 0x1;
55  }
56 
57  rewrite = ethernet_build_rewrite (vnm, vr->config.sw_if_index, link_type,
58  dst_mac);
59  clib_memcpy (eth, rewrite, vec_len (rewrite));
60 
61  /* change the source mac from the HW addr to the VRRP virtual MAC */
63  (eth->src_address, vrrp_src_mac_prefix, sizeof (vrrp_src_mac_prefix));
64  eth->src_address[4] = mac_byte_ipver;
65  eth->src_address[5] = vr->config.vr_id;
66 
67  n_bytes += vec_len (rewrite);
68 
69  vlib_buffer_chain_increase_length (b, b, n_bytes);
70  vlib_buffer_advance (b, n_bytes);
71 
72  vec_free (rewrite);
73 
74  return n_bytes;
75 }
76 
77 #define VRRP4_MCAST_ADDR_AS_U8 { 224, 0, 0, 18 }
78 #define VRRP6_MCAST_ADDR_AS_U8 \
79 { 0xff, 0x2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x12 }
80 
81 static const ip46_address_t vrrp4_mcast_addr = {
82  .ip4 = {.as_u8 = VRRP4_MCAST_ADDR_AS_U8,},
83 };
84 
85 static const ip46_address_t vrrp6_mcast_addr = {
86  .ip6 = {.as_u8 = VRRP6_MCAST_ADDR_AS_U8,},
87 };
88 
89 /* size of static parts of header + (# addrs * addr length) */
92 {
93  u16 addr_len = vrrp_vr_is_ipv6 (vr) ? 16 : 4;
94 
95  return sizeof (vrrp_header_t) + (vec_len (vr->config.vr_addrs) * addr_len);
96 }
97 
98 static int
100  const ip46_address_t * dst)
101 {
102  if (!vrrp_vr_is_ipv6 (vr)) /* IPv4 */
103  {
105 
106  clib_memset (ip4, 0, sizeof (*ip4));
107  ip4->ip_version_and_header_length = 0x45;
108  ip4->ttl = 255;
109  ip4->protocol = IP_PROTOCOL_VRRP;
110  clib_memcpy (&ip4->dst_address, &dst->ip4, sizeof (dst->ip4));
111  fib_sas4_get (vr->config.sw_if_index, NULL, &ip4->src_address);
112  ip4->length = clib_host_to_net_u16 (sizeof (*ip4) +
113  vrrp_adv_payload_len (vr));
114  ip4->checksum = ip4_header_checksum (ip4);
115 
116  vlib_buffer_chain_increase_length (b, b, sizeof (*ip4));
117  vlib_buffer_advance (b, sizeof (*ip4));
118 
119  return sizeof (*ip4);
120  }
121  else
122  {
124 
125  clib_memset (ip6, 0, sizeof (*ip6));
126  ip6->ip_version_traffic_class_and_flow_label = 0x00000060;
127  ip6->hop_limit = 255;
128  ip6->protocol = IP_PROTOCOL_VRRP;
129  clib_memcpy (&ip6->dst_address, &dst->ip6, sizeof (dst->ip6));
132  ip6->payload_length = clib_host_to_net_u16 (vrrp_adv_payload_len (vr));
133 
134  vlib_buffer_chain_increase_length (b, b, sizeof (*ip6));
135  vlib_buffer_advance (b, sizeof (*ip6));
136 
137  return sizeof (*ip6);
138  }
139 }
140 
141 
142 u16
143 vrrp_adv_csum (void *l3_hdr, void *payload, u8 is_ipv6, u16 len)
144 {
145  ip_csum_t csum = 0;
146  u8 proto = IP_PROTOCOL_VRRP;
147  int addr_len;
148  int word_size = sizeof (uword);
149  void *src_addr;
150  int i;
151 
152  if (is_ipv6)
153  {
154  addr_len = 16;
155  src_addr = &(((ip6_header_t *) l3_hdr)->src_address);
156  }
157  else
158  {
159  addr_len = 4;
160  src_addr = &(((ip4_header_t *) l3_hdr)->src_address);
161  }
162 
163  for (i = 0; i < (2 * addr_len); i += word_size)
164  {
165  if (word_size == sizeof (u64))
166  csum =
167  ip_csum_with_carry (csum, clib_mem_unaligned (src_addr + i, u64));
168  else
169  csum =
170  ip_csum_with_carry (csum, clib_mem_unaligned (src_addr + i, u32));
171  }
172 
173  csum = ip_csum_with_carry (csum,
174  clib_host_to_net_u32 (len + (proto << 16)));
175 
176  /* now do the payload */
177  csum = ip_incremental_checksum (csum, payload, len);
178 
179  csum = ~ip_csum_fold (csum);
180 
181  return (u16) csum;
182 }
183 
184 static int
186 {
187  vrrp_header_t *vrrp = vlib_buffer_get_current (b);
188  void *l3_hdr;
189  ip46_address_t *vr_addr;
190  void *hdr_addr;
191  u8 is_ipv6;
192  u8 n_addrs;
193  int len;
194 
195  n_addrs = vec_len (vr->config.vr_addrs);
196  is_ipv6 = vrrp_vr_is_ipv6 (vr);
197 
198  if (is_ipv6)
199  {
200  ip6_header_t *ip6;
201 
202  len = sizeof (*vrrp) + n_addrs * sizeof (ip6_address_t);;
203  l3_hdr = vlib_buffer_get_current (b) - sizeof (ip6_header_t);
204  ip6 = l3_hdr;
205  ip6->payload_length = clib_host_to_net_u16 (len);
206  }
207  else
208  {
209  len = sizeof (*vrrp) + n_addrs * sizeof (ip4_address_t);
210  l3_hdr = vlib_buffer_get_current (b) - sizeof (ip4_header_t);
211  }
212 
213  vrrp->vrrp_version_and_type = 0x31;
214  vrrp->vr_id = vr->config.vr_id;
215  vrrp->priority = (shutdown) ? 0 : vrrp_vr_priority (vr);
216  vrrp->n_addrs = vec_len (vr->config.vr_addrs);
217  vrrp->rsvd_and_max_adv_int = clib_host_to_net_u16 (vr->config.adv_interval);
218  vrrp->checksum = 0;
219 
220  hdr_addr = (void *) (vrrp + 1);
221 
222  vec_foreach (vr_addr, vr->config.vr_addrs)
223  {
224  if (is_ipv6)
225  {
226  clib_memcpy (hdr_addr, &vr_addr->ip6, 16);
227  hdr_addr += 16;
228  }
229  else
230  {
231  clib_memcpy (hdr_addr, &vr_addr->ip4, 4);
232  hdr_addr += 4;
233  }
234  }
235 
237 
238  vrrp->checksum =
239  vrrp_adv_csum (l3_hdr, vrrp, is_ipv6, vrrp_adv_payload_len (vr));
240 
241  return len;
242 }
243 
246 {
247  if (vrrp_vr_is_unicast (vr))
248  {
249  if (vrrp_vr_is_ipv6 (vr))
250  return ip6_lookup_node.index;
251  else
252  return ip4_lookup_node.index;
253  }
254  else
255  {
256  vrrp_main_t *vmp = &vrrp_main;
257 
258  return vmp->intf_output_node_idx;
259  }
260 }
261 
262 static_always_inline const ip46_address_t *
264 {
265  if (vrrp_vr_is_ipv6 (vr))
266  return &vrrp6_mcast_addr;
267 
268  return &vrrp4_mcast_addr;
269 }
270 
271 int
272 vrrp_adv_send (vrrp_vr_t * vr, int shutdown)
273 {
275  vlib_frame_t *to_frame;
276  int i, n_buffers = 1;
277  u32 node_index, *to_next, *bi = 0;
278  u8 is_unicast = vrrp_vr_is_unicast (vr);
279 
280  node_index = vrrp_adv_next_node (vr);
281 
282  if (is_unicast)
283  n_buffers = vec_len (vr->config.peer_addrs);
284 
285  if (n_buffers < 1)
286  {
287  /* A unicast VR will not start without peers added so this should
288  * not happen. Just avoiding a crash if it happened somehow.
289  */
290  clib_warning ("Unicast VR configuration corrupted for %U",
291  format_vrrp_vr_key, vr);
292  return -1;
293  }
294 
295  vec_validate (bi, n_buffers - 1);
296  if (vlib_buffer_alloc (vm, bi, n_buffers) != n_buffers)
297  {
298  clib_warning ("Buffer allocation failed for %U", format_vrrp_vr_key,
299  vr);
300  vec_free (bi);
301  return -1;
302  }
303 
304  to_frame = vlib_get_frame_to_node (vm, node_index);
305  to_next = vlib_frame_vector_args (to_frame);
306 
307  for (i = 0; i < n_buffers; i++)
308  {
309  vlib_buffer_t *b;
310  u32 bi0;
311  const ip46_address_t *dst = vrrp_adv_mcast_addr (vr);
312 
313  bi0 = vec_elt (bi, i);
314  b = vlib_get_buffer (vm, bi0);
315 
317  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
318  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
319  vnet_buffer (b)->sw_if_index[VLIB_TX] = vr->config.sw_if_index;
320 
321  if (is_unicast)
322  {
323  dst = vec_elt_at_index (vr->config.peer_addrs, i);
324  vnet_buffer (b)->sw_if_index[VLIB_TX] = ~0;
325  }
326  else
328 
329  vrrp_adv_l3_build (vr, b, dst);
330  vrrp_adv_payload_build (vr, b, shutdown);
331 
332  vlib_buffer_reset (b);
333 
334  to_next[i] = bi0;
335  }
336 
337  to_frame->n_vectors = n_buffers;
338 
339  vlib_put_frame_to_node (vm, node_index, to_frame);
340 
341  vec_free (bi);
342 
343  return 0;
344 }
345 
346 static void
347 vrrp6_na_pkt_build (vrrp_vr_t * vr, vlib_buffer_t * b, ip6_address_t * addr6)
348 {
349  vnet_main_t *vnm = vnet_get_main ();
351  ethernet_header_t *eth;
352  ip6_header_t *ip6;
353  icmp6_neighbor_solicitation_or_advertisement_header_t *na;
354  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *ll_opt;
355  int payload_length, bogus_length;
356  int rewrite_bytes = 0;
357  u8 *rewrite;
358  u8 dst_mac[6];
359 
360  /* L2 headers */
361  eth = vlib_buffer_get_current (b);
362 
363  ip6_multicast_ethernet_address (dst_mac, IP6_MULTICAST_GROUP_ID_all_hosts);
364  rewrite =
366  dst_mac);
367  rewrite_bytes += vec_len (rewrite);
368  clib_memcpy (eth, rewrite, vec_len (rewrite));
369  vec_free (rewrite);
370 
371  b->current_length += rewrite_bytes;
372  vlib_buffer_advance (b, rewrite_bytes);
373 
374  /* IPv6 */
375  ip6 = vlib_buffer_get_current (b);
376 
377  b->current_length += sizeof (*ip6);
378  clib_memset (ip6, 0, sizeof (*ip6));
379 
380  ip6->ip_version_traffic_class_and_flow_label = 0x00000060;
381  ip6->protocol = IP_PROTOCOL_ICMP6;
382  ip6->hop_limit = 255;
384  IP6_MULTICAST_SCOPE_link_local,
385  IP6_MULTICAST_GROUP_ID_all_hosts);
388 
389 
390  /* ICMPv6 */
391  na = (icmp6_neighbor_solicitation_or_advertisement_header_t *) (ip6 + 1);
392  ll_opt =
393  (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *) (na +
394  1);
395 
396  payload_length = sizeof (*na) + sizeof (*ll_opt);
397  b->current_length += payload_length;
398  clib_memset (na, 0, payload_length);
399 
400  na->icmp.type = ICMP6_neighbor_advertisement; /* icmp code, csum are 0 */
401  na->target_address = *addr6;
402  na->advertisement_flags = clib_host_to_net_u32
405 
406  ll_opt->header.type =
407  ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address;
408  ll_opt->header.n_data_u64s = 1;
409  clib_memcpy (ll_opt->ethernet_address, vr->runtime.mac.bytes,
410  sizeof (vr->runtime.mac));
411 
412  ip6->payload_length = clib_host_to_net_u16 (payload_length);
413  na->icmp.checksum =
414  ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6, &bogus_length);
415 }
416 
417 const mac_address_t broadcast_mac = {
418  .bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,},
419 };
420 
421 static void
423 {
424  vnet_main_t *vnm = vnet_get_main ();
425  ethernet_header_t *eth;
427  int rewrite_bytes;
428  u8 *rewrite;
429 
430  eth = vlib_buffer_get_current (b);
431 
432  rewrite =
434  broadcast_mac.bytes);
435  rewrite_bytes = vec_len (rewrite);
436  clib_memcpy (eth, rewrite, rewrite_bytes);
437  vec_free (rewrite);
438 
439  b->current_length += rewrite_bytes;
440  vlib_buffer_advance (b, rewrite_bytes);
441 
442  arp = vlib_buffer_get_current (b);
443  b->current_length += sizeof (*arp);
444 
445  clib_memset (arp, 0, sizeof (*arp));
446 
447  arp->l2_type = clib_host_to_net_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet);
448  arp->l3_type = clib_host_to_net_u16 (ETHERNET_TYPE_IP4);
449  arp->n_l2_address_bytes = 6;
450  arp->n_l3_address_bytes = 4;
451  arp->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
452  arp->ip4_over_ethernet[0].mac = vr->runtime.mac;
453  arp->ip4_over_ethernet[0].ip4 = *ip4;
454  arp->ip4_over_ethernet[1].mac = broadcast_mac;
455  arp->ip4_over_ethernet[1].ip4 = *ip4;
456 }
457 
458 int
460 {
462  vrrp_main_t *vmp = &vrrp_main;
463  vlib_frame_t *to_frame;
464  u32 *bi = 0;
465  u32 n_buffers;
466  u32 *to_next;
467  int i;
468 
469  if (vec_len (vr->config.peer_addrs))
470  return 0; /* unicast is used in routed environments - don't garp */
471 
472  n_buffers = vec_len (vr->config.vr_addrs);
473  if (!n_buffers)
474  {
475  clib_warning ("Unable to send gratuitous ARP for VR %U - no addresses",
476  format_vrrp_vr_key, vr);
477  return -1;
478  }
479 
480  /* need to send a packet for each VR address */
481  vec_validate (bi, n_buffers - 1);
482 
483  if (vlib_buffer_alloc (vm, bi, n_buffers) != n_buffers)
484  {
485  clib_warning ("Buffer allocation failed for %U", format_vrrp_vr_key,
486  vr);
487  vec_free (bi);
488  return -1;
489  }
490 
491  to_frame = vlib_get_frame_to_node (vm, vmp->intf_output_node_idx);
492  to_frame->n_vectors = 0;
493  to_next = vlib_frame_vector_args (to_frame);
494 
495  for (i = 0; i < n_buffers; i++)
496  {
497  vlib_buffer_t *b;
498  ip46_address_t *addr;
499 
500  addr = vec_elt_at_index (vr->config.vr_addrs, i);
501  b = vlib_get_buffer (vm, bi[i]);
502 
504  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
505  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
506  vnet_buffer (b)->sw_if_index[VLIB_TX] = vr->config.sw_if_index;
507 
508  if (vrrp_vr_is_ipv6 (vr))
509  vrrp6_na_pkt_build (vr, b, &addr->ip6);
510  else
511  vrrp4_garp_pkt_build (vr, b, &addr->ip4);
512 
513  vlib_buffer_reset (b);
514 
515  to_next[i] = bi[i];
516  to_frame->n_vectors++;
517  }
518 
519  vlib_put_frame_to_node (vm, vmp->intf_output_node_idx, to_frame);
520 
521  return 0;
522 }
523 
524 #define IGMP4_MCAST_ADDR_AS_U8 { 224, 0, 0, 22 }
525 
526 static const ip4_header_t igmp_ip4_mcast = {
527  .ip_version_and_header_length = 0x46, /* there's options! */
528  .ttl = 1,
529  .protocol = IP_PROTOCOL_IGMP,
530  .tos = 0xc0,
531  .dst_address = {.as_u8 = IGMP4_MCAST_ADDR_AS_U8,},
532 };
533 
534 static void
536 {
537  ip4_header_t *ip4;
538  u8 *ip4_options;
541 
542  ip4 = vlib_buffer_get_current (b);
543  clib_memcpy (ip4, &igmp_ip4_mcast, sizeof (*ip4));
544  fib_sas4_get (vr->config.sw_if_index, NULL, &ip4->src_address);
545 
546  vlib_buffer_chain_increase_length (b, b, sizeof (*ip4));
547  vlib_buffer_advance (b, sizeof (*ip4));
548 
549  ip4_options = (u8 *) (ip4 + 1);
550  ip4_options[0] = 0x94; /* 10010100 == the router alert option */
551  ip4_options[1] = 0x04; /* length == 4 bytes */
552  ip4_options[2] = 0x0; /* value == Router shall examine packet */
553  ip4_options[3] = 0x0; /* reserved */
554 
556  vlib_buffer_advance (b, 4);
557 
558  report = vlib_buffer_get_current (b);
559 
560  report->header.type = IGMP_TYPE_membership_report_v3;
561  report->header.code = 0;
562  report->header.checksum = 0;
563  report->unused = 0;
564  report->n_groups = clib_host_to_net_u16 (1);
565 
566  vlib_buffer_chain_increase_length (b, b, sizeof (*report));
567  vlib_buffer_advance (b, sizeof (*report));
568 
569  group = vlib_buffer_get_current (b);
570  group->type = IGMP_MEMBERSHIP_GROUP_change_to_exclude;
571  group->n_aux_u32s = 0;
572  group->n_src_addresses = 0;
573  group->group_address.as_u32 = clib_host_to_net_u32 (0xe0000012);
574 
575  vlib_buffer_chain_increase_length (b, b, sizeof (*group));
576  vlib_buffer_advance (b, sizeof (*group));
577 
578  ip4->length = clib_host_to_net_u16 (b->current_data);
579  ip4->checksum = ip4_header_checksum (ip4);
580 
581  int payload_len = vlib_buffer_get_current (b) - ((void *) report);
582  report->header.checksum =
583  ~ip_csum_fold (ip_incremental_checksum (0, report, payload_len));
584 
585  vlib_buffer_reset (b);
586 }
587 
588 /* multicast listener report packet format for ethernet. */
589 typedef CLIB_PACKED (struct
590  {
591  ip6_hop_by_hop_ext_t ext_hdr;
592  ip6_router_alert_option_t alert;
593  ip6_padN_option_t pad;
594  icmp46_header_t icmp;
595  u16 rsvd;
596  u16 num_addr_records;
597  icmp6_multicast_address_record_t records[0];
598  }) icmp6_multicast_listener_report_header_t;
599 
600 static void
601 vrrp_icmp6_mlr_pkt_build (vrrp_vr_t * vr, vlib_buffer_t * b)
602 {
604  ip6_header_t *ip6;
605  icmp6_multicast_listener_report_header_t *rh;
606  icmp6_multicast_address_record_t *rr;
607  ip46_address_t *vr_addr;
608  int bogus_length, n_addrs;
609  u16 payload_length;
610 
611  n_addrs = vec_len (vr->config.vr_addrs) + 1;
612  payload_length = sizeof (*rh) + (n_addrs * sizeof (*rr));
613  b->current_length = sizeof (*ip6) + payload_length;
614  b->error = ICMP6_ERROR_NONE;
615 
616  ip6 = vlib_buffer_get_current (b);
617  rh = (icmp6_multicast_listener_report_header_t *) (ip6 + 1);
618  rr = (icmp6_multicast_address_record_t *) (rh + 1);
619 
620  /* IP header */
621  clib_memset (ip6, 0, b->current_length);
623  clib_host_to_net_u32 (0x60000000);
624  ip6->hop_limit = 1;
625  ip6->protocol = IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS;
627  IP6_MULTICAST_SCOPE_link_local,
628  IP6_MULTICAST_GROUP_ID_mldv2_routers);
631 
632  clib_memset (rh, 0, sizeof (*rh));
633 
634  /* v6 hop by hop extension header */
635  rh->ext_hdr.next_hdr = IP_PROTOCOL_ICMP6;
636  rh->ext_hdr.n_data_u64s = 0;
637 
638  rh->alert.type = IP6_MLDP_ALERT_TYPE;
639  rh->alert.len = 2;
640  rh->alert.value = 0;
641 
642  rh->pad.type = 1;
643  rh->pad.len = 0;
644 
645  /* icmp6 header */
646  rh->icmp.type = ICMP6_multicast_listener_report_v2;
647  rh->icmp.checksum = 0;
648 
649  rh->rsvd = 0;
650  rh->num_addr_records = clib_host_to_net_u16 (n_addrs);
651 
652  /* group addresses */
653 
654  /* All VRRP routers group */
655  rr->type = 4;
656  rr->aux_data_len_u32s = 0;
657  rr->num_sources = 0;
659  (&rr->mcast_addr, &vrrp6_mcast_addr.ip6, sizeof (ip6_address_t));
660 
661  /* solicited node multicast addresses for VR addrs */
662  vec_foreach (vr_addr, vr->config.vr_addrs)
663  {
664  u32 id;
665 
666  rr++;
667  rr->type = 4;
668  rr->aux_data_len_u32s = 0;
669  rr->num_sources = 0;
670 
671  id = clib_net_to_host_u32 (vr_addr->ip6.as_u32[3]) & 0x00ffffff;
672  ip6_set_solicited_node_multicast_address (&rr->mcast_addr, id);
673  }
674 
675  ip6->payload_length = clib_host_to_net_u16 (payload_length);
676  rh->icmp.checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6,
677  &bogus_length);
678 }
679 
680 int
682 {
684  vlib_buffer_t *b;
685  vlib_frame_t *f;
686  vnet_main_t *vnm = vnet_get_main ();
687  vrrp_intf_t *intf;
688  u32 bi = 0, *to_next;
689  int n_buffers = 1;
690  u8 is_ipv6;
691  u32 node_index;
692 
694  return 0;
695 
696  if (vlib_buffer_alloc (vm, &bi, n_buffers) != n_buffers)
697  {
698  clib_warning ("Buffer allocation failed for %U", format_vrrp_vr_key,
699  vr);
700  return -1;
701  }
702 
703  is_ipv6 = vrrp_vr_is_ipv6 (vr);
704 
705  b = vlib_get_buffer (vm, bi);
706 
708  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
709 
710  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
711  vnet_buffer (b)->sw_if_index[VLIB_TX] = vr->config.sw_if_index;
712 
713  intf = vrrp_intf_get (vr->config.sw_if_index);
714  vnet_buffer (b)->ip.adj_index[VLIB_TX] = intf->mcast_adj_index[is_ipv6];
715 
716  if (is_ipv6)
717  {
718  vrrp_icmp6_mlr_pkt_build (vr, b);
719  node_index = ip6_rewrite_mcast_node.index;
720  }
721  else
722  {
723  vrrp_igmp_pkt_build (vr, b);
724  node_index = ip4_rewrite_mcast_node.index;
725  }
726 
727  f = vlib_get_frame_to_node (vm, node_index);
728  to_next = vlib_frame_vector_args (f);
729  to_next[0] = bi;
730  f->n_vectors = 1;
731 
732  vlib_put_frame_to_node (vm, node_index, f);
733 
734  return f->n_vectors;
735 }
736 
737 
738 /*
739  * fd.io coding-style-patch-verification: ON
740  *
741  * Local Variables:
742  * eval: (c-set-style "gnu")
743  * End:
744  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
static uword vnet_sw_interface_is_up(vnet_main_t *vnm, u32 sw_if_index)
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
igmp_membership_group_v3_type_t type
Definition: igmp_packet.h:149
static u8 vrrp_vr_is_unicast(vrrp_vr_t *vr)
Definition: vrrp.h:318
u8 pad[3]
log2 (size of the packing page block)
Definition: bihash_doc.h:61
u32 sw_if_index
Definition: vrrp.h:71
static void vlib_buffer_reset(vlib_buffer_t *b)
Reset current header & length to state they were in when packet was received.
Definition: buffer.h:281
ip4_address_t src_address
Definition: ip4_packet.h:125
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
Definition: vrrp.h:106
adj_index_t mcast_adj_index[2]
Definition: vrrp.h:138
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
unsigned long u64
Definition: types.h:89
static const u8 vrrp_src_mac_prefix[4]
Definition: vrrp_packet.c:29
#define ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static void vlib_buffer_chain_increase_length(vlib_buffer_t *first, vlib_buffer_t *last, i32 len)
u8 src_address[6]
Definition: packet.h:56
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
uword ip_csum_t
Definition: ip_packet.h:246
vlib_main_t * vm
Definition: in2out_ed.c:1580
static ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
Definition: ip_packet.h:249
static int vrrp_adv_payload_build(vrrp_vr_t *vr, vlib_buffer_t *b, int shutdown)
Definition: vrrp_packet.c:185
vhost_vring_addr_t addr
Definition: vhost_user.h:111
ip6_address_t src_address
Definition: ip6_packet.h:310
unsigned char u8
Definition: types.h:56
u8 id[64]
Definition: dhcp.api:160
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:104
#define clib_memcpy(d, s, n)
Definition: string.h:180
vlib_node_registration_t ip4_rewrite_mcast_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_mcast_node)
Definition: ip4_forward.c:2653
vlib_node_registration_t ip6_rewrite_mcast_node
(constructor) VLIB_REGISTER_NODE (ip6_rewrite_mcast_node)
Definition: ip6_forward.c:2224
#define static_always_inline
Definition: clib.h:109
static int vrrp_adv_l3_build(vrrp_vr_t *vr, vlib_buffer_t *b, const ip46_address_t *dst)
Definition: vrrp_packet.c:99
ethernet_arp_ip4_over_ethernet_address_t ip4_over_ethernet[2]
Definition: arp_packet.h:142
#define VRRP4_MCAST_ADDR_AS_U8
Definition: vrrp_packet.c:77
vl_api_ip6_address_t ip6
Definition: one.api:424
#define ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE
ip4_address_t dst_address
Definition: ip4_packet.h:125
vrrp_vr_config_t config
Definition: vrrp.h:108
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:182
const cJSON *const b
Definition: cJSON.h:255
int vrrp_vr_multicast_group_join(vrrp_vr_t *vr)
Definition: vrrp_packet.c:681
static const ip46_address_t vrrp4_mcast_addr
Definition: vrrp_packet.c:81
unsigned int u32
Definition: types.h:88
mac_address_t mac
Definition: vrrp.h:100
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
const mac_address_t broadcast_mac
Definition: vrrp_packet.c:417
#define VRRP6_MCAST_ADDR_AS_U8
Definition: vrrp_packet.c:78
u8 * format_vrrp_vr_key(u8 *s, va_list *args)
Definition: vrrp_format.c:65
vl_api_ip_proto_t proto
Definition: acl_types.api:51
icmp
Definition: map.api:387
static __clib_warn_unused_result u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:677
unsigned short u16
Definition: types.h:57
#define IP6_MLDP_ALERT_TYPE
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:216
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
vl_api_mac_address_t src_addr
Definition: flow_types.api:64
u8 vr_id
Definition: vrrp.h:72
#define always_inline
Definition: ipsec.h:28
vl_api_ip4_address_t ip4
Definition: one.api:376
vrrp_vr_runtime_t runtime
Definition: vrrp.h:109
igmp_type_t type
Definition: igmp_packet.h:70
vl_api_address_t dst
Definition: gre.api:55
typedef CLIB_PACKED(struct { ip6_hop_by_hop_ext_t ext_hdr;ip6_router_alert_option_t alert;ip6_padN_option_t pad;icmp46_header_t icmp;u16 rsvd;u16 num_addr_records;icmp6_multicast_address_record_t records[0];})
Definition: vrrp_packet.c:589
static u8 vrrp_vr_is_ipv6(vrrp_vr_t *vr)
Definition: vrrp.h:312
u8 len
Definition: ip_types.api:103
u16 n_vectors
Definition: node.h:397
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
#define clib_warning(format, args...)
Definition: error.h:59
static const u8 vrrp6_dst_mac[6]
Definition: vrrp_packet.c:28
static int vrrp_adv_l2_build_multicast(vrrp_vr_t *vr, vlib_buffer_t *b)
Definition: vrrp_packet.c:32
static void vrrp_igmp_pkt_build(vrrp_vr_t *vr, vlib_buffer_t *b)
Definition: vrrp_packet.c:535
static u8 vrrp_vr_priority(vrrp_vr_t *vr)
Definition: vrrp.h:356
static void vrrp4_garp_pkt_build(vrrp_vr_t *vr, vlib_buffer_t *b, ip4_address_t *ip4)
Definition: vrrp_packet.c:422
vrrp_main_t vrrp_main
Definition: vrrp.c:25
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:1099
vlib_node_registration_t ip6_lookup_node
(constructor) VLIB_REGISTER_NODE (ip6_lookup_node)
Definition: ip6_forward.c:742
u32 intf_output_node_idx
Definition: vrrp.h:175
int vrrp_adv_send(vrrp_vr_t *vr, int shutdown)
Definition: vrrp_packet.c:272
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
static u16 vrrp_adv_payload_len(vrrp_vr_t *vr)
Definition: vrrp_packet.c:91
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:252
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
ip4_address_t group_address
Definition: igmp_packet.h:158
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
int vrrp_garp_or_na_send(vrrp_vr_t *vr)
Definition: vrrp_packet.c:459
#define vec_elt(v, i)
Get vector value at index i.
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:297
Definition: defs.h:47
u16 payload_length
Definition: ip6_packet.h:301
#define IGMP4_MCAST_ADDR_AS_U8
Definition: vrrp_packet.c:524
static vrrp_intf_t * vrrp_intf_get(u32 sw_if_index)
Definition: vrrp.h:289
static_always_inline u32 vrrp_adv_next_node(vrrp_vr_t *vr)
Definition: vrrp_packet.c:245
static void ip6_set_solicited_node_multicast_address(ip6_address_t *a, u32 id)
Definition: ip6_packet.h:144
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
bool fib_sas4_get(u32 sw_if_index, const ip4_address_t *dst, ip4_address_t *src)
Get an IPv4 Source address to use in a packet being sent out an interface.
Definition: fib_sas.c:50
static const ip46_address_t vrrp6_mcast_addr
Definition: vrrp_packet.c:85
static void vrrp6_na_pkt_build(vrrp_vr_t *vr, vlib_buffer_t *b, ip6_address_t *addr6)
Definition: vrrp_packet.c:347
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:497
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
u8 * ethernet_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
build a rewrite string to use for sending packets of type &#39;link_type&#39; to &#39;dst_address&#39; ...
Definition: interface.c:83
static void ip6_address_copy(ip6_address_t *dst, const ip6_address_t *src)
Definition: ip6_packet.h:127
#define vnet_buffer(b)
Definition: buffer.h:417
static const u8 vrrp4_dst_mac[6]
Definition: vrrp_packet.c:27
#define vec_foreach(var, vec)
Vector iterator.
ip46_address_t * vr_addrs
Definition: vrrp.h:76
bool is_ipv6
Definition: dhcp.api:202
static void ip6_multicast_ethernet_address(u8 *ethernet_address, u32 group_id)
Definition: ip6_packet.h:156
u8 ip_version_and_header_length
Definition: ip4_packet.h:93
u16 adv_interval
Definition: vrrp.h:74
ip46_address_t * peer_addrs
Definition: vrrp.h:77
u16 vrrp_adv_csum(void *l3_hdr, void *payload, u8 is_ipv6, u16 len)
Definition: vrrp_packet.c:143
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:320
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:314
static_always_inline const ip46_address_t * vrrp_adv_mcast_addr(vrrp_vr_t *vr)
Definition: vrrp_packet.c:263
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:302
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:310
static void ip6_set_reserved_multicast_address(ip6_address_t *a, ip6_multicast_address_scope_t scope, u16 id)
Definition: ip6_packet.h:134