FD.io VPP  v21.10.1-2-g0a485f517
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 #include <vnet/pg/pg.h>
44 
46 
47 typedef struct {
48  u8 packet_data[32];
50 
51 static u8 * format_srp_input_trace (u8 * s, va_list * va)
52 {
53  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
54  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
55  srp_input_trace_t * t = va_arg (*va, srp_input_trace_t *);
56 
57  s = format (s, "%U", format_srp_header, t->packet_data);
58 
59  return s;
60 }
61 
62 typedef enum {
68 
69 typedef struct {
74 
76  [SRP_MODE_reserved0] = {
78  .error = SRP_ERROR_UNKNOWN_MODE,
79  },
80  [SRP_MODE_reserved1] = {
81  .next_index = SRP_INPUT_NEXT_ERROR,
82  .error = SRP_ERROR_UNKNOWN_MODE,
83  },
84  [SRP_MODE_reserved2] = {
85  .next_index = SRP_INPUT_NEXT_ERROR,
86  .error = SRP_ERROR_UNKNOWN_MODE,
87  },
88  [SRP_MODE_reserved3] = {
89  .next_index = SRP_INPUT_NEXT_ERROR,
90  .error = SRP_ERROR_UNKNOWN_MODE,
91  },
92  [SRP_MODE_keep_alive] = {
93  .next_index = SRP_INPUT_NEXT_ERROR,
94  .error = SRP_ERROR_KEEP_ALIVE_DROPPED,
95  },
96  [SRP_MODE_data] = {
97  .next_index = SRP_INPUT_NEXT_ETHERNET_INPUT,
98  .buffer_advance = sizeof (srp_header_t),
99  },
100  [SRP_MODE_control_pass_to_host] = {
101  .next_index = SRP_INPUT_NEXT_CONTROL,
102  },
103  [SRP_MODE_control_locally_buffered_for_host] = {
104  .next_index = SRP_INPUT_NEXT_CONTROL,
105  },
106 };
107 
108 static uword
112 {
113  vnet_main_t * vnm = vnet_get_main();
114  srp_main_t * sm = &srp_main;
115  u32 n_left_from, next_index, * from, * to_next;
116 
118  n_left_from = from_frame->n_vectors;
119 
120  if (node->flags & VLIB_NODE_FLAG_TRACE)
122  from,
123  n_left_from,
124  sizeof (from[0]),
125  sizeof (srp_input_trace_t));
126 
127  next_index = node->cached_next_index;
128 
129  while (n_left_from > 0)
130  {
131  u32 n_left_to_next;
132 
133  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
134 
135  while (n_left_from >= 4 && n_left_to_next >= 2)
136  {
137  u32 bi0, bi1, sw_if_index0, sw_if_index1;
138  vlib_buffer_t * b0, * b1;
139  u8 next0, next1, error0, error1;
140  srp_header_t * s0, * s1;
141  srp_input_disposition_t * d0, * d1;
142  vnet_hw_interface_t * hi0, * hi1;
143  srp_interface_t * si0, * si1;
144 
145  /* Prefetch next iteration. */
146  {
147  vlib_buffer_t * b2, * b3;
148 
149  b2 = vlib_get_buffer (vm, from[2]);
150  b3 = vlib_get_buffer (vm, from[3]);
151 
152  vlib_prefetch_buffer_header (b2, LOAD);
153  vlib_prefetch_buffer_header (b3, LOAD);
154 
155  CLIB_PREFETCH (b2->data, sizeof (srp_header_t), LOAD);
156  CLIB_PREFETCH (b3->data, sizeof (srp_header_t), LOAD);
157  }
158 
159  bi0 = from[0];
160  bi1 = from[1];
161  to_next[0] = bi0;
162  to_next[1] = bi1;
163  from += 2;
164  to_next += 2;
165  n_left_to_next -= 2;
166  n_left_from -= 2;
167 
168  b0 = vlib_get_buffer (vm, bi0);
169  b1 = vlib_get_buffer (vm, bi1);
170 
171  s0 = vlib_buffer_get_current (b0);
172  s1 = vlib_buffer_get_current (b1);
173 
174  /* Data packets are always assigned to side A (outer ring) interface. */
175  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
176  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
177 
178  hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
179  hi1 = vnet_get_sup_hw_interface (vnm, sw_if_index1);
180 
181  si0 = pool_elt_at_index (sm->interface_pool, hi0->hw_instance);
182  si1 = pool_elt_at_index (sm->interface_pool, hi1->hw_instance);
183 
184  sw_if_index0 = (s0->mode == SRP_MODE_data
186  : sw_if_index0);
187  sw_if_index1 = (s1->mode == SRP_MODE_data
189  : sw_if_index1);
190 
191  vnet_buffer (b0)->sw_if_index[VLIB_RX] = sw_if_index0;
192  vnet_buffer (b1)->sw_if_index[VLIB_RX] = sw_if_index1;
193 
194  d0 = srp_input_disposition_by_mode + s0->mode;
195  d1 = srp_input_disposition_by_mode + s1->mode;
196 
197  next0 = d0->next_index;
198  next1 = d1->next_index;
199 
200  error0 = d0->error;
201  error1 = d1->error;
202 
205 
206  b0->error = node->errors[error0];
207  b1->error = node->errors[error1];
208 
210  to_next, n_left_to_next,
211  bi0, bi1, next0, next1);
212  }
213 
214  while (n_left_from > 0 && n_left_to_next > 0)
215  {
216  u32 bi0, sw_if_index0;
217  vlib_buffer_t * b0;
218  u8 next0, error0;
219  srp_header_t * s0;
221  srp_interface_t * si0;
222  vnet_hw_interface_t * hi0;
223 
224  bi0 = from[0];
225  to_next[0] = bi0;
226  from += 1;
227  to_next += 1;
228  n_left_to_next -= 1;
229  n_left_from -= 1;
230 
231  b0 = vlib_get_buffer (vm, bi0);
232 
233  s0 = vlib_buffer_get_current (b0);
234 
235  /* Data packets are always assigned to side A (outer ring) interface. */
236  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
237 
238  hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
239 
240  si0 = pool_elt_at_index (sm->interface_pool, hi0->hw_instance);
241 
242  sw_if_index0 = (s0->mode == SRP_MODE_data
244  : sw_if_index0);
245 
246  vnet_buffer (b0)->sw_if_index[VLIB_RX] = sw_if_index0;
247 
248  d0 = srp_input_disposition_by_mode + s0->mode;
249 
250  next0 = d0->next_index;
251 
252  error0 = d0->error;
253 
255 
256  b0->error = node->errors[error0];
257 
259  to_next, n_left_to_next,
260  bi0, next0);
261  }
262 
263  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
264  }
265 
266  return from_frame->n_vectors;
267 }
268 
269 static char * srp_error_strings[] = {
270 #define _(f,s) s,
272 #undef _
273 };
274 
276  .function = srp_input,
277  .name = "srp-input",
278  /* Takes a vector of packets. */
279  .vector_size = sizeof (u32),
280 
281  .n_errors = SRP_N_ERROR,
282  .error_strings = srp_error_strings,
283 
284  .n_next_nodes = SRP_INPUT_N_NEXT,
285  .next_nodes = {
286  [SRP_INPUT_NEXT_ERROR] = "error-drop",
287  [SRP_INPUT_NEXT_ETHERNET_INPUT] = "ethernet-input",
288  [SRP_INPUT_NEXT_CONTROL] = "srp-control",
289  },
290 
291  .format_buffer = format_srp_header_with_length,
292  .format_trace = format_srp_input_trace,
293  .unformat_buffer = unformat_srp_header,
294 };
295 
296 static uword
298 {
299  vnet_main_t * vnm = vnet_get_main();
301  srp_topology_header_t * t;
303  u32 nb, nmb;
304 
305  t = (void *) *contents;
306 
307  nb = clib_net_to_host_u16 (t->n_bytes_of_data_that_follows);
308  nmb = (nb - sizeof (t->originator_address)) / sizeof (mb[0]);
309  if (vec_len (*contents) < sizeof (t[0]) + nmb * sizeof (mb[0]))
310  return SRP_ERROR_TOPOLOGY_BAD_LENGTH;
311 
312  /* Fill in our source MAC address. */
313  clib_memcpy_fast (t->ethernet.src_address, hi->hw_address, vec_len (hi->hw_address));
314 
315  /* Make space for our MAC binding. */
316  vec_resize (*contents, sizeof (srp_topology_mac_binding_t));
317  t = (void *) *contents;
318  t->n_bytes_of_data_that_follows = clib_host_to_net_u16 (nb + sizeof (mb[0]));
319 
320  mb = t->bindings + nmb;
321 
322  mb->flags =
323  ((t->srp.is_inner_ring ? SRP_TOPOLOGY_MAC_BINDING_FLAG_IS_INNER_RING : 0)
324  | (/* is wrapped FIXME */ 0));
325  clib_memcpy_fast (mb->address, hi->hw_address, vec_len (hi->hw_address));
326 
327  t->control.checksum
328  = ~ip_csum_fold (ip_incremental_checksum (0, &t->control,
329  vec_len (*contents) - STRUCT_OFFSET_OF (srp_generic_control_header_t, control)));
330 
331  {
332  vlib_frame_t * f;
333  vlib_buffer_t * b;
334  u32 * to_next;
335  u32 bi = ~0;
336 
337  if (vlib_buffer_add_data (vm, /* buffer to append to */ &bi,
338  *contents, vec_len (*contents)))
339  {
340  /* complete or partial buffer allocation failure */
341  if (bi != ~0)
342  vlib_buffer_free (vm, &bi, 1);
343  return SRP_ERROR_CONTROL_PACKETS_PROCESSED;
344  }
345  b = vlib_get_buffer (vm, bi);
346  vnet_buffer (b)->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
347  f = vlib_get_frame_to_node (vm, hi->output_node_index);
348  to_next = vlib_frame_vector_args (f);
349  to_next[0] = bi;
350  f->n_vectors = 1;
351  vlib_put_frame_to_node (vm, hi->output_node_index, f);
352  }
353 
354  return SRP_ERROR_CONTROL_PACKETS_PROCESSED;
355 }
356 
359  u8 ** contents);
360 
361 static uword
365 {
366  u32 n_left_from, next_index, * from, * to_next;
367  vlib_node_runtime_t * error_node;
368  static u8 * contents;
369 
370  error_node = vlib_node_get_runtime (vm, srp_input_node.index);
371 
373  n_left_from = from_frame->n_vectors;
374 
375  if (node->flags & VLIB_NODE_FLAG_TRACE)
377  from,
378  n_left_from,
379  sizeof (from[0]),
380  sizeof (srp_input_trace_t));
381 
382  next_index = node->cached_next_index;
383 
384  while (n_left_from > 0)
385  {
386  u32 n_left_to_next;
387 
388  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
389 
390  while (n_left_from > 0 && n_left_to_next > 0)
391  {
392  u32 bi0, l2_len0, l3_len0;
393  vlib_buffer_t * b0;
394  u8 next0, error0;
396 
397  bi0 = from[0];
398  to_next[0] = bi0;
399  from += 1;
400  to_next += 1;
401  n_left_to_next -= 1;
402  n_left_from -= 1;
403 
404  b0 = vlib_get_buffer (vm, bi0);
405 
406  s0 = vlib_buffer_get_current(b0);
407  l2_len0 = vlib_buffer_length_in_chain (vm, b0);
408  l3_len0 = l2_len0 - STRUCT_OFFSET_OF (srp_generic_control_header_t, control);
409 
410  error0 = SRP_ERROR_CONTROL_PACKETS_PROCESSED;
411 
412  error0 = s0->control.version != 0 ? SRP_ERROR_CONTROL_VERSION_NON_ZERO : error0;
413 
414  {
415  u16 save0 = s0->control.checksum;
416  u16 computed0;
417  s0->control.checksum = 0;
418  computed0 = ~ip_csum_fold (ip_incremental_checksum (0, &s0->control, l3_len0));
419  error0 = save0 != computed0 ? SRP_ERROR_CONTROL_BAD_CHECKSUM : error0;
420  }
421 
422  if (error0 == SRP_ERROR_CONTROL_PACKETS_PROCESSED)
423  {
425  [SRP_CONTROL_PACKET_TYPE_topology] = srp_topology_packet,
426  };
428 
429  f = 0;
430  if (s0->control.type < ARRAY_LEN (t))
431  f = t[s0->control.type];
432 
433  if (f)
434  {
435  vec_validate (contents, l2_len0 - 1);
436  vlib_buffer_contents (vm, bi0, contents);
437  error0 = f (vm, vnet_buffer (b0)->sw_if_index[VLIB_RX], &contents);
438  }
439  else
440  error0 = SRP_ERROR_UNKNOWN_CONTROL;
441  }
442 
443  b0->error = error_node->errors[error0];
444  next0 = 0;
445 
447  to_next, n_left_to_next,
448  bi0, next0);
449  }
450 
451  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
452  }
453 
454  return from_frame->n_vectors;
455 }
456 
458  .function = srp_control_input,
459  .name = "srp-control",
460  /* Takes a vector of packets. */
461  .vector_size = sizeof (u32),
462 
463  .n_next_nodes = 1,
464  .next_nodes = {
465  [0] = "error-drop",
466  },
467 
468  .format_buffer = format_srp_header_with_length,
469  .format_trace = format_srp_input_trace,
470  .unformat_buffer = unformat_srp_header,
471 };
472 
473 static u8 * format_srp_ips_request_type (u8 * s, va_list * args)
474 {
475  u32 x = va_arg (*args, u32);
476  char * t = 0;
477  switch (x)
478  {
479 #define _(f,n) case SRP_IPS_REQUEST_##f: t = #f; break;
481 #undef _
482  default:
483  return format (s, "unknown 0x%x", x);
484  }
485  return format (s, "%U", format_c_identifier, t);
486 }
487 
488 static u8 * format_srp_ips_status (u8 * s, va_list * args)
489 {
490  u32 x = va_arg (*args, u32);
491  char * t = 0;
492  switch (x)
493  {
494 #define _(f,n) case SRP_IPS_STATUS_##f: t = #f; break;
496 #undef _
497  default:
498  return format (s, "unknown 0x%x", x);
499  }
500  return format (s, "%U", format_c_identifier, t);
501 }
502 
503 static u8 * format_srp_ips_state (u8 * s, va_list * args)
504 {
505  u32 x = va_arg (*args, u32);
506  char * t = 0;
507  switch (x)
508  {
509 #define _(f) case SRP_IPS_STATE_##f: t = #f; break;
511 #undef _
512  default:
513  return format (s, "unknown 0x%x", x);
514  }
515  return format (s, "%U", format_c_identifier, t);
516 }
517 
518 static u8 * format_srp_ring (u8 * s, va_list * args)
519 {
520  u32 ring = va_arg (*args, u32);
521  return format (s, "%s", ring == SRP_RING_INNER ? "inner" : "outer");
522 }
523 
524 static u8 * format_srp_ips_header (u8 * s, va_list * args)
525 {
526  srp_ips_header_t * h = va_arg (*args, srp_ips_header_t *);
527 
528  s = format (s, "%U, %U, %U, %s-path",
529  format_srp_ips_request_type, h->request_type,
530  format_ethernet_address, h->originator_address,
531  format_srp_ips_status, h->status,
532  h->is_long_path ? "long" : "short");
533 
534  return s;
535 }
536 
537 static u8 * format_srp_interface (u8 * s, va_list * args)
538 {
539  srp_interface_t * si = va_arg (*args, srp_interface_t *);
541 
542  s = format (s, "address %U, IPS state %U",
543  format_ethernet_address, si->my_address,
544  format_srp_ips_state, si->current_ips_state);
545  for (ir = si->rings; ir < si->rings + SRP_N_RING; ir++)
547  s = format (s, ", %U neighbor %U",
548  format_srp_ring, ir->ring,
550 
551  return s;
552 }
553 
554 u8 * format_srp_device (u8 * s, va_list * args)
555 {
556  u32 hw_if_index = va_arg (*args, u32);
557  CLIB_UNUSED (int verbose) = va_arg (*args, int);
558  vnet_main_t * vnm = vnet_get_main();
559  srp_main_t * sm = &srp_main;
560  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
561  srp_interface_t * si = pool_elt_at_index (sm->interface_pool, hi->hw_instance);
562  return format (s, "%U", format_srp_interface, si);
563 }
564 
567 {
568  vnet_main_t * vnm = vnet_get_main();
569  srp_main_t * sm = &srp_main;
572 
573  ASSERT (hi->hw_class_index == srp_hw_interface_class.index);
574  si = pool_elt_at_index (sm->interface_pool, hi->hw_instance);
575 
576  ASSERT (si->rings[SRP_RING_INNER].hw_if_index == hi->hw_if_index
577  || si->rings[SRP_RING_OUTER].hw_if_index == hi->hw_if_index);
578  if (ring)
579  *ring =
580  (hi->hw_if_index == si->rings[SRP_RING_INNER].hw_if_index
582  : SRP_RING_OUTER);
583 
584  return si;
585 }
586 
588  srp_ring_type_t tx_ring,
590 {
591  clib_memset (i, 0, sizeof (i[0]));
592 
593  i->srp.ttl = 1;
594  i->srp.is_inner_ring = tx_ring;
595  i->srp.priority = 7;
596  i->srp.mode = SRP_MODE_control_locally_buffered_for_host;
598 
599  clib_memcpy_fast (&i->ethernet.src_address, &si->my_address, sizeof (si->my_address));
600  i->ethernet.type = clib_host_to_net_u16 (ETHERNET_TYPE_SRP_CONTROL);
601 
602  /* Checksum will be filled in later. */
603  i->control.version = 0;
604  i->control.type = SRP_CONTROL_PACKET_TYPE_ips;
605  i->control.ttl = 255;
606 
607  clib_memcpy_fast (&i->originator_address, &si->my_address, sizeof (si->my_address));
608 }
609 
611  srp_ring_type_t tx_ring,
613 {
614  srp_main_t * sm = &srp_main;
615  vnet_main_t * vnm = vnet_get_main();
616  vlib_main_t * vm = sm->vlib_main;
617  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, si->rings[tx_ring].hw_if_index);
618  vlib_frame_t * f;
619  vlib_buffer_t * b;
620  u32 * to_next, bi = ~0;
621 
622  if (! vnet_sw_interface_is_admin_up (vnm, hi->sw_if_index))
623  return;
624  if (hi->hw_class_index != srp_hw_interface_class.index)
625  return;
626 
627  i->control.checksum
628  = ~ip_csum_fold (ip_incremental_checksum (0, &i->control,
629  sizeof (i[0]) - STRUCT_OFFSET_OF (srp_ips_header_t, control)));
630 
631  if (vlib_buffer_add_data (vm, /* buffer to append to */ &bi, i,
632  sizeof (i[0])))
633  {
634  /* complete or partial allocation failure */
635  if (bi != ~0)
636  vlib_buffer_free (vm, &bi, 1);
637  return;
638  }
639 
640  /* FIXME trace. */
641  if (0)
642  clib_warning ("%U %U",
643  format_vnet_sw_if_index_name, vnm, hi->sw_if_index,
645 
646  b = vlib_get_buffer (vm, bi);
647  vnet_buffer (b)->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_TX] = hi->sw_if_index;
648 
649  f = vlib_get_frame_to_node (vm, hi->output_node_index);
650  to_next = vlib_frame_vector_args (f);
651  to_next[0] = bi;
652  f->n_vectors = 1;
653  vlib_put_frame_to_node (vm, hi->output_node_index, f);
654 }
655 
657 {
658  static u8 t[16] = {
659  [SRP_IPS_REQUEST_forced_switch] = 1,
660  [SRP_IPS_REQUEST_manual_switch] = 1,
661  [SRP_IPS_REQUEST_signal_fail] = 1,
662  [SRP_IPS_REQUEST_signal_degrade] = 1,
663  };
664  return (int) r < ARRAY_LEN (t) ? t[r] : 0;
665 }
666 
667 /* Called when an IPS control packet is received on given interface. */
669 {
670  vnet_main_t * vnm = vnet_get_main();
672  srp_ring_type_t rx_ring;
674  srp_interface_ring_t * ir = &si->rings[rx_ring];
675 
676  /* FIXME trace. */
677  if (0)
678  clib_warning ("%U %U %U",
679  format_time_interval, "h:m:s:u", vlib_time_now (vm),
682 
683  /* Ignore self-generated IPS packets. */
684  if (! memcmp (h->originator_address, si->my_address, sizeof (h->originator_address)))
685  goto done;
686 
687  /* Learn neighbor address from short path messages. */
688  if (! h->is_long_path)
689  {
691  && memcmp (ir->rx_neighbor_address, h->originator_address, sizeof (ir->rx_neighbor_address)))
692  {
693  ASSERT (0);
694  }
696  clib_memcpy_fast (ir->rx_neighbor_address, h->originator_address, sizeof (ir->rx_neighbor_address));
697  }
698 
699  switch (si->current_ips_state)
700  {
701  case SRP_IPS_STATE_idle:
702  /* Received {REQ,NEIGHBOR,W,S} in idle state: wrap. */
703  if (requests_switch (h->request_type)
704  && ! h->is_long_path
705  && h->status == SRP_IPS_STATUS_wrapped)
706  {
707  srp_ips_header_t to_tx[2];
708 
709  si->current_ips_state = SRP_IPS_STATE_wrapped;
710  si->hw_wrap_function (si->rings[SRP_SIDE_A].hw_if_index, /* enable_wrap */ 1);
711  si->hw_wrap_function (si->rings[SRP_SIDE_B].hw_if_index, /* enable_wrap */ 1);
712 
713  init_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
714  to_tx[0].request_type = SRP_IPS_REQUEST_idle;
715  to_tx[0].status = SRP_IPS_STATUS_wrapped;
716  to_tx[0].is_long_path = 0;
717  tx_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
718 
719  init_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
720  to_tx[1].request_type = h->request_type;
721  to_tx[1].status = SRP_IPS_STATUS_wrapped;
722  to_tx[1].is_long_path = 1;
723  tx_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
724  }
725  break;
726 
727  case SRP_IPS_STATE_wrapped:
728  if (! h->is_long_path
729  && h->request_type == SRP_IPS_REQUEST_idle
730  && h->status == SRP_IPS_STATUS_idle)
731  {
732  si->current_ips_state = SRP_IPS_STATE_idle;
733  si->hw_wrap_function (si->rings[SRP_SIDE_A].hw_if_index, /* enable_wrap */ 0);
734  si->hw_wrap_function (si->rings[SRP_SIDE_B].hw_if_index, /* enable_wrap */ 0);
735  }
736  break;
737 
738  case SRP_IPS_STATE_pass_thru:
739  /* FIXME */
740  break;
741 
742  default:
743  abort ();
744  break;
745  }
746  done:
747  ;
748 }
749 
750 /* Preform local IPS request on given interface. */
752 {
753  vnet_main_t * vnm = vnet_get_main();
754  srp_main_t * sm = &srp_main;
755  srp_ring_type_t rx_ring;
757  srp_interface_ring_t * ir = &si->rings[rx_ring];
758 
759  if (request == SRP_IPS_REQUEST_wait_to_restore)
760  {
761  if (si->current_ips_state != SRP_IPS_STATE_wrapped)
762  return;
763  if (! ir->waiting_to_restore)
764  {
766  ir->waiting_to_restore = 1;
767  }
768  }
769  else
770  {
771  /* FIXME handle local signal fail. */
773  ir->waiting_to_restore = 0;
774  }
775 
776  /* FIXME trace. */
777  if (0)
778  clib_warning ("%U %U",
781 
782 }
783 
785 {
786  srp_main_t * sm = &srp_main;
787  srp_ips_header_t to_tx[2];
789  srp_interface_ring_t * r0 = &si->rings[rx_ring ^ 0];
790  srp_interface_ring_t * r1 = &si->rings[rx_ring ^ 1];
791  f64 now = vlib_time_now (sm->vlib_main);
792 
793  if (! si->ips_process_enable)
794  return;
795 
796  if (si->current_ips_state == SRP_IPS_STATE_wrapped
797  && r0->waiting_to_restore
798  && r1->waiting_to_restore
799  && now >= r0->wait_to_restore_start_time + si->config.wait_to_restore_idle_delay
800  && now >= r1->wait_to_restore_start_time + si->config.wait_to_restore_idle_delay)
801  {
802  si->current_ips_state = SRP_IPS_STATE_idle;
805  }
806 
807  if (si->current_ips_state != SRP_IPS_STATE_idle)
808  return;
809 
810  init_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
811  init_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
812 
813  if (si->current_ips_state == SRP_IPS_STATE_idle)
814  {
815  to_tx[0].request_type = to_tx[1].request_type = SRP_IPS_REQUEST_idle;
816  to_tx[0].status = to_tx[1].status = SRP_IPS_STATUS_idle;
817  to_tx[0].is_long_path = to_tx[1].is_long_path = 0;
818  }
819 
820  else if (si->current_ips_state == SRP_IPS_STATE_wrapped)
821  {
822  to_tx[0].request_type =
823  (si->rings[rx_ring ^ 0].waiting_to_restore
824  ? SRP_IPS_REQUEST_wait_to_restore
825  : SRP_IPS_REQUEST_signal_fail);
826  to_tx[1].request_type =
827  (si->rings[rx_ring ^ 1].waiting_to_restore
828  ? SRP_IPS_REQUEST_wait_to_restore
829  : SRP_IPS_REQUEST_signal_fail);
830  to_tx[0].status = to_tx[1].status = SRP_IPS_STATUS_wrapped;
831  to_tx[0].is_long_path = 0;
832  to_tx[1].is_long_path = 1;
833  }
834 
835  tx_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
836  tx_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
837 }
838 
839 static uword
842  vlib_frame_t * f)
843 {
844  srp_main_t * sm = &srp_main;
846 
847  while (1)
848  {
851  }
852  vlib_process_suspend (vm, 1.0);
853  }
854 
855  return 0;
856 }
857 
859  .function = srp_ips_process,
860  .type = VLIB_NODE_TYPE_PROCESS,
861  .name = "srp-ips-process",
862  .state = VLIB_NODE_STATE_DISABLED,
863 };
864 
865 static void
867 {
873 }
874 
876 {
877  srp_main_t * sm = &srp_main;
878 
879  sm->default_data_ttl = 255;
880  sm->vlib_main = vm;
885 
886  return 0;
887 }
888 
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:979
srp_interface_t::rings
srp_interface_ring_t rings[SRP_N_RING]
Definition: srp.h:114
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:858
srp_ring_type_t
srp_ring_type_t
Definition: srp.h:62
foreach_srp_ips_state
#define foreach_srp_ips_state
Definition: srp.h:50
srp_main_t
Definition: srp.h:124
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:297
srp_main_t::vlib_main
vlib_main_t * vlib_main
Definition: srp.h:125
unformat_pg_srp_header
uword unformat_pg_srp_header(unformat_input_t *input, va_list *args)
Definition: pg.c:78
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
pg.h
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:1098
srp_generic_control_header_t
Definition: packet.h:124
srp_input_node
static vlib_node_registration_t srp_input_node
Definition: node.c:275
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
format_srp_input_trace
static u8 * format_srp_input_trace(u8 *s, va_list *va)
Definition: node.c:51
maybe_send_ips_message
static void maybe_send_ips_message(srp_interface_t *si)
Definition: node.c:784
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:71
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:63
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:78
format_srp_interface
static u8 * format_srp_interface(u8 *s, va_list *args)
Definition: node.c:537
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:566
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
node_index
node node_index
Definition: interface_output.c:440
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:48
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:63
srp_main_t::default_data_ttl
u32 default_data_ttl
Definition: srp.h:133
r
vnet_hw_if_output_node_runtime_t * r
Definition: interface_output.c:1089
vlib_node_t::unformat_buffer
unformat_function_t * unformat_buffer
Definition: node.h:349
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:357
srp_main_t::interface_pool
srp_interface_t * interface_pool
Definition: srp.h:128
h
h
Definition: flowhash_template.h:372
srp_setup_node
static void srp_setup_node(vlib_main_t *vm, u32 node_index)
Definition: node.c:866
srp_error_strings
static char * srp_error_strings[]
Definition: node.c:269
pg_node_t
Definition: pg.h:332
format_srp_device
u8 * format_srp_device(u8 *s, va_list *args)
Definition: node.c:554
srp_input_disposition_t::next_index
u8 next_index
Definition: node.c:70
srp_interface_ring_t::rx_neighbor_address_valid
u8 rx_neighbor_address_valid
Definition: srp.h:83
CLIB_PREFETCH
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:76
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:66
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
vlib_node_t::format_buffer
format_function_t * format_buffer
Definition: node.h:348
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:206
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:89
SRP_N_RING
@ SRP_N_RING
Definition: srp.h:65
pg_node_t::unformat_edit
unformat_function_t * unformat_edit
Definition: pg.h:335
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
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:875
srp_input_disposition_t::error
u16 error
Definition: node.c:72
uword
u64 uword
Definition: types.h:112
pg_get_node
static pg_node_t * pg_get_node(uword node_index)
Definition: pg.h:391
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:473
vlib_get_node
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:86
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:75
foreach_srp_error
#define foreach_srp_error
Definition: srp.h:191
srp_input_trace_t
Definition: node.c:47
srp_ips_local_request
void srp_ips_local_request(u32 sw_if_index, srp_ips_request_type_t request)
Definition: node.c:751
srp_input_disposition_t
Definition: node.c:69
SRP_INPUT_NEXT_CONTROL
@ SRP_INPUT_NEXT_CONTROL
Definition: node.c:65
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:104
format_srp_ring
static u8 * format_srp_ring(u8 *s, va_list *args)
Definition: node.c:518
srp_ips_process
static uword srp_ips_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: node.c:840
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:587
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:72
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:458
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:64
format_srp_ips_status
static u8 * format_srp_ips_status(u8 *s, va_list *args)
Definition: node.c:488
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:71
si
vnet_sw_interface_t * si
Definition: interface_output.c:418
requests_switch
static int requests_switch(srp_ips_request_type_t r)
Definition: node.c:656
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:362
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:45
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_control_input_node
static vlib_node_registration_t srp_control_input_node
Definition: node.c:457
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:524
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:81
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:419
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:64
i
int i
Definition: flowhash_template.h:376
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:887
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:610
SRP_SIDE_B
@ SRP_SIDE_B
Definition: srp.h:67
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:86
srp_input_next_t
srp_input_next_t
Definition: node.c:62
vlib_time_now
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:327
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:66
srp_input
static uword srp_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: node.c:109
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:503
srp_ips_rx_packet
void srp_ips_rx_packet(u32 sw_if_index, srp_ips_header_t *h)
Definition: node.c:668
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111