FD.io VPP  v21.06
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 
316  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
317  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
318  vnet_buffer (b)->sw_if_index[VLIB_TX] = vr->config.sw_if_index;
319 
320  if (is_unicast)
321  {
322  dst = vec_elt_at_index (vr->config.peer_addrs, i);
323  vnet_buffer (b)->sw_if_index[VLIB_TX] = ~0;
324  }
325  else
327 
328  vrrp_adv_l3_build (vr, b, dst);
329  vrrp_adv_payload_build (vr, b, shutdown);
330 
331  vlib_buffer_reset (b);
332 
333  to_next[i] = bi0;
334  }
335 
336  to_frame->n_vectors = n_buffers;
337 
338  vlib_put_frame_to_node (vm, node_index, to_frame);
339 
340  vec_free (bi);
341 
342  return 0;
343 }
344 
345 static void
346 vrrp6_na_pkt_build (vrrp_vr_t * vr, vlib_buffer_t * b, ip6_address_t * addr6)
347 {
348  vnet_main_t *vnm = vnet_get_main ();
350  ethernet_header_t *eth;
351  ip6_header_t *ip6;
352  icmp6_neighbor_solicitation_or_advertisement_header_t *na;
353  icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *ll_opt;
354  int payload_length, bogus_length;
355  int rewrite_bytes = 0;
356  u8 *rewrite;
357  u8 dst_mac[6];
358 
359  /* L2 headers */
360  eth = vlib_buffer_get_current (b);
361 
362  ip6_multicast_ethernet_address (dst_mac, IP6_MULTICAST_GROUP_ID_all_hosts);
363  rewrite =
365  dst_mac);
366  rewrite_bytes += vec_len (rewrite);
367  clib_memcpy (eth, rewrite, vec_len (rewrite));
368  vec_free (rewrite);
369 
370  b->current_length += rewrite_bytes;
371  vlib_buffer_advance (b, rewrite_bytes);
372 
373  /* IPv6 */
374  ip6 = vlib_buffer_get_current (b);
375 
376  b->current_length += sizeof (*ip6);
377  clib_memset (ip6, 0, sizeof (*ip6));
378 
379  ip6->ip_version_traffic_class_and_flow_label = 0x00000060;
380  ip6->protocol = IP_PROTOCOL_ICMP6;
381  ip6->hop_limit = 255;
383  IP6_MULTICAST_SCOPE_link_local,
384  IP6_MULTICAST_GROUP_ID_all_hosts);
387 
388 
389  /* ICMPv6 */
390  na = (icmp6_neighbor_solicitation_or_advertisement_header_t *) (ip6 + 1);
391  ll_opt =
392  (icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *) (na +
393  1);
394 
395  payload_length = sizeof (*na) + sizeof (*ll_opt);
396  b->current_length += payload_length;
397  clib_memset (na, 0, payload_length);
398 
399  na->icmp.type = ICMP6_neighbor_advertisement; /* icmp code, csum are 0 */
400  na->target_address = *addr6;
401  na->advertisement_flags = clib_host_to_net_u32
404 
405  ll_opt->header.type =
406  ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address;
407  ll_opt->header.n_data_u64s = 1;
408  clib_memcpy (ll_opt->ethernet_address, vr->runtime.mac.bytes,
409  sizeof (vr->runtime.mac));
410 
411  ip6->payload_length = clib_host_to_net_u16 (payload_length);
412  na->icmp.checksum =
413  ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6, &bogus_length);
414 }
415 
416 const mac_address_t broadcast_mac = {
417  .bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,},
418 };
419 
420 static void
422 {
423  vnet_main_t *vnm = vnet_get_main ();
424  ethernet_header_t *eth;
426  int rewrite_bytes;
427  u8 *rewrite;
428 
429  eth = vlib_buffer_get_current (b);
430 
431  rewrite =
433  broadcast_mac.bytes);
434  rewrite_bytes = vec_len (rewrite);
435  clib_memcpy (eth, rewrite, rewrite_bytes);
436  vec_free (rewrite);
437 
438  b->current_length += rewrite_bytes;
439  vlib_buffer_advance (b, rewrite_bytes);
440 
441  arp = vlib_buffer_get_current (b);
442  b->current_length += sizeof (*arp);
443 
444  clib_memset (arp, 0, sizeof (*arp));
445 
446  arp->l2_type = clib_host_to_net_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet);
447  arp->l3_type = clib_host_to_net_u16 (ETHERNET_TYPE_IP4);
448  arp->n_l2_address_bytes = 6;
449  arp->n_l3_address_bytes = 4;
450  arp->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
451  arp->ip4_over_ethernet[0].mac = vr->runtime.mac;
452  arp->ip4_over_ethernet[0].ip4 = *ip4;
453  arp->ip4_over_ethernet[1].mac = broadcast_mac;
454  arp->ip4_over_ethernet[1].ip4 = *ip4;
455 }
456 
457 int
459 {
461  vrrp_main_t *vmp = &vrrp_main;
462  vlib_frame_t *to_frame;
463  u32 *bi = 0;
464  u32 n_buffers;
465  u32 *to_next;
466  int i;
467 
468  if (vec_len (vr->config.peer_addrs))
469  return 0; /* unicast is used in routed environments - don't garp */
470 
471  n_buffers = vec_len (vr->config.vr_addrs);
472  if (!n_buffers)
473  {
474  clib_warning ("Unable to send gratuitous ARP for VR %U - no addresses",
475  format_vrrp_vr_key, vr);
476  return -1;
477  }
478 
479  /* need to send a packet for each VR address */
480  vec_validate (bi, n_buffers - 1);
481 
482  if (vlib_buffer_alloc (vm, bi, n_buffers) != n_buffers)
483  {
484  clib_warning ("Buffer allocation failed for %U", format_vrrp_vr_key,
485  vr);
486  vec_free (bi);
487  return -1;
488  }
489 
490  to_frame = vlib_get_frame_to_node (vm, vmp->intf_output_node_idx);
491  to_frame->n_vectors = 0;
492  to_next = vlib_frame_vector_args (to_frame);
493 
494  for (i = 0; i < n_buffers; i++)
495  {
496  vlib_buffer_t *b;
497  ip46_address_t *addr;
498 
499  addr = vec_elt_at_index (vr->config.vr_addrs, i);
500  b = vlib_get_buffer (vm, bi[i]);
501 
502  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
503  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
504  vnet_buffer (b)->sw_if_index[VLIB_TX] = vr->config.sw_if_index;
505 
506  if (vrrp_vr_is_ipv6 (vr))
507  vrrp6_na_pkt_build (vr, b, &addr->ip6);
508  else
509  vrrp4_garp_pkt_build (vr, b, &addr->ip4);
510 
511  vlib_buffer_reset (b);
512 
513  to_next[i] = bi[i];
514  to_frame->n_vectors++;
515  }
516 
517  vlib_put_frame_to_node (vm, vmp->intf_output_node_idx, to_frame);
518 
519  return 0;
520 }
521 
522 #define IGMP4_MCAST_ADDR_AS_U8 { 224, 0, 0, 22 }
523 
524 static const ip4_header_t igmp_ip4_mcast = {
525  .ip_version_and_header_length = 0x46, /* there's options! */
526  .ttl = 1,
527  .protocol = IP_PROTOCOL_IGMP,
528  .tos = 0xc0,
529  .dst_address = {.as_u8 = IGMP4_MCAST_ADDR_AS_U8,},
530 };
531 
532 static void
534 {
535  ip4_header_t *ip4;
536  u8 *ip4_options;
539 
540  ip4 = vlib_buffer_get_current (b);
541  clib_memcpy (ip4, &igmp_ip4_mcast, sizeof (*ip4));
542  fib_sas4_get (vr->config.sw_if_index, NULL, &ip4->src_address);
543 
544  vlib_buffer_chain_increase_length (b, b, sizeof (*ip4));
545  vlib_buffer_advance (b, sizeof (*ip4));
546 
547  ip4_options = (u8 *) (ip4 + 1);
548  ip4_options[0] = 0x94; /* 10010100 == the router alert option */
549  ip4_options[1] = 0x04; /* length == 4 bytes */
550  ip4_options[2] = 0x0; /* value == Router shall examine packet */
551  ip4_options[3] = 0x0; /* reserved */
552 
554  vlib_buffer_advance (b, 4);
555 
556  report = vlib_buffer_get_current (b);
557 
558  report->header.type = IGMP_TYPE_membership_report_v3;
559  report->header.code = 0;
560  report->header.checksum = 0;
561  report->unused = 0;
562  report->n_groups = clib_host_to_net_u16 (1);
563 
564  vlib_buffer_chain_increase_length (b, b, sizeof (*report));
565  vlib_buffer_advance (b, sizeof (*report));
566 
567  group = vlib_buffer_get_current (b);
568  group->type = IGMP_MEMBERSHIP_GROUP_change_to_exclude;
569  group->n_aux_u32s = 0;
570  group->n_src_addresses = 0;
571  group->group_address.as_u32 = clib_host_to_net_u32 (0xe0000012);
572 
573  vlib_buffer_chain_increase_length (b, b, sizeof (*group));
574  vlib_buffer_advance (b, sizeof (*group));
575 
576  ip4->length = clib_host_to_net_u16 (b->current_data);
577  ip4->checksum = ip4_header_checksum (ip4);
578 
579  int payload_len = vlib_buffer_get_current (b) - ((void *) report);
580  report->header.checksum =
581  ~ip_csum_fold (ip_incremental_checksum (0, report, payload_len));
582 
583  vlib_buffer_reset (b);
584 }
585 
586 /* multicast listener report packet format for ethernet. */
587 typedef CLIB_PACKED (struct
588  {
589  ip6_hop_by_hop_ext_t ext_hdr;
590  ip6_router_alert_option_t alert;
591  ip6_padN_option_t pad;
592  icmp46_header_t icmp;
593  u16 rsvd;
594  u16 num_addr_records;
595  icmp6_multicast_address_record_t records[0];
596  }) icmp6_multicast_listener_report_header_t;
597 
598 static void
599 vrrp_icmp6_mlr_pkt_build (vrrp_vr_t * vr, vlib_buffer_t * b)
600 {
602  ip6_header_t *ip6;
603  icmp6_multicast_listener_report_header_t *rh;
604  icmp6_multicast_address_record_t *rr;
605  ip46_address_t *vr_addr;
606  int bogus_length, n_addrs;
607  u16 payload_length;
608 
609  n_addrs = vec_len (vr->config.vr_addrs) + 1;
610  payload_length = sizeof (*rh) + (n_addrs * sizeof (*rr));
611  b->current_length = sizeof (*ip6) + payload_length;
612  b->error = ICMP6_ERROR_NONE;
613 
614  ip6 = vlib_buffer_get_current (b);
615  rh = (icmp6_multicast_listener_report_header_t *) (ip6 + 1);
616  rr = (icmp6_multicast_address_record_t *) (rh + 1);
617 
618  /* IP header */
619  clib_memset (ip6, 0, b->current_length);
621  clib_host_to_net_u32 (0x60000000);
622  ip6->hop_limit = 1;
623  ip6->protocol = IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS;
625  IP6_MULTICAST_SCOPE_link_local,
626  IP6_MULTICAST_GROUP_ID_mldv2_routers);
629 
630  clib_memset (rh, 0, sizeof (*rh));
631 
632  /* v6 hop by hop extension header */
633  rh->ext_hdr.next_hdr = IP_PROTOCOL_ICMP6;
634  rh->ext_hdr.n_data_u64s = 0;
635 
636  rh->alert.type = IP6_MLDP_ALERT_TYPE;
637  rh->alert.len = 2;
638  rh->alert.value = 0;
639 
640  rh->pad.type = 1;
641  rh->pad.len = 0;
642 
643  /* icmp6 header */
644  rh->icmp.type = ICMP6_multicast_listener_report_v2;
645  rh->icmp.checksum = 0;
646 
647  rh->rsvd = 0;
648  rh->num_addr_records = clib_host_to_net_u16 (n_addrs);
649 
650  /* group addresses */
651 
652  /* All VRRP routers group */
653  rr->type = 4;
654  rr->aux_data_len_u32s = 0;
655  rr->num_sources = 0;
657  (&rr->mcast_addr, &vrrp6_mcast_addr.ip6, sizeof (ip6_address_t));
658 
659  /* solicited node multicast addresses for VR addrs */
660  vec_foreach (vr_addr, vr->config.vr_addrs)
661  {
662  u32 id;
663 
664  rr++;
665  rr->type = 4;
666  rr->aux_data_len_u32s = 0;
667  rr->num_sources = 0;
668 
669  id = clib_net_to_host_u32 (vr_addr->ip6.as_u32[3]) & 0x00ffffff;
670  ip6_set_solicited_node_multicast_address (&rr->mcast_addr, id);
671  }
672 
673  ip6->payload_length = clib_host_to_net_u16 (payload_length);
674  rh->icmp.checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ip6,
675  &bogus_length);
676 }
677 
678 int
680 {
682  vlib_buffer_t *b;
683  vlib_frame_t *f;
684  vnet_main_t *vnm = vnet_get_main ();
685  vrrp_intf_t *intf;
686  u32 bi = 0, *to_next;
687  int n_buffers = 1;
688  u8 is_ipv6;
689  u32 node_index;
690 
692  return 0;
693 
694  if (vlib_buffer_alloc (vm, &bi, n_buffers) != n_buffers)
695  {
696  clib_warning ("Buffer allocation failed for %U", format_vrrp_vr_key,
697  vr);
698  return -1;
699  }
700 
701  is_ipv6 = vrrp_vr_is_ipv6 (vr);
702 
703  b = vlib_get_buffer (vm, bi);
704 
705  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
706 
707  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
708  vnet_buffer (b)->sw_if_index[VLIB_TX] = vr->config.sw_if_index;
709 
710  intf = vrrp_intf_get (vr->config.sw_if_index);
711  vnet_buffer (b)->ip.adj_index[VLIB_TX] = intf->mcast_adj_index[is_ipv6];
712 
713  if (is_ipv6)
714  {
715  vrrp_icmp6_mlr_pkt_build (vr, b);
716  node_index = ip6_rewrite_mcast_node.index;
717  }
718  else
719  {
720  vrrp_igmp_pkt_build (vr, b);
721  node_index = ip4_rewrite_mcast_node.index;
722  }
723 
724  f = vlib_get_frame_to_node (vm, node_index);
725  to_next = vlib_frame_vector_args (f);
726  to_next[0] = bi;
727  f->n_vectors = 1;
728 
729  vlib_put_frame_to_node (vm, node_index, f);
730 
731  return f->n_vectors;
732 }
733 
734 
735 /*
736  * fd.io coding-style-patch-verification: ON
737  *
738  * Local Variables:
739  * eval: (c-set-style "gnu")
740  * End:
741  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:524
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:133
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:305
ip4_address_t src_address
Definition: ip4_packet.h:125
Definition: vrrp.h:106
adj_index_t mcast_adj_index[2]
Definition: vrrp.h:138
u32 n_bytes
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:119
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:122
uword ip_csum_t
Definition: ip_packet.h:245
static ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
Definition: ip_packet.h:248
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:130
ip6_address_t src_address
Definition: ip6_packet.h:310
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
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
unsigned int u32
Definition: types.h:88
#define clib_memcpy(d, s, n)
Definition: string.h:197
vlib_node_registration_t ip4_rewrite_mcast_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_mcast_node)
Definition: ip4_forward.c:2641
vlib_node_registration_t ip6_rewrite_mcast_node
(constructor) VLIB_REGISTER_NODE (ip6_rewrite_mcast_node)
Definition: ip6_forward.c:2229
vlib_frame_t * f
#define static_always_inline
Definition: clib.h:112
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:184
vnet_main_t * vnet_get_main(void)
int vrrp_vr_multicast_group_join(vrrp_vr_t *vr)
Definition: vrrp_packet.c:679
static const ip46_address_t vrrp4_mcast_addr
Definition: vrrp_packet.c:81
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:145
const mac_address_t broadcast_mac
Definition: vrrp_packet.c:416
#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:708
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:218
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
vl_api_mac_address_t src_addr
Definition: flow_types.api:64
u8 vr_id
Definition: vrrp.h:72
vl_api_ip4_address_t ip4
Definition: one.api:376
vrrp_vr_runtime_t runtime
Definition: vrrp.h:109
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
igmp_type_t type
Definition: igmp_packet.h:70
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:587
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:388
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
#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:533
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:421
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:1098
vlib_node_registration_t ip6_lookup_node
(constructor) VLIB_REGISTER_NODE (ip6_lookup_node)
Definition: ip6_forward.c:741
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.
#define always_inline
Definition: rdma_mlx5dv.h:23
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:276
u32 n_buffers
#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:38
int vrrp_garp_or_na_send(vrrp_vr_t *vr)
Definition: vrrp_packet.c:458
#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:522
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:346
VLIB buffer representation.
Definition: buffer.h:111
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:301
node node_index
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:437
static const u8 vrrp4_dst_mac[6]
Definition: vrrp_packet.c:27
vl_api_ip4_address_t dst
Definition: pnat.api:41
#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:319
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
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:301
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
rewrite
Definition: pnat.api:158