FD.io VPP  v19.01.3-6-g70449b9b9
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 
74 static srp_input_disposition_t srp_input_disposition_by_mode[8] = {
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
109  vlib_node_runtime_t * node,
110  vlib_frame_t * from_frame)
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 
116  from = vlib_frame_vector_args (from_frame);
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 = (void *) (b0->data + b0->current_data);
171  s1 = (void *) (b1->data + b1->current_data);
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 
208  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
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 = (void *) (b0->data + b0->current_data);
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 
257  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
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();
299  vnet_hw_interface_t * hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
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));
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 
337  /* 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;
348  to_next = vlib_frame_vector_args (f);
349  to_next[0] = bi;
350  f->n_vectors = 1;
352  }
353 
354  return SRP_ERROR_CONTROL_PACKETS_PROCESSED;
355 }
356 
359  u8 ** contents);
360 
361 static uword
363  vlib_node_runtime_t * node,
364  vlib_frame_t * from_frame)
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 
372  from = vlib_frame_vector_args (from_frame);
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 = (void *) (b0->data + b0->current_data);
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 
446  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
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,
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",
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);
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;
570  vnet_hw_interface_t * hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
571  srp_interface_t * si;
572 
575 
578  if (ring)
579  *ring =
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 
610 static void tx_ips_packet (srp_interface_t * si,
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;
618  vlib_frame_t * f;
619  vlib_buffer_t * b;
620  u32 * to_next, bi = ~0;
621 
623  return;
624  if (hi->hw_class_index != srp_hw_interface_class.index)
625  return;
626 
627  i->control.checksum
629  sizeof (i[0]) - STRUCT_OFFSET_OF (srp_ips_header_t, control)));
630 
632  /* buffer to append to */ &bi,
633  i, sizeof (i[0])))
634  {
635  /* complete or partial allocation failure */
636  if (bi != ~0)
637  vlib_buffer_free (vm, &bi, 1);
638  return;
639  }
640 
641  /* FIXME trace. */
642  if (0)
643  clib_warning ("%U %U",
646 
647  b = vlib_get_buffer (vm, bi);
648  vnet_buffer (b)->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_TX] = hi->sw_if_index;
649 
651  to_next = vlib_frame_vector_args (f);
652  to_next[0] = bi;
653  f->n_vectors = 1;
655 }
656 
658 {
659  static u8 t[16] = {
660  [SRP_IPS_REQUEST_forced_switch] = 1,
661  [SRP_IPS_REQUEST_manual_switch] = 1,
662  [SRP_IPS_REQUEST_signal_fail] = 1,
663  [SRP_IPS_REQUEST_signal_degrade] = 1,
664  };
665  return (int) r < ARRAY_LEN (t) ? t[r] : 0;
666 }
667 
668 /* Called when an IPS control packet is received on given interface. */
670 {
671  vnet_main_t * vnm = vnet_get_main();
672  vlib_main_t * vm = srp_main.vlib_main;
673  srp_ring_type_t rx_ring;
674  srp_interface_t * si = srp_get_interface (sw_if_index, &rx_ring);
675  srp_interface_ring_t * ir = &si->rings[rx_ring];
676 
677  /* FIXME trace. */
678  if (0)
679  clib_warning ("%U %U %U",
680  format_time_interval, "h:m:s:u", vlib_time_now (vm),
681  format_vnet_sw_if_index_name, vnm, sw_if_index,
683 
684  /* Ignore self-generated IPS packets. */
685  if (! memcmp (h->originator_address, si->my_address, sizeof (h->originator_address)))
686  goto done;
687 
688  /* Learn neighbor address from short path messages. */
689  if (! h->is_long_path)
690  {
692  && memcmp (ir->rx_neighbor_address, h->originator_address, sizeof (ir->rx_neighbor_address)))
693  {
694  ASSERT (0);
695  }
698  }
699 
700  switch (si->current_ips_state)
701  {
702  case SRP_IPS_STATE_idle:
703  /* Received {REQ,NEIGHBOR,W,S} in idle state: wrap. */
704  if (requests_switch (h->request_type)
705  && ! h->is_long_path
706  && h->status == SRP_IPS_STATUS_wrapped)
707  {
708  srp_ips_header_t to_tx[2];
709 
710  si->current_ips_state = SRP_IPS_STATE_wrapped;
711  si->hw_wrap_function (si->rings[SRP_SIDE_A].hw_if_index, /* enable_wrap */ 1);
712  si->hw_wrap_function (si->rings[SRP_SIDE_B].hw_if_index, /* enable_wrap */ 1);
713 
714  init_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
715  to_tx[0].request_type = SRP_IPS_REQUEST_idle;
716  to_tx[0].status = SRP_IPS_STATUS_wrapped;
717  to_tx[0].is_long_path = 0;
718  tx_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
719 
720  init_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
721  to_tx[1].request_type = h->request_type;
722  to_tx[1].status = SRP_IPS_STATUS_wrapped;
723  to_tx[1].is_long_path = 1;
724  tx_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
725  }
726  break;
727 
728  case SRP_IPS_STATE_wrapped:
729  if (! h->is_long_path
730  && h->request_type == SRP_IPS_REQUEST_idle
731  && h->status == SRP_IPS_STATUS_idle)
732  {
733  si->current_ips_state = SRP_IPS_STATE_idle;
734  si->hw_wrap_function (si->rings[SRP_SIDE_A].hw_if_index, /* enable_wrap */ 0);
735  si->hw_wrap_function (si->rings[SRP_SIDE_B].hw_if_index, /* enable_wrap */ 0);
736  }
737  break;
738 
739  case SRP_IPS_STATE_pass_thru:
740  /* FIXME */
741  break;
742 
743  default:
744  abort ();
745  break;
746  }
747  done:
748  ;
749 }
750 
751 /* Preform local IPS request on given interface. */
753 {
754  vnet_main_t * vnm = vnet_get_main();
755  srp_main_t * sm = &srp_main;
756  srp_ring_type_t rx_ring;
757  srp_interface_t * si = srp_get_interface (sw_if_index, &rx_ring);
758  srp_interface_ring_t * ir = &si->rings[rx_ring];
759 
760  if (request == SRP_IPS_REQUEST_wait_to_restore)
761  {
762  if (si->current_ips_state != SRP_IPS_STATE_wrapped)
763  return;
764  if (! ir->waiting_to_restore)
765  {
767  ir->waiting_to_restore = 1;
768  }
769  }
770  else
771  {
772  /* FIXME handle local signal fail. */
774  ir->waiting_to_restore = 0;
775  }
776 
777  /* FIXME trace. */
778  if (0)
779  clib_warning ("%U %U",
780  format_vnet_sw_if_index_name, vnm, sw_if_index,
781  format_srp_ips_request_type, request);
782 
783 }
784 
786 {
787  srp_main_t * sm = &srp_main;
788  srp_ips_header_t to_tx[2];
790  srp_interface_ring_t * r0 = &si->rings[rx_ring ^ 0];
791  srp_interface_ring_t * r1 = &si->rings[rx_ring ^ 1];
792  f64 now = vlib_time_now (sm->vlib_main);
793 
794  if (! si->ips_process_enable)
795  return;
796 
797  if (si->current_ips_state == SRP_IPS_STATE_wrapped
798  && r0->waiting_to_restore
799  && r1->waiting_to_restore
802  {
803  si->current_ips_state = SRP_IPS_STATE_idle;
806  }
807 
808  if (si->current_ips_state != SRP_IPS_STATE_idle)
809  return;
810 
811  init_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
812  init_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
813 
814  if (si->current_ips_state == SRP_IPS_STATE_idle)
815  {
816  to_tx[0].request_type = to_tx[1].request_type = SRP_IPS_REQUEST_idle;
817  to_tx[0].status = to_tx[1].status = SRP_IPS_STATUS_idle;
818  to_tx[0].is_long_path = to_tx[1].is_long_path = 0;
819  }
820 
821  else if (si->current_ips_state == SRP_IPS_STATE_wrapped)
822  {
823  to_tx[0].request_type =
824  (si->rings[rx_ring ^ 0].waiting_to_restore
825  ? SRP_IPS_REQUEST_wait_to_restore
826  : SRP_IPS_REQUEST_signal_fail);
827  to_tx[1].request_type =
828  (si->rings[rx_ring ^ 1].waiting_to_restore
829  ? SRP_IPS_REQUEST_wait_to_restore
830  : SRP_IPS_REQUEST_signal_fail);
831  to_tx[0].status = to_tx[1].status = SRP_IPS_STATUS_wrapped;
832  to_tx[0].is_long_path = 0;
833  to_tx[1].is_long_path = 1;
834  }
835 
836  tx_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
837  tx_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
838 }
839 
840 static uword
842  vlib_node_runtime_t * rt,
843  vlib_frame_t * f)
844 {
845  srp_main_t * sm = &srp_main;
846  srp_interface_t * si;
847 
848  while (1)
849  {
850  pool_foreach (si, sm->interface_pool, ({
851  maybe_send_ips_message (si);
852  }));
853  vlib_process_suspend (vm, 1.0);
854  }
855 
856  return 0;
857 }
858 
860  .function = srp_ips_process,
861  .type = VLIB_NODE_TYPE_PROCESS,
862  .name = "srp-ips-process",
863  .state = VLIB_NODE_STATE_DISABLED,
864 };
865 
867 {
868  srp_main_t * sm = &srp_main;
869 
870  sm->default_data_ttl = 255;
871  sm->vlib_main = vm;
875  srp_setup_node (vm, srp_input_node.index);
876 
877  return 0;
878 }
879 
static int requests_switch(srp_ips_request_type_t r)
Definition: node.c:657
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
static u8 * format_srp_input_trace(u8 *s, va_list *va)
Definition: node.c:50
vmrglw vmrglh hi
f64 wait_to_restore_start_time
Definition: srp.h:90
srp_main_t srp_main
Definition: node.c:44
void srp_ips_local_request(u32 sw_if_index, srp_ips_request_type_t request)
Definition: node.c:752
#define foreach_srp_error
Definition: srp.h:202
#define CLIB_UNUSED(x)
Definition: clib.h:82
#define SRP_TOPOLOGY_MAC_BINDING_FLAG_IS_INNER_RING
Definition: packet.h:132
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:529
u8 rx_neighbor_address_valid
Definition: srp.h:84
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
srp_control_header_t control
Definition: packet.h:127
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:232
u8 src_address[6]
Definition: packet.h:56
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
static vlib_node_registration_t srp_input_node
Definition: node.c:274
int i
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:65
static void srp_header_compute_parity(srp_header_t *h)
Definition: packet.h:89
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:493
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:267
static void maybe_send_ips_message(srp_interface_t *si)
Definition: node.c:785
Definition: srp.h:68
format_function_t format_vnet_sw_if_index_name
static u8 * format_srp_ips_state(u8 *s, va_list *args)
Definition: node.c:503
unsigned char u8
Definition: types.h:56
static u8 * format_srp_ips_request_type(u8 *s, va_list *args)
Definition: node.c:473
u8 my_address[6]
Definition: srp.h:110
double f64
Definition: types.h:142
static vlib_node_registration_t srp_control_input_node
Definition: node.c:457
srp_interface_t * interface_pool
Definition: srp.h:129
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:422
ethernet_header_t ethernet
Definition: packet.h:180
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:490
Definition: srp.h:66
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
u32 sw_if_index
Definition: vxlan_gbp.api:37
#define always_inline
Definition: clib.h:98
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:188
u32 default_data_ttl
Definition: srp.h:134
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:181
static void srp_setup_node(vlib_main_t *vm, u32 node_index)
Definition: srp.h:193
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:242
static uword srp_topology_packet(vlib_main_t *vm, u32 sw_if_index, u8 **contents)
Definition: node.c:296
unsigned int u32
Definition: types.h:88
static clib_error_t * srp_init(vlib_main_t *vm)
Definition: node.c:866
static u8 * format_srp_ips_header(u8 *s, va_list *args)
Definition: node.c:524
u8 * format_c_identifier(u8 *s, va_list *va)
Definition: std-formats.c:258
srp_header_t srp
Definition: packet.h:179
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:511
static char * srp_error_strings[]
Definition: node.c:268
srp_ips_request_type_t
Definition: packet.h:162
srp_ring_type_t
Definition: srp.h:63
srp_interface_ring_t rings[SRP_N_RING]
Definition: srp.h:115
uword() srp_control_handler_function_t(vlib_main_t *vm, u32 sw_if_index, u8 **contents)
Definition: node.c:357
static void tx_ips_packet(srp_interface_t *si, srp_ring_type_t tx_ring, srp_ips_header_t *i)
Definition: node.c:610
unsigned short u16
Definition: types.h:57
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:190
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
Definition: buffer.h:442
static u8 * format_srp_interface(u8 *s, va_list *args)
Definition: node.c:537
u8 packet_data[32]
Definition: node.c:47
#define foreach_srp_ips_state
Definition: srp.h:51
vnet_hw_interface_class_t srp_hw_interface_class
srp_hw_wrap_function_t * hw_wrap_function
Definition: srp.h:120
#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
#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:218
u8 * format_srp_header(u8 *s, va_list *args)
Definition: format.c:104
#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:338
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:139
static u8 * format_srp_ring(u8 *s, va_list *args)
Definition: node.c:518
static uword vlib_buffer_contents(vlib_main_t *vm, u32 buffer_index, u8 *contents)
Copy buffer contents to memory.
Definition: buffer_funcs.h:301
f64 wait_to_restore_idle_delay
Definition: srp.h:99
u8 rx_neighbor_address[6]
Definition: srp.h:82
u16 n_vectors
Definition: node.h:420
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
vlib_main_t * vm
Definition: buffer.c:301
uword unformat_srp_header(unformat_input_t *input, va_list *args)
Definition: format.c:111
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:254
u8 waiting_to_restore
Definition: srp.h:87
#define clib_warning(format, args...)
Definition: error.h:59
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:89
u8 * format_srp_header_with_length(u8 *s, va_list *args)
Definition: format.c:63
#define ARRAY_LEN(x)
Definition: clib.h:62
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:452
u8 * format_srp_device(u8 *s, va_list *args)
Definition: node.c:554
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:537
u8 originator_address[6]
Definition: packet.h:182
#define ASSERT(truth)
static uword srp_control_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: node.c:362
u32 vlib_register_node(vlib_main_t *vm, vlib_node_registration_t *r)
Definition: node.c:520
void srp_ips_rx_packet(u32 sw_if_index, srp_ips_header_t *h)
Definition: node.c:669
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:233
vlib_node_registration_t srp_ips_process_node
Definition: node.c:859
Definition: srp.h:67
static uword srp_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: node.c:108
static uword vnet_sw_interface_is_admin_up(vnet_main_t *vnm, u32 sw_if_index)
int vlib_buffer_add_data(vlib_main_t *vm, vlib_buffer_free_list_index_t free_list_index, u32 *buffer_index, void *data, u32 n_data_bytes)
Definition: buffer.c:709
struct _vlib_node_registration vlib_node_registration_t
Definition: defs.h:47
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:47
u8 ips_process_enable
Definition: srp.h:113
srp_control_header_t control
Definition: packet.h:181
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
srp_input_next_t
Definition: node.c:61
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:244
vhost_user_req_t request
Definition: vhost_user.h:114
u8 * format_time_interval(u8 *s, va_list *args)
Definition: std-formats.c:122
static uword srp_ips_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: node.c:841
#define vnet_buffer(b)
Definition: buffer.h:368
u8 data[0]
Packet data.
Definition: buffer.h:176
u16 flags
Copy of main node flags.
Definition: node.h:531
static void init_ips_packet(srp_interface_t *si, srp_ring_type_t tx_ring, srp_ips_header_t *i)
Definition: node.c:587
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:326
srp_interface_config_t config
Definition: srp.h:118
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:62
srp_ring_type_t ring
Definition: srp.h:73
srp_ips_state_t current_ips_state
Definition: srp.h:107
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:237
Definition: defs.h:46
static srp_interface_t * srp_get_interface(u32 sw_if_index, srp_ring_type_t *ring)
Definition: node.c:566
vlib_main_t * vlib_main
Definition: srp.h:126
static u8 * format_srp_ips_status(u8 *s, va_list *args)
Definition: node.c:488