FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
node.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  * node.c: srp packet processing
17  *
18  * Copyright (c) 2011 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vlib/vlib.h>
41 #include <vnet/ip/ip_packet.h> /* for ip_csum_fold */
42 #include <vnet/srp/srp.h>
43 
45 
46 typedef struct {
47  u8 packet_data[32];
49 
50 static u8 * format_srp_input_trace (u8 * s, va_list * va)
51 {
52  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
53  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
54  srp_input_trace_t * t = va_arg (*va, srp_input_trace_t *);
55 
56  s = format (s, "%U", format_srp_header, t->packet_data);
57 
58  return s;
59 }
60 
61 typedef enum {
67 
68 typedef struct {
73 
75  [SRP_MODE_reserved0] = {
77  .error = SRP_ERROR_UNKNOWN_MODE,
78  },
79  [SRP_MODE_reserved1] = {
80  .next_index = SRP_INPUT_NEXT_ERROR,
81  .error = SRP_ERROR_UNKNOWN_MODE,
82  },
83  [SRP_MODE_reserved2] = {
84  .next_index = SRP_INPUT_NEXT_ERROR,
85  .error = SRP_ERROR_UNKNOWN_MODE,
86  },
87  [SRP_MODE_reserved3] = {
88  .next_index = SRP_INPUT_NEXT_ERROR,
89  .error = SRP_ERROR_UNKNOWN_MODE,
90  },
91  [SRP_MODE_keep_alive] = {
92  .next_index = SRP_INPUT_NEXT_ERROR,
93  .error = SRP_ERROR_KEEP_ALIVE_DROPPED,
94  },
95  [SRP_MODE_data] = {
96  .next_index = SRP_INPUT_NEXT_ETHERNET_INPUT,
97  .buffer_advance = sizeof (srp_header_t),
98  },
99  [SRP_MODE_control_pass_to_host] = {
100  .next_index = SRP_INPUT_NEXT_CONTROL,
101  },
102  [SRP_MODE_control_locally_buffered_for_host] = {
103  .next_index = SRP_INPUT_NEXT_CONTROL,
104  },
105 };
106 
107 static uword
111 {
112  vnet_main_t * vnm = vnet_get_main();
113  srp_main_t * sm = &srp_main;
114  u32 n_left_from, next_index, * from, * to_next;
115 
117  n_left_from = from_frame->n_vectors;
118 
119  if (node->flags & VLIB_NODE_FLAG_TRACE)
121  from,
122  n_left_from,
123  sizeof (from[0]),
124  sizeof (srp_input_trace_t));
125 
126  next_index = node->cached_next_index;
127 
128  while (n_left_from > 0)
129  {
130  u32 n_left_to_next;
131 
132  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
133 
134  while (n_left_from >= 4 && n_left_to_next >= 2)
135  {
136  u32 bi0, bi1, sw_if_index0, sw_if_index1;
137  vlib_buffer_t * b0, * b1;
138  u8 next0, next1, error0, error1;
139  srp_header_t * s0, * s1;
140  srp_input_disposition_t * d0, * d1;
141  vnet_hw_interface_t * hi0, * hi1;
142  srp_interface_t * si0, * si1;
143 
144  /* Prefetch next iteration. */
145  {
146  vlib_buffer_t * b2, * b3;
147 
148  b2 = vlib_get_buffer (vm, from[2]);
149  b3 = vlib_get_buffer (vm, from[3]);
150 
151  vlib_prefetch_buffer_header (b2, LOAD);
152  vlib_prefetch_buffer_header (b3, LOAD);
153 
154  CLIB_PREFETCH (b2->data, sizeof (srp_header_t), LOAD);
155  CLIB_PREFETCH (b3->data, sizeof (srp_header_t), LOAD);
156  }
157 
158  bi0 = from[0];
159  bi1 = from[1];
160  to_next[0] = bi0;
161  to_next[1] = bi1;
162  from += 2;
163  to_next += 2;
164  n_left_to_next -= 2;
165  n_left_from -= 2;
166 
167  b0 = vlib_get_buffer (vm, bi0);
168  b1 = vlib_get_buffer (vm, bi1);
169 
170  s0 = vlib_buffer_get_current (b0);
171  s1 = vlib_buffer_get_current (b1);
172 
173  /* Data packets are always assigned to side A (outer ring) interface. */
174  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
175  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
176 
177  hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
178  hi1 = vnet_get_sup_hw_interface (vnm, sw_if_index1);
179 
180  si0 = pool_elt_at_index (sm->interface_pool, hi0->hw_instance);
181  si1 = pool_elt_at_index (sm->interface_pool, hi1->hw_instance);
182 
183  sw_if_index0 = (s0->mode == SRP_MODE_data
185  : sw_if_index0);
186  sw_if_index1 = (s1->mode == SRP_MODE_data
188  : sw_if_index1);
189 
190  vnet_buffer (b0)->sw_if_index[VLIB_RX] = sw_if_index0;
191  vnet_buffer (b1)->sw_if_index[VLIB_RX] = sw_if_index1;
192 
193  d0 = srp_input_disposition_by_mode + s0->mode;
194  d1 = srp_input_disposition_by_mode + s1->mode;
195 
196  next0 = d0->next_index;
197  next1 = d1->next_index;
198 
199  error0 = d0->error;
200  error1 = d1->error;
201 
204 
205  b0->error = node->errors[error0];
206  b1->error = node->errors[error1];
207 
209  to_next, n_left_to_next,
210  bi0, bi1, next0, next1);
211  }
212 
213  while (n_left_from > 0 && n_left_to_next > 0)
214  {
215  u32 bi0, sw_if_index0;
216  vlib_buffer_t * b0;
217  u8 next0, error0;
218  srp_header_t * s0;
220  srp_interface_t * si0;
221  vnet_hw_interface_t * hi0;
222 
223  bi0 = from[0];
224  to_next[0] = bi0;
225  from += 1;
226  to_next += 1;
227  n_left_to_next -= 1;
228  n_left_from -= 1;
229 
230  b0 = vlib_get_buffer (vm, bi0);
231 
232  s0 = vlib_buffer_get_current (b0);
233 
234  /* Data packets are always assigned to side A (outer ring) interface. */
235  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
236 
237  hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
238 
239  si0 = pool_elt_at_index (sm->interface_pool, hi0->hw_instance);
240 
241  sw_if_index0 = (s0->mode == SRP_MODE_data
243  : sw_if_index0);
244 
245  vnet_buffer (b0)->sw_if_index[VLIB_RX] = sw_if_index0;
246 
247  d0 = srp_input_disposition_by_mode + s0->mode;
248 
249  next0 = d0->next_index;
250 
251  error0 = d0->error;
252 
254 
255  b0->error = node->errors[error0];
256 
258  to_next, n_left_to_next,
259  bi0, next0);
260  }
261 
262  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
263  }
264 
265  return from_frame->n_vectors;
266 }
267 
268 static char * srp_error_strings[] = {
269 #define _(f,s) s,
271 #undef _
272 };
273 
275  .function = srp_input,
276  .name = "srp-input",
277  /* Takes a vector of packets. */
278  .vector_size = sizeof (u32),
279 
280  .n_errors = SRP_N_ERROR,
281  .error_strings = srp_error_strings,
282 
283  .n_next_nodes = SRP_INPUT_N_NEXT,
284  .next_nodes = {
285  [SRP_INPUT_NEXT_ERROR] = "error-drop",
286  [SRP_INPUT_NEXT_ETHERNET_INPUT] = "ethernet-input",
287  [SRP_INPUT_NEXT_CONTROL] = "srp-control",
288  },
289 
290  .format_buffer = format_srp_header_with_length,
291  .format_trace = format_srp_input_trace,
292  .unformat_buffer = unformat_srp_header,
293 };
294 
295 static uword
297 {
298  vnet_main_t * vnm = vnet_get_main();
300  srp_topology_header_t * t;
302  u32 nb, nmb;
303 
304  t = (void *) *contents;
305 
306  nb = clib_net_to_host_u16 (t->n_bytes_of_data_that_follows);
307  nmb = (nb - sizeof (t->originator_address)) / sizeof (mb[0]);
308  if (vec_len (*contents) < sizeof (t[0]) + nmb * sizeof (mb[0]))
309  return SRP_ERROR_TOPOLOGY_BAD_LENGTH;
310 
311  /* Fill in our source MAC address. */
312  clib_memcpy_fast (t->ethernet.src_address, hi->hw_address, vec_len (hi->hw_address));
313 
314  /* Make space for our MAC binding. */
315  vec_resize (*contents, sizeof (srp_topology_mac_binding_t));
316  t = (void *) *contents;
317  t->n_bytes_of_data_that_follows = clib_host_to_net_u16 (nb + sizeof (mb[0]));
318 
319  mb = t->bindings + nmb;
320 
321  mb->flags =
322  ((t->srp.is_inner_ring ? SRP_TOPOLOGY_MAC_BINDING_FLAG_IS_INNER_RING : 0)
323  | (/* is wrapped FIXME */ 0));
324  clib_memcpy_fast (mb->address, hi->hw_address, vec_len (hi->hw_address));
325 
326  t->control.checksum
327  = ~ip_csum_fold (ip_incremental_checksum (0, &t->control,
328  vec_len (*contents) - STRUCT_OFFSET_OF (srp_generic_control_header_t, control)));
329 
330  {
331  vlib_frame_t * f;
332  vlib_buffer_t * b;
333  u32 * to_next;
334  u32 bi = ~0;
335 
336  if (vlib_buffer_add_data (vm, /* buffer to append to */ &bi,
337  *contents, vec_len (*contents)))
338  {
339  /* complete or partial buffer allocation failure */
340  if (bi != ~0)
341  vlib_buffer_free (vm, &bi, 1);
342  return SRP_ERROR_CONTROL_PACKETS_PROCESSED;
343  }
344  b = vlib_get_buffer (vm, bi);
345  vnet_buffer (b)->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
346  f = vlib_get_frame_to_node (vm, hi->output_node_index);
347  to_next = vlib_frame_vector_args (f);
348  to_next[0] = bi;
349  f->n_vectors = 1;
350  vlib_put_frame_to_node (vm, hi->output_node_index, f);
351  }
352 
353  return SRP_ERROR_CONTROL_PACKETS_PROCESSED;
354 }
355 
358  u8 ** contents);
359 
360 static uword
364 {
365  u32 n_left_from, next_index, * from, * to_next;
366  vlib_node_runtime_t * error_node;
367  static u8 * contents;
368 
369  error_node = vlib_node_get_runtime (vm, srp_input_node.index);
370 
372  n_left_from = from_frame->n_vectors;
373 
374  if (node->flags & VLIB_NODE_FLAG_TRACE)
376  from,
377  n_left_from,
378  sizeof (from[0]),
379  sizeof (srp_input_trace_t));
380 
381  next_index = node->cached_next_index;
382 
383  while (n_left_from > 0)
384  {
385  u32 n_left_to_next;
386 
387  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
388 
389  while (n_left_from > 0 && n_left_to_next > 0)
390  {
391  u32 bi0, l2_len0, l3_len0;
392  vlib_buffer_t * b0;
393  u8 next0, error0;
395 
396  bi0 = from[0];
397  to_next[0] = bi0;
398  from += 1;
399  to_next += 1;
400  n_left_to_next -= 1;
401  n_left_from -= 1;
402 
403  b0 = vlib_get_buffer (vm, bi0);
404 
405  s0 = vlib_buffer_get_current(b0);
406  l2_len0 = vlib_buffer_length_in_chain (vm, b0);
407  l3_len0 = l2_len0 - STRUCT_OFFSET_OF (srp_generic_control_header_t, control);
408 
409  error0 = SRP_ERROR_CONTROL_PACKETS_PROCESSED;
410 
411  error0 = s0->control.version != 0 ? SRP_ERROR_CONTROL_VERSION_NON_ZERO : error0;
412 
413  {
414  u16 save0 = s0->control.checksum;
415  u16 computed0;
416  s0->control.checksum = 0;
417  computed0 = ~ip_csum_fold (ip_incremental_checksum (0, &s0->control, l3_len0));
418  error0 = save0 != computed0 ? SRP_ERROR_CONTROL_BAD_CHECKSUM : error0;
419  }
420 
421  if (error0 == SRP_ERROR_CONTROL_PACKETS_PROCESSED)
422  {
424  [SRP_CONTROL_PACKET_TYPE_topology] = srp_topology_packet,
425  };
427 
428  f = 0;
429  if (s0->control.type < ARRAY_LEN (t))
430  f = t[s0->control.type];
431 
432  if (f)
433  {
434  vec_validate (contents, l2_len0 - 1);
435  vlib_buffer_contents (vm, bi0, contents);
436  error0 = f (vm, vnet_buffer (b0)->sw_if_index[VLIB_RX], &contents);
437  }
438  else
439  error0 = SRP_ERROR_UNKNOWN_CONTROL;
440  }
441 
442  b0->error = error_node->errors[error0];
443  next0 = 0;
444 
446  to_next, n_left_to_next,
447  bi0, next0);
448  }
449 
450  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
451  }
452 
453  return from_frame->n_vectors;
454 }
455 
457  .function = srp_control_input,
458  .name = "srp-control",
459  /* Takes a vector of packets. */
460  .vector_size = sizeof (u32),
461 
462  .n_next_nodes = 1,
463  .next_nodes = {
464  [0] = "error-drop",
465  },
466 
467  .format_buffer = format_srp_header_with_length,
468  .format_trace = format_srp_input_trace,
469  .unformat_buffer = unformat_srp_header,
470 };
471 
472 static u8 * format_srp_ips_request_type (u8 * s, va_list * args)
473 {
474  u32 x = va_arg (*args, u32);
475  char * t = 0;
476  switch (x)
477  {
478 #define _(f,n) case SRP_IPS_REQUEST_##f: t = #f; break;
480 #undef _
481  default:
482  return format (s, "unknown 0x%x", x);
483  }
484  return format (s, "%U", format_c_identifier, t);
485 }
486 
487 static u8 * format_srp_ips_status (u8 * s, va_list * args)
488 {
489  u32 x = va_arg (*args, u32);
490  char * t = 0;
491  switch (x)
492  {
493 #define _(f,n) case SRP_IPS_STATUS_##f: t = #f; break;
495 #undef _
496  default:
497  return format (s, "unknown 0x%x", x);
498  }
499  return format (s, "%U", format_c_identifier, t);
500 }
501 
502 static u8 * format_srp_ips_state (u8 * s, va_list * args)
503 {
504  u32 x = va_arg (*args, u32);
505  char * t = 0;
506  switch (x)
507  {
508 #define _(f) case SRP_IPS_STATE_##f: t = #f; break;
510 #undef _
511  default:
512  return format (s, "unknown 0x%x", x);
513  }
514  return format (s, "%U", format_c_identifier, t);
515 }
516 
517 static u8 * format_srp_ring (u8 * s, va_list * args)
518 {
519  u32 ring = va_arg (*args, u32);
520  return format (s, "%s", ring == SRP_RING_INNER ? "inner" : "outer");
521 }
522 
523 static u8 * format_srp_ips_header (u8 * s, va_list * args)
524 {
525  srp_ips_header_t * h = va_arg (*args, srp_ips_header_t *);
526 
527  s = format (s, "%U, %U, %U, %s-path",
528  format_srp_ips_request_type, h->request_type,
529  format_ethernet_address, h->originator_address,
530  format_srp_ips_status, h->status,
531  h->is_long_path ? "long" : "short");
532 
533  return s;
534 }
535 
536 static u8 * format_srp_interface (u8 * s, va_list * args)
537 {
538  srp_interface_t * si = va_arg (*args, srp_interface_t *);
540 
541  s = format (s, "address %U, IPS state %U",
542  format_ethernet_address, si->my_address,
543  format_srp_ips_state, si->current_ips_state);
544  for (ir = si->rings; ir < si->rings + SRP_N_RING; ir++)
546  s = format (s, ", %U neighbor %U",
547  format_srp_ring, ir->ring,
549 
550  return s;
551 }
552 
553 u8 * format_srp_device (u8 * s, va_list * args)
554 {
555  u32 hw_if_index = va_arg (*args, u32);
556  CLIB_UNUSED (int verbose) = va_arg (*args, int);
557  vnet_main_t * vnm = vnet_get_main();
558  srp_main_t * sm = &srp_main;
559  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
560  srp_interface_t * si = pool_elt_at_index (sm->interface_pool, hi->hw_instance);
561  return format (s, "%U", format_srp_interface, si);
562 }
563 
566 {
567  vnet_main_t * vnm = vnet_get_main();
568  srp_main_t * sm = &srp_main;
571 
572  ASSERT (hi->hw_class_index == srp_hw_interface_class.index);
573  si = pool_elt_at_index (sm->interface_pool, hi->hw_instance);
574 
575  ASSERT (si->rings[SRP_RING_INNER].hw_if_index == hi->hw_if_index
576  || si->rings[SRP_RING_OUTER].hw_if_index == hi->hw_if_index);
577  if (ring)
578  *ring =
579  (hi->hw_if_index == si->rings[SRP_RING_INNER].hw_if_index
581  : SRP_RING_OUTER);
582 
583  return si;
584 }
585 
587  srp_ring_type_t tx_ring,
589 {
590  clib_memset (i, 0, sizeof (i[0]));
591 
592  i->srp.ttl = 1;
593  i->srp.is_inner_ring = tx_ring;
594  i->srp.priority = 7;
595  i->srp.mode = SRP_MODE_control_locally_buffered_for_host;
597 
598  clib_memcpy_fast (&i->ethernet.src_address, &si->my_address, sizeof (si->my_address));
599  i->ethernet.type = clib_host_to_net_u16 (ETHERNET_TYPE_SRP_CONTROL);
600 
601  /* Checksum will be filled in later. */
602  i->control.version = 0;
603  i->control.type = SRP_CONTROL_PACKET_TYPE_ips;
604  i->control.ttl = 255;
605 
606  clib_memcpy_fast (&i->originator_address, &si->my_address, sizeof (si->my_address));
607 }
608 
610  srp_ring_type_t tx_ring,
612 {
613  srp_main_t * sm = &srp_main;
614  vnet_main_t * vnm = vnet_get_main();
615  vlib_main_t * vm = sm->vlib_main;
616  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, si->rings[tx_ring].hw_if_index);
617  vlib_frame_t * f;
618  vlib_buffer_t * b;
619  u32 * to_next, bi = ~0;
620 
621  if (! vnet_sw_interface_is_admin_up (vnm, hi->sw_if_index))
622  return;
623  if (hi->hw_class_index != srp_hw_interface_class.index)
624  return;
625 
626  i->control.checksum
627  = ~ip_csum_fold (ip_incremental_checksum (0, &i->control,
628  sizeof (i[0]) - STRUCT_OFFSET_OF (srp_ips_header_t, control)));
629 
630  if (vlib_buffer_add_data (vm, /* buffer to append to */ &bi, i,
631  sizeof (i[0])))
632  {
633  /* complete or partial allocation failure */
634  if (bi != ~0)
635  vlib_buffer_free (vm, &bi, 1);
636  return;
637  }
638 
639  /* FIXME trace. */
640  if (0)
641  clib_warning ("%U %U",
642  format_vnet_sw_if_index_name, vnm, hi->sw_if_index,
644 
645  b = vlib_get_buffer (vm, bi);
646  vnet_buffer (b)->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_TX] = hi->sw_if_index;
647 
648  f = vlib_get_frame_to_node (vm, hi->output_node_index);
649  to_next = vlib_frame_vector_args (f);
650  to_next[0] = bi;
651  f->n_vectors = 1;
652  vlib_put_frame_to_node (vm, hi->output_node_index, f);
653 }
654 
656 {
657  static u8 t[16] = {
658  [SRP_IPS_REQUEST_forced_switch] = 1,
659  [SRP_IPS_REQUEST_manual_switch] = 1,
660  [SRP_IPS_REQUEST_signal_fail] = 1,
661  [SRP_IPS_REQUEST_signal_degrade] = 1,
662  };
663  return (int) r < ARRAY_LEN (t) ? t[r] : 0;
664 }
665 
666 /* Called when an IPS control packet is received on given interface. */
668 {
669  vnet_main_t * vnm = vnet_get_main();
671  srp_ring_type_t rx_ring;
673  srp_interface_ring_t * ir = &si->rings[rx_ring];
674 
675  /* FIXME trace. */
676  if (0)
677  clib_warning ("%U %U %U",
678  format_time_interval, "h:m:s:u", vlib_time_now (vm),
681 
682  /* Ignore self-generated IPS packets. */
683  if (! memcmp (h->originator_address, si->my_address, sizeof (h->originator_address)))
684  goto done;
685 
686  /* Learn neighbor address from short path messages. */
687  if (! h->is_long_path)
688  {
690  && memcmp (ir->rx_neighbor_address, h->originator_address, sizeof (ir->rx_neighbor_address)))
691  {
692  ASSERT (0);
693  }
695  clib_memcpy_fast (ir->rx_neighbor_address, h->originator_address, sizeof (ir->rx_neighbor_address));
696  }
697 
698  switch (si->current_ips_state)
699  {
700  case SRP_IPS_STATE_idle:
701  /* Received {REQ,NEIGHBOR,W,S} in idle state: wrap. */
702  if (requests_switch (h->request_type)
703  && ! h->is_long_path
704  && h->status == SRP_IPS_STATUS_wrapped)
705  {
706  srp_ips_header_t to_tx[2];
707 
708  si->current_ips_state = SRP_IPS_STATE_wrapped;
709  si->hw_wrap_function (si->rings[SRP_SIDE_A].hw_if_index, /* enable_wrap */ 1);
710  si->hw_wrap_function (si->rings[SRP_SIDE_B].hw_if_index, /* enable_wrap */ 1);
711 
712  init_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
713  to_tx[0].request_type = SRP_IPS_REQUEST_idle;
714  to_tx[0].status = SRP_IPS_STATUS_wrapped;
715  to_tx[0].is_long_path = 0;
716  tx_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
717 
718  init_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
719  to_tx[1].request_type = h->request_type;
720  to_tx[1].status = SRP_IPS_STATUS_wrapped;
721  to_tx[1].is_long_path = 1;
722  tx_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
723  }
724  break;
725 
726  case SRP_IPS_STATE_wrapped:
727  if (! h->is_long_path
728  && h->request_type == SRP_IPS_REQUEST_idle
729  && h->status == SRP_IPS_STATUS_idle)
730  {
731  si->current_ips_state = SRP_IPS_STATE_idle;
732  si->hw_wrap_function (si->rings[SRP_SIDE_A].hw_if_index, /* enable_wrap */ 0);
733  si->hw_wrap_function (si->rings[SRP_SIDE_B].hw_if_index, /* enable_wrap */ 0);
734  }
735  break;
736 
737  case SRP_IPS_STATE_pass_thru:
738  /* FIXME */
739  break;
740 
741  default:
742  abort ();
743  break;
744  }
745  done:
746  ;
747 }
748 
749 /* Preform local IPS request on given interface. */
751 {
752  vnet_main_t * vnm = vnet_get_main();
753  srp_main_t * sm = &srp_main;
754  srp_ring_type_t rx_ring;
756  srp_interface_ring_t * ir = &si->rings[rx_ring];
757 
758  if (request == SRP_IPS_REQUEST_wait_to_restore)
759  {
760  if (si->current_ips_state != SRP_IPS_STATE_wrapped)
761  return;
762  if (! ir->waiting_to_restore)
763  {
765  ir->waiting_to_restore = 1;
766  }
767  }
768  else
769  {
770  /* FIXME handle local signal fail. */
772  ir->waiting_to_restore = 0;
773  }
774 
775  /* FIXME trace. */
776  if (0)
777  clib_warning ("%U %U",
780 
781 }
782 
784 {
785  srp_main_t * sm = &srp_main;
786  srp_ips_header_t to_tx[2];
788  srp_interface_ring_t * r0 = &si->rings[rx_ring ^ 0];
789  srp_interface_ring_t * r1 = &si->rings[rx_ring ^ 1];
790  f64 now = vlib_time_now (sm->vlib_main);
791 
792  if (! si->ips_process_enable)
793  return;
794 
795  if (si->current_ips_state == SRP_IPS_STATE_wrapped
796  && r0->waiting_to_restore
797  && r1->waiting_to_restore
798  && now >= r0->wait_to_restore_start_time + si->config.wait_to_restore_idle_delay
799  && now >= r1->wait_to_restore_start_time + si->config.wait_to_restore_idle_delay)
800  {
801  si->current_ips_state = SRP_IPS_STATE_idle;
804  }
805 
806  if (si->current_ips_state != SRP_IPS_STATE_idle)
807  return;
808 
809  init_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
810  init_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
811 
812  if (si->current_ips_state == SRP_IPS_STATE_idle)
813  {
814  to_tx[0].request_type = to_tx[1].request_type = SRP_IPS_REQUEST_idle;
815  to_tx[0].status = to_tx[1].status = SRP_IPS_STATUS_idle;
816  to_tx[0].is_long_path = to_tx[1].is_long_path = 0;
817  }
818 
819  else if (si->current_ips_state == SRP_IPS_STATE_wrapped)
820  {
821  to_tx[0].request_type =
822  (si->rings[rx_ring ^ 0].waiting_to_restore
823  ? SRP_IPS_REQUEST_wait_to_restore
824  : SRP_IPS_REQUEST_signal_fail);
825  to_tx[1].request_type =
826  (si->rings[rx_ring ^ 1].waiting_to_restore
827  ? SRP_IPS_REQUEST_wait_to_restore
828  : SRP_IPS_REQUEST_signal_fail);
829  to_tx[0].status = to_tx[1].status = SRP_IPS_STATUS_wrapped;
830  to_tx[0].is_long_path = 0;
831  to_tx[1].is_long_path = 1;
832  }
833 
834  tx_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
835  tx_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
836 }
837 
838 static uword
841  vlib_frame_t * f)
842 {
843  srp_main_t * sm = &srp_main;
845 
846  while (1)
847  {
850  }
851  vlib_process_suspend (vm, 1.0);
852  }
853 
854  return 0;
855 }
856 
858  .function = srp_ips_process,
859  .type = VLIB_NODE_TYPE_PROCESS,
860  .name = "srp-ips-process",
861  .state = VLIB_NODE_STATE_DISABLED,
862 };
863 
865 {
866  srp_main_t * sm = &srp_main;
867 
868  sm->default_data_ttl = 255;
869  sm->vlib_main = vm;
874 
875  return 0;
876 }
877 
srp_topology_mac_binding_t::address
u8 address[6]
Definition: packet.h:136
vlib.h
vlib_frame_t::n_vectors
u16 n_vectors
Definition: node.h:387
vlib_buffer_free
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:982
srp_interface_t::rings
srp_interface_ring_t rings[SRP_N_RING]
Definition: srp.h:115
foreach_srp_ips_request_type
@ foreach_srp_ips_request_type
Definition: packet.h:164
srp_ips_process_node
vlib_node_registration_t srp_ips_process_node
Definition: node.c:857
srp_ring_type_t
srp_ring_type_t
Definition: srp.h:63
foreach_srp_ips_state
#define foreach_srp_ips_state
Definition: srp.h:51
srp_main_t
Definition: srp.h:125
vlib_prefetch_buffer_header
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
srp_topology_packet
static uword srp_topology_packet(vlib_main_t *vm, u32 sw_if_index, u8 **contents)
Definition: node.c:296
srp_main_t::vlib_main
vlib_main_t * vlib_main
Definition: srp.h:126
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
vlib_get_buffer
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
srp.h
f
vlib_frame_t * f
Definition: interface_output.c:1080
srp_generic_control_header_t
Definition: packet.h:124
srp_input_node
static vlib_node_registration_t srp_input_node
Definition: node.c:274
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
format_srp_input_trace
static u8 * format_srp_input_trace(u8 *s, va_list *va)
Definition: node.c:50
maybe_send_ips_message
static void maybe_send_ips_message(srp_interface_t *si)
Definition: node.c:783
format_ethernet_address
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
vlib_trace_frame_buffers_only
void vlib_trace_frame_buffers_only(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, uword n_buffers, uword next_buffer_stride, uword n_buffer_data_bytes_in_trace)
Definition: trace.c:48
srp_input_disposition_t::buffer_advance
u8 buffer_advance
Definition: node.c:70
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
SRP_INPUT_NEXT_ERROR
@ SRP_INPUT_NEXT_ERROR
Definition: node.c:62
srp_header_t
Definition: packet.h:66
u16
unsigned short u16
Definition: types.h:57
srp_interface_ring_t::sw_if_index
u32 sw_if_index
Definition: srp.h:79
format_srp_interface
static u8 * format_srp_interface(u8 *s, va_list *args)
Definition: node.c:536
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
srp_get_interface
static srp_interface_t * srp_get_interface(u32 sw_if_index, srp_ring_type_t *ring)
Definition: node.c:565
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
foreach_srp_ips_status
@ foreach_srp_ips_status
Definition: packet.h:174
srp_input_trace_t::packet_data
u8 packet_data[32]
Definition: node.c:47
srp_ips_header_t
Definition: packet.h:178
from_frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * from_frame
Definition: esp_encrypt.c:1328
ip_packet.h
hi
vl_api_ip4_address_t hi
Definition: arp.api:37
SRP_RING_OUTER
@ SRP_RING_OUTER
Definition: srp.h:64
srp_main_t::default_data_ttl
u32 default_data_ttl
Definition: srp.h:134
r
vnet_hw_if_output_node_runtime_t * r
Definition: interface_output.c:1071
vlib_frame_t
Definition: node.h:372
vlib_get_frame_to_node
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:184
vlib_buffer_length_in_chain
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:433
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
srp_control_handler_function_t
uword() srp_control_handler_function_t(vlib_main_t *vm, u32 sw_if_index, u8 **contents)
Definition: node.c:356
srp_main_t::interface_pool
srp_interface_t * interface_pool
Definition: srp.h:129
h
h
Definition: flowhash_template.h:372
srp_error_strings
static char * srp_error_strings[]
Definition: node.c:268
format_srp_device
u8 * format_srp_device(u8 *s, va_list *args)
Definition: node.c:553
srp_input_disposition_t::next_index
u8 next_index
Definition: node.c:69
srp_interface_ring_t::rx_neighbor_address_valid
u8 rx_neighbor_address_valid
Definition: srp.h:84
CLIB_PREFETCH
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
STRUCT_OFFSET_OF
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:73
vlib_put_frame_to_node
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:218
vlib_node_runtime_t::errors
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:460
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
SRP_INPUT_N_NEXT
@ SRP_INPUT_N_NEXT
Definition: node.c:65
vlib_buffer_advance
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
vlib_buffer_t::error
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
SRP_N_ERROR
@ SRP_N_ERROR
Definition: srp.h:217
vlib_buffer_contents
static uword vlib_buffer_contents(vlib_main_t *vm, u32 buffer_index, u8 *contents)
Copy buffer contents to memory.
Definition: buffer_funcs.h:467
srp_interface_ring_t::wait_to_restore_start_time
f64 wait_to_restore_start_time
Definition: srp.h:90
SRP_N_RING
@ SRP_N_RING
Definition: srp.h:66
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:437
format_srp_header_with_length
u8 * format_srp_header_with_length(u8 *s, va_list *args)
Definition: format.c:63
vnet_get_hw_interface
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface_funcs.h:44
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
ip_incremental_checksum
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:319
srp_topology_mac_binding_t::flags
u8 flags
Definition: packet.h:131
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
srp_init
static clib_error_t * srp_init(vlib_main_t *vm)
Definition: node.c:864
srp_input_disposition_t::error
u16 error
Definition: node.c:71
uword
u64 uword
Definition: types.h:112
srp_hw_interface_class
vnet_hw_interface_class_t srp_hw_interface_class
format_srp_ips_request_type
static u8 * format_srp_ips_request_type(u8 *s, va_list *args)
Definition: node.c:472
i
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
f64
double f64
Definition: types.h:142
format_time_interval
u8 * format_time_interval(u8 *s, va_list *args)
Definition: std-formats.c:138
srp_generic_control_header_t::control
srp_control_header_t control
Definition: packet.h:127
srp_header_compute_parity
static void srp_header_compute_parity(srp_header_t *h)
Definition: packet.h:89
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
srp_input_disposition_by_mode
static srp_input_disposition_t srp_input_disposition_by_mode[8]
Definition: node.c:74
foreach_srp_error
#define foreach_srp_error
Definition: srp.h:202
srp_input_trace_t
Definition: node.c:46
srp_ips_local_request
void srp_ips_local_request(u32 sw_if_index, srp_ips_request_type_t request)
Definition: node.c:750
srp_input_disposition_t
Definition: node.c:68
SRP_INPUT_NEXT_CONTROL
@ SRP_INPUT_NEXT_CONTROL
Definition: node.c:64
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
vnet_sw_interface_is_admin_up
static uword vnet_sw_interface_is_admin_up(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface_funcs.h:265
srp_interface_t
Definition: srp.h:105
format_srp_ring
static u8 * format_srp_ring(u8 *s, va_list *args)
Definition: node.c:517
srp_ips_process
static uword srp_ips_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: node.c:839
format_srp_header
u8 * format_srp_header(u8 *s, va_list *args)
Definition: format.c:104
request
vhost_user_req_t request
Definition: vhost_user.h:123
init_ips_packet
static void init_ips_packet(srp_interface_t *si, srp_ring_type_t tx_ring, srp_ips_header_t *i)
Definition: node.c:586
vnet_hw_interface_t
Definition: interface.h:638
vnet_main_t
Definition: vnet.h:76
vlib_validate_buffer_enqueue_x1
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
srp_interface_ring_t::ring
srp_ring_type_t ring
Definition: srp.h:73
srp_ips_request_type_t
srp_ips_request_type_t
Definition: packet.h:162
vnet_hw_interface_t::hw_instance
u32 hw_instance
Definition: interface.h:664
format_vnet_sw_if_index_name
format_function_t format_vnet_sw_if_index_name
Definition: interface_funcs.h:455
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
format_c_identifier
u8 * format_c_identifier(u8 *s, va_list *va)
Definition: std-formats.c:329
SRP_INPUT_NEXT_ETHERNET_INPUT
@ SRP_INPUT_NEXT_ETHERNET_INPUT
Definition: node.c:63
format_srp_ips_status
static u8 * format_srp_ips_status(u8 *s, va_list *args)
Definition: node.c:487
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
vlib_process_suspend
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:486
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
vnet_get_sup_hw_interface
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface_funcs.h:92
srp_interface_ring_t
Definition: srp.h:72
si
vnet_sw_interface_t * si
Definition: interface_output.c:398
requests_switch
static int requests_switch(srp_ips_request_type_t r)
Definition: node.c:655
VLIB_NODE_TYPE_PROCESS
@ VLIB_NODE_TYPE_PROCESS
Definition: node.h:84
srp_control_input
static uword srp_control_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: node.c:361
vlib_node_get_runtime
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:116
srp_main
srp_main_t srp_main
Definition: node.c:44
vec_resize
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V,...
Definition: vec.h:296
srp_setup_node
static void srp_setup_node(vlib_main_t *vm, u32 node_index)
Definition: srp.h:193
srp_control_input_node
static vlib_node_registration_t srp_control_input_node
Definition: node.c:456
now
f64 now
Definition: nat44_ei_out2in.c:710
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
vlib_node_t
Definition: node.h:247
format_srp_ips_header
static u8 * format_srp_ips_header(u8 *s, va_list *args)
Definition: node.c:523
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
srp_interface_ring_t::rx_neighbor_address
u8 rx_neighbor_address[6]
Definition: srp.h:82
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
rt
vnet_interface_output_runtime_t * rt
Definition: interface_output.c:399
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
vlib_buffer_t::data
u8 data[]
Packet data.
Definition: buffer.h:204
SRP_RING_INNER
@ SRP_RING_INNER
Definition: srp.h:65
clib_warning
#define clib_warning(format, args...)
Definition: error.h:59
SRP_N_CONTROL_PACKET_TYPE
@ SRP_N_CONTROL_PACKET_TYPE
Definition: packet.h:109
vnet_sw_interface_t::hw_if_index
u32 hw_if_index
Definition: interface.h:886
vlib_register_node
u32 vlib_register_node(vlib_main_t *vm, vlib_node_registration_t *r)
Definition: node.c:519
tx_ips_packet
static void tx_ips_packet(srp_interface_t *si, srp_ring_type_t tx_ring, srp_ips_header_t *i)
Definition: node.c:609
SRP_SIDE_B
@ SRP_SIDE_B
Definition: srp.h:68
vlib_validate_buffer_enqueue_x2
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
srp_interface_ring_t::waiting_to_restore
u8 waiting_to_restore
Definition: srp.h:87
srp_input_next_t
srp_input_next_t
Definition: node.c:61
vlib_time_now
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:325
srp_topology_mac_binding_t
Definition: packet.h:130
vlib_buffer_add_data
int vlib_buffer_add_data(vlib_main_t *vm, u32 *buffer_index, void *data, u32 n_data_bytes)
Definition: buffer.c:398
vlib_node_runtime_t
Definition: node.h:454
SRP_SIDE_A
@ SRP_SIDE_A
Definition: srp.h:67
srp_input
static uword srp_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: node.c:108
unformat_srp_header
uword unformat_srp_header(unformat_input_t *input, va_list *args)
Definition: format.c:111
from
from
Definition: nat44_ei_hairpinning.c:415
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
vlib_get_next_frame
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:395
ip_csum_fold
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:301
SRP_TOPOLOGY_MAC_BINDING_FLAG_IS_INNER_RING
#define SRP_TOPOLOGY_MAC_BINDING_FLAG_IS_INNER_RING
Definition: packet.h:132
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
format_srp_ips_state
static u8 * format_srp_ips_state(u8 *s, va_list *args)
Definition: node.c:502
srp_ips_rx_packet
void srp_ips_rx_packet(u32 sw_if_index, srp_ips_header_t *h)
Definition: node.c:667
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111