FD.io VPP  v18.10-34-gcce845e
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 (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 (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  {
332  vlib_buffer_t * b;
333  u32 * to_next = vlib_frame_vector_args (f);
334  u32 bi;
335 
337  /* buffer to append to */ ~0,
338  *contents, vec_len (*contents));
339  b = vlib_get_buffer (vm, bi);
340  vnet_buffer (b)->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
341  to_next[0] = bi;
342  f->n_vectors = 1;
344  }
345 
346  return SRP_ERROR_CONTROL_PACKETS_PROCESSED;
347 }
348 
351  u8 ** contents);
352 
353 static uword
355  vlib_node_runtime_t * node,
356  vlib_frame_t * from_frame)
357 {
358  u32 n_left_from, next_index, * from, * to_next;
359  vlib_node_runtime_t * error_node;
360  static u8 * contents;
361 
362  error_node = vlib_node_get_runtime (vm, srp_input_node.index);
363 
364  from = vlib_frame_vector_args (from_frame);
365  n_left_from = from_frame->n_vectors;
366 
367  if (node->flags & VLIB_NODE_FLAG_TRACE)
369  from,
370  n_left_from,
371  sizeof (from[0]),
372  sizeof (srp_input_trace_t));
373 
374  next_index = node->cached_next_index;
375 
376  while (n_left_from > 0)
377  {
378  u32 n_left_to_next;
379 
380  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
381 
382  while (n_left_from > 0 && n_left_to_next > 0)
383  {
384  u32 bi0, l2_len0, l3_len0;
385  vlib_buffer_t * b0;
386  u8 next0, error0;
388 
389  bi0 = from[0];
390  to_next[0] = bi0;
391  from += 1;
392  to_next += 1;
393  n_left_to_next -= 1;
394  n_left_from -= 1;
395 
396  b0 = vlib_get_buffer (vm, bi0);
397 
398  s0 = (void *) (b0->data + b0->current_data);
399  l2_len0 = vlib_buffer_length_in_chain (vm, b0);
400  l3_len0 = l2_len0 - STRUCT_OFFSET_OF (srp_generic_control_header_t, control);
401 
402  error0 = SRP_ERROR_CONTROL_PACKETS_PROCESSED;
403 
404  error0 = s0->control.version != 0 ? SRP_ERROR_CONTROL_VERSION_NON_ZERO : error0;
405 
406  {
407  u16 save0 = s0->control.checksum;
408  u16 computed0;
409  s0->control.checksum = 0;
410  computed0 = ~ip_csum_fold (ip_incremental_checksum (0, &s0->control, l3_len0));
411  error0 = save0 != computed0 ? SRP_ERROR_CONTROL_BAD_CHECKSUM : error0;
412  }
413 
414  if (error0 == SRP_ERROR_CONTROL_PACKETS_PROCESSED)
415  {
417  [SRP_CONTROL_PACKET_TYPE_topology] = srp_topology_packet,
418  };
420 
421  f = 0;
422  if (s0->control.type < ARRAY_LEN (t))
423  f = t[s0->control.type];
424 
425  if (f)
426  {
427  vec_validate (contents, l2_len0 - 1);
428  vlib_buffer_contents (vm, bi0, contents);
429  error0 = f (vm, vnet_buffer (b0)->sw_if_index[VLIB_RX], &contents);
430  }
431  else
432  error0 = SRP_ERROR_UNKNOWN_CONTROL;
433  }
434 
435  b0->error = error_node->errors[error0];
436  next0 = 0;
437 
438  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
439  to_next, n_left_to_next,
440  bi0, next0);
441  }
442 
443  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
444  }
445 
446  return from_frame->n_vectors;
447 }
448 
450  .function = srp_control_input,
451  .name = "srp-control",
452  /* Takes a vector of packets. */
453  .vector_size = sizeof (u32),
454 
455  .n_next_nodes = 1,
456  .next_nodes = {
457  [0] = "error-drop",
458  },
459 
460  .format_buffer = format_srp_header_with_length,
461  .format_trace = format_srp_input_trace,
462  .unformat_buffer = unformat_srp_header,
463 };
464 
465 static u8 * format_srp_ips_request_type (u8 * s, va_list * args)
466 {
467  u32 x = va_arg (*args, u32);
468  char * t = 0;
469  switch (x)
470  {
471 #define _(f,n) case SRP_IPS_REQUEST_##f: t = #f; break;
473 #undef _
474  default:
475  return format (s, "unknown 0x%x", x);
476  }
477  return format (s, "%U", format_c_identifier, t);
478 }
479 
480 static u8 * format_srp_ips_status (u8 * s, va_list * args)
481 {
482  u32 x = va_arg (*args, u32);
483  char * t = 0;
484  switch (x)
485  {
486 #define _(f,n) case SRP_IPS_STATUS_##f: t = #f; break;
488 #undef _
489  default:
490  return format (s, "unknown 0x%x", x);
491  }
492  return format (s, "%U", format_c_identifier, t);
493 }
494 
495 static u8 * format_srp_ips_state (u8 * s, va_list * args)
496 {
497  u32 x = va_arg (*args, u32);
498  char * t = 0;
499  switch (x)
500  {
501 #define _(f) case SRP_IPS_STATE_##f: t = #f; break;
503 #undef _
504  default:
505  return format (s, "unknown 0x%x", x);
506  }
507  return format (s, "%U", format_c_identifier, t);
508 }
509 
510 static u8 * format_srp_ring (u8 * s, va_list * args)
511 {
512  u32 ring = va_arg (*args, u32);
513  return format (s, "%s", ring == SRP_RING_INNER ? "inner" : "outer");
514 }
515 
516 static u8 * format_srp_ips_header (u8 * s, va_list * args)
517 {
518  srp_ips_header_t * h = va_arg (*args, srp_ips_header_t *);
519 
520  s = format (s, "%U, %U, %U, %s-path",
521  format_srp_ips_request_type, h->request_type,
523  format_srp_ips_status, h->status,
524  h->is_long_path ? "long" : "short");
525 
526  return s;
527 }
528 
529 static u8 * format_srp_interface (u8 * s, va_list * args)
530 {
531  srp_interface_t * si = va_arg (*args, srp_interface_t *);
533 
534  s = format (s, "address %U, IPS state %U",
537  for (ir = si->rings; ir < si->rings + SRP_N_RING; ir++)
539  s = format (s, ", %U neighbor %U",
540  format_srp_ring, ir->ring,
542 
543  return s;
544 }
545 
546 u8 * format_srp_device (u8 * s, va_list * args)
547 {
548  u32 hw_if_index = va_arg (*args, u32);
549  CLIB_UNUSED (int verbose) = va_arg (*args, int);
550  vnet_main_t * vnm = vnet_get_main();
551  srp_main_t * sm = &srp_main;
552  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
554  return format (s, "%U", format_srp_interface, si);
555 }
556 
559 {
560  vnet_main_t * vnm = vnet_get_main();
561  srp_main_t * sm = &srp_main;
562  vnet_hw_interface_t * hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
563  srp_interface_t * si;
564 
567 
570  if (ring)
571  *ring =
574  : SRP_RING_OUTER);
575 
576  return si;
577 }
578 
580  srp_ring_type_t tx_ring,
582 {
583  memset (i, 0, sizeof (i[0]));
584 
585  i->srp.ttl = 1;
586  i->srp.is_inner_ring = tx_ring;
587  i->srp.priority = 7;
588  i->srp.mode = SRP_MODE_control_locally_buffered_for_host;
590 
591  clib_memcpy (&i->ethernet.src_address, &si->my_address, sizeof (si->my_address));
592  i->ethernet.type = clib_host_to_net_u16 (ETHERNET_TYPE_SRP_CONTROL);
593 
594  /* Checksum will be filled in later. */
595  i->control.version = 0;
596  i->control.type = SRP_CONTROL_PACKET_TYPE_ips;
597  i->control.ttl = 255;
598 
599  clib_memcpy (&i->originator_address, &si->my_address, sizeof (si->my_address));
600 }
601 
602 static void tx_ips_packet (srp_interface_t * si,
603  srp_ring_type_t tx_ring,
605 {
606  srp_main_t * sm = &srp_main;
607  vnet_main_t * vnm = vnet_get_main();
608  vlib_main_t * vm = sm->vlib_main;
610  vlib_frame_t * f;
611  vlib_buffer_t * b;
612  u32 * to_next, bi;
613 
615  return;
616  if (hi->hw_class_index != srp_hw_interface_class.index)
617  return;
618 
619  i->control.checksum
621  sizeof (i[0]) - STRUCT_OFFSET_OF (srp_ips_header_t, control)));
622 
624  /* buffer to append to */ ~0,
625  i, sizeof (i[0]));
626 
627  /* FIXME trace. */
628  if (0)
629  clib_warning ("%U %U",
632 
633  b = vlib_get_buffer (vm, bi);
634  vnet_buffer (b)->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_TX] = hi->sw_if_index;
635 
637  to_next = vlib_frame_vector_args (f);
638  to_next[0] = bi;
639  f->n_vectors = 1;
641 }
642 
644 {
645  static u8 t[16] = {
646  [SRP_IPS_REQUEST_forced_switch] = 1,
647  [SRP_IPS_REQUEST_manual_switch] = 1,
648  [SRP_IPS_REQUEST_signal_fail] = 1,
649  [SRP_IPS_REQUEST_signal_degrade] = 1,
650  };
651  return (int) r < ARRAY_LEN (t) ? t[r] : 0;
652 }
653 
654 /* Called when an IPS control packet is received on given interface. */
656 {
657  vnet_main_t * vnm = vnet_get_main();
658  vlib_main_t * vm = srp_main.vlib_main;
659  srp_ring_type_t rx_ring;
660  srp_interface_t * si = srp_get_interface (sw_if_index, &rx_ring);
661  srp_interface_ring_t * ir = &si->rings[rx_ring];
662 
663  /* FIXME trace. */
664  if (0)
665  clib_warning ("%U %U %U",
666  format_time_interval, "h:m:s:u", vlib_time_now (vm),
667  format_vnet_sw_if_index_name, vnm, sw_if_index,
669 
670  /* Ignore self-generated IPS packets. */
671  if (! memcmp (h->originator_address, si->my_address, sizeof (h->originator_address)))
672  goto done;
673 
674  /* Learn neighbor address from short path messages. */
675  if (! h->is_long_path)
676  {
678  && memcmp (ir->rx_neighbor_address, h->originator_address, sizeof (ir->rx_neighbor_address)))
679  {
680  ASSERT (0);
681  }
684  }
685 
686  switch (si->current_ips_state)
687  {
688  case SRP_IPS_STATE_idle:
689  /* Received {REQ,NEIGHBOR,W,S} in idle state: wrap. */
690  if (requests_switch (h->request_type)
691  && ! h->is_long_path
692  && h->status == SRP_IPS_STATUS_wrapped)
693  {
694  srp_ips_header_t to_tx[2];
695 
696  si->current_ips_state = SRP_IPS_STATE_wrapped;
697  si->hw_wrap_function (si->rings[SRP_SIDE_A].hw_if_index, /* enable_wrap */ 1);
698  si->hw_wrap_function (si->rings[SRP_SIDE_B].hw_if_index, /* enable_wrap */ 1);
699 
700  init_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
701  to_tx[0].request_type = SRP_IPS_REQUEST_idle;
702  to_tx[0].status = SRP_IPS_STATUS_wrapped;
703  to_tx[0].is_long_path = 0;
704  tx_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
705 
706  init_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
707  to_tx[1].request_type = h->request_type;
708  to_tx[1].status = SRP_IPS_STATUS_wrapped;
709  to_tx[1].is_long_path = 1;
710  tx_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
711  }
712  break;
713 
714  case SRP_IPS_STATE_wrapped:
715  if (! h->is_long_path
716  && h->request_type == SRP_IPS_REQUEST_idle
717  && h->status == SRP_IPS_STATUS_idle)
718  {
719  si->current_ips_state = SRP_IPS_STATE_idle;
720  si->hw_wrap_function (si->rings[SRP_SIDE_A].hw_if_index, /* enable_wrap */ 0);
721  si->hw_wrap_function (si->rings[SRP_SIDE_B].hw_if_index, /* enable_wrap */ 0);
722  }
723  break;
724 
725  case SRP_IPS_STATE_pass_thru:
726  /* FIXME */
727  break;
728 
729  default:
730  abort ();
731  break;
732  }
733  done:
734  ;
735 }
736 
737 /* Preform local IPS request on given interface. */
739 {
740  vnet_main_t * vnm = vnet_get_main();
741  srp_main_t * sm = &srp_main;
742  srp_ring_type_t rx_ring;
743  srp_interface_t * si = srp_get_interface (sw_if_index, &rx_ring);
744  srp_interface_ring_t * ir = &si->rings[rx_ring];
745 
746  if (request == SRP_IPS_REQUEST_wait_to_restore)
747  {
748  if (si->current_ips_state != SRP_IPS_STATE_wrapped)
749  return;
750  if (! ir->waiting_to_restore)
751  {
753  ir->waiting_to_restore = 1;
754  }
755  }
756  else
757  {
758  /* FIXME handle local signal fail. */
760  ir->waiting_to_restore = 0;
761  }
762 
763  /* FIXME trace. */
764  if (0)
765  clib_warning ("%U %U",
766  format_vnet_sw_if_index_name, vnm, sw_if_index,
767  format_srp_ips_request_type, request);
768 
769 }
770 
772 {
773  srp_main_t * sm = &srp_main;
774  srp_ips_header_t to_tx[2];
776  srp_interface_ring_t * r0 = &si->rings[rx_ring ^ 0];
777  srp_interface_ring_t * r1 = &si->rings[rx_ring ^ 1];
778  f64 now = vlib_time_now (sm->vlib_main);
779 
780  if (! si->ips_process_enable)
781  return;
782 
783  if (si->current_ips_state == SRP_IPS_STATE_wrapped
784  && r0->waiting_to_restore
785  && r1->waiting_to_restore
788  {
789  si->current_ips_state = SRP_IPS_STATE_idle;
792  }
793 
794  if (si->current_ips_state != SRP_IPS_STATE_idle)
795  return;
796 
797  init_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
798  init_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
799 
800  if (si->current_ips_state == SRP_IPS_STATE_idle)
801  {
802  to_tx[0].request_type = to_tx[1].request_type = SRP_IPS_REQUEST_idle;
803  to_tx[0].status = to_tx[1].status = SRP_IPS_STATUS_idle;
804  to_tx[0].is_long_path = to_tx[1].is_long_path = 0;
805  }
806 
807  else if (si->current_ips_state == SRP_IPS_STATE_wrapped)
808  {
809  to_tx[0].request_type =
810  (si->rings[rx_ring ^ 0].waiting_to_restore
811  ? SRP_IPS_REQUEST_wait_to_restore
812  : SRP_IPS_REQUEST_signal_fail);
813  to_tx[1].request_type =
814  (si->rings[rx_ring ^ 1].waiting_to_restore
815  ? SRP_IPS_REQUEST_wait_to_restore
816  : SRP_IPS_REQUEST_signal_fail);
817  to_tx[0].status = to_tx[1].status = SRP_IPS_STATUS_wrapped;
818  to_tx[0].is_long_path = 0;
819  to_tx[1].is_long_path = 1;
820  }
821 
822  tx_ips_packet (si, rx_ring ^ 0, &to_tx[0]);
823  tx_ips_packet (si, rx_ring ^ 1, &to_tx[1]);
824 }
825 
826 static uword
828  vlib_node_runtime_t * rt,
829  vlib_frame_t * f)
830 {
831  srp_main_t * sm = &srp_main;
832  srp_interface_t * si;
833 
834  while (1)
835  {
836  pool_foreach (si, sm->interface_pool, ({
837  maybe_send_ips_message (si);
838  }));
839  vlib_process_suspend (vm, 1.0);
840  }
841 
842  return 0;
843 }
844 
846  .function = srp_ips_process,
847  .type = VLIB_NODE_TYPE_PROCESS,
848  .name = "srp-ips-process",
849  .state = VLIB_NODE_STATE_DISABLED,
850 };
851 
853 {
854  srp_main_t * sm = &srp_main;
855 
856  sm->default_data_ttl = 255;
857  sm->vlib_main = vm;
861  srp_setup_node (vm, srp_input_node.index);
862 
863  return 0;
864 }
865 
static int requests_switch(srp_ips_request_type_t r)
Definition: node.c:643
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
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
u32 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:776
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:738
#define foreach_srp_error
Definition: srp.h:202
#define CLIB_UNUSED(x)
Definition: clib.h:81
#define SRP_TOPOLOGY_MAC_BINDING_FLAG_IS_INNER_RING
Definition: packet.h:132
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)
srp_control_header_t control
Definition: packet.h:127
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:227
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:64
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:472
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:263
static void maybe_send_ips_message(srp_interface_t *si)
Definition: node.c:771
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:495
unsigned char u8
Definition: types.h:56
static u8 * format_srp_ips_request_type(u8 *s, va_list *args)
Definition: node.c:465
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:449
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:448
ethernet_header_t ethernet
Definition: packet.h:180
memset(h->entries, 0, sizeof(h->entries[0])*entries)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:109
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:443
Definition: srp.h:66
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
u32 sw_if_index
Definition: vxlan_gbp.api:39
#define always_inline
Definition: clib.h:94
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:187
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:182
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:240
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:852
static u8 * format_srp_ips_header(u8 *s, va_list *args)
Definition: node.c:516
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:464
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
static void tx_ips_packet(srp_interface_t *si, srp_ring_type_t tx_ring, srp_ips_header_t *i)
Definition: node.c:602
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:191
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
Definition: buffer.h:440
static u8 * format_srp_interface(u8 *s, va_list *args)
Definition: node.c:529
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:364
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:138
static u8 * format_srp_ring(u8 *s, va_list *args)
Definition: node.c:510
static uword vlib_buffer_contents(vlib_main_t *vm, u32 buffer_index, u8 *contents)
Copy buffer contents to memory.
Definition: buffer_funcs.h:297
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:401
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
vlib_main_t * vm
Definition: buffer.c:294
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 clib_memcpy(a, b, c)
Definition: string.h:75
#define ARRAY_LEN(x)
Definition: clib.h:61
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:455
u8 * format_srp_device(u8 *s, va_list *args)
Definition: node.c:546
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
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:354
u32 vlib_register_node(vlib_main_t *vm, vlib_node_registration_t *r)
Definition: node.c:519
void srp_ips_rx_packet(u32 sw_if_index, srp_ips_header_t *h)
Definition: node.c:655
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:218
vlib_node_registration_t srp_ips_process_node
Definition: node.c:845
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)
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
uword( srp_control_handler_function_t)(vlib_main_t *vm, u32 sw_if_index, u8 **contents)
Definition: node.c:349
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:267
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:827
#define vnet_buffer(b)
Definition: buffer.h:344
u8 data[0]
Packet data.
Definition: buffer.h:175
u16 flags
Copy of main node flags.
Definition: node.h:507
static void init_ips_packet(srp_interface_t *si, srp_ring_type_t tx_ring, srp_ips_header_t *i)
Definition: node.c:579
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:310
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:58
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:558
vlib_main_t * vlib_main
Definition: srp.h:126
static u8 * format_srp_ips_status(u8 *s, va_list *args)
Definition: node.c:480