FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
ip4_source_and_port_range_check.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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 #include <vnet/ip/ip.h>
17 #include <vnet/dpo/load_balance.h>
18 #include <vnet/fib/fib_table.h>
19 #include <vnet/fib/ip4_fib.h>
20 
22 
23 /**
24  * @file
25  * @brief IPv4 Source and Port Range Checking.
26  *
27  * This file contains the source code for IPv4 source and port range
28  * checking.
29  */
30 
31 
32 /**
33  * @brief The pool of range chack DPOs
34  */
36 
37 /**
38  * @brief Dynamically registered DPO type
39  */
41 
44 
45 #define foreach_ip4_source_and_port_range_check_error \
46  _(CHECK_FAIL, "ip4 source and port range check bad packets") \
47  _(CHECK_OK, "ip4 source and port range check good packets")
48 
49 typedef enum
50 {
51 #define _(sym,str) IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_##sym,
53 #undef _
56 
58 #define _(sym,string) string,
60 #undef _
61 };
62 
63 typedef struct
64 {
72 
73 static u8 *
75 {
76  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
77  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
80 
81  if (t->bypass)
82  s = format (s, "PASS (bypass case)");
83  else
84  s = format (s, "fib %d src ip %U %s dst port %d: %s",
86  t->is_tcp ? "TCP" : "UDP", (u32) t->port,
87  (t->pass == 1) ? "PASS" : "FAIL");
88  return s;
89 }
90 
91 typedef enum
92 {
96 
97 
98 static inline u32
100  u16 dst_port, u32 next)
101 {
102  u16x8 key = u16x8_splat (dst_port);
103  int i;
104 
105  if (NULL == ppr_dpo || dst_port == 0)
107 
108 
109  for (i = 0; i < ppr_dpo->n_used_blocks; i++)
110  if (!u16x8_is_all_zero ((ppr_dpo->blocks[i].low.as_u16x8 <= key) &
111  (ppr_dpo->blocks[i].hi.as_u16x8 >= key)))
112  return next;
113 
115 }
116 
119 {
121 }
122 
126  vlib_frame_t * frame, int is_tx)
127 {
128  ip4_main_t *im = &ip4_main;
129  u32 n_left_from, *from, *to_next;
130  u32 next_index;
131  vlib_node_runtime_t *error_node = node;
132  u32 good_packets = 0;
133  int i;
134 
136  n_left_from = frame->n_vectors;
137  next_index = node->cached_next_index;
138 
139  while (n_left_from > 0)
140  {
141  u32 n_left_to_next;
142 
143  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
144 
145 
146  /* while (n_left_from >= 4 && n_left_to_next >= 2) */
147  /* { */
148  /* vlib_buffer_t *b0, *b1; */
149  /* ip4_header_t *ip0, *ip1; */
150  /* ip4_fib_mtrie_t *mtrie0, *mtrie1; */
151  /* ip4_fib_mtrie_leaf_t leaf0, leaf1; */
152  /* ip_source_and_port_range_check_config_t *c0, *c1; */
153  /* ip_adjacency_t *adj0 = 0, *adj1 = 0; */
154  /* u32 bi0, next0, adj_index0, pass0, save_next0, fib_index0; */
155  /* u32 bi1, next1, adj_index1, pass1, save_next1, fib_index1; */
156  /* udp_header_t *udp0, *udp1; */
157 
158  /* /\* Prefetch next iteration. *\/ */
159  /* { */
160  /* vlib_buffer_t *p2, *p3; */
161 
162  /* p2 = vlib_get_buffer (vm, from[2]); */
163  /* p3 = vlib_get_buffer (vm, from[3]); */
164 
165  /* vlib_prefetch_buffer_header (p2, LOAD); */
166  /* vlib_prefetch_buffer_header (p3, LOAD); */
167 
168  /* CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD); */
169  /* CLIB_PREFETCH (p3->data, sizeof (ip1[0]), LOAD); */
170  /* } */
171 
172  /* bi0 = to_next[0] = from[0]; */
173  /* bi1 = to_next[1] = from[1]; */
174  /* from += 2; */
175  /* to_next += 2; */
176  /* n_left_from -= 2; */
177  /* n_left_to_next -= 2; */
178 
179  /* b0 = vlib_get_buffer (vm, bi0); */
180  /* b1 = vlib_get_buffer (vm, bi1); */
181 
182  /* fib_index0 = */
183  /* vec_elt (im->fib_index_by_sw_if_index, */
184  /* vnet_buffer (b0)->sw_if_index[VLIB_RX]); */
185  /* fib_index1 = */
186  /* vec_elt (im->fib_index_by_sw_if_index, */
187  /* vnet_buffer (b1)->sw_if_index[VLIB_RX]); */
188 
189  /* ip0 = vlib_buffer_get_current (b0); */
190  /* ip1 = vlib_buffer_get_current (b1); */
191 
192  /* if (is_tx) */
193  /* { */
194  /* c0 = vnet_get_config_data (&tx_cm->config_main, */
195  /* &b0->current_config_index, */
196  /* &next0, sizeof (c0[0])); */
197  /* c1 = vnet_get_config_data (&tx_cm->config_main, */
198  /* &b1->current_config_index, */
199  /* &next1, sizeof (c1[0])); */
200  /* } */
201  /* else */
202  /* { */
203  /* c0 = vnet_get_config_data (&rx_cm->config_main, */
204  /* &b0->current_config_index, */
205  /* &next0, sizeof (c0[0])); */
206  /* c1 = vnet_get_config_data (&rx_cm->config_main, */
207  /* &b1->current_config_index, */
208  /* &next1, sizeof (c1[0])); */
209  /* } */
210 
211  /* /\* we can't use the default VRF here... *\/ */
212  /* for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++) */
213  /* { */
214  /* ASSERT (c0->fib_index[i] && c1->fib_index[i]); */
215  /* } */
216 
217 
218  /* if (is_tx) */
219  /* { */
220  /* if (ip0->protocol == IP_PROTOCOL_UDP) */
221  /* fib_index0 = */
222  /* c0->fib_index */
223  /* [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN]; */
224  /* if (ip0->protocol == IP_PROTOCOL_TCP) */
225  /* fib_index0 = */
226  /* c0->fib_index */
227  /* [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN]; */
228  /* } */
229  /* else */
230  /* { */
231  /* if (ip0->protocol == IP_PROTOCOL_UDP) */
232  /* fib_index0 = */
233  /* c0->fib_index */
234  /* [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT]; */
235  /* if (ip0->protocol == IP_PROTOCOL_TCP) */
236  /* fib_index0 = */
237  /* c0->fib_index */
238  /* [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT]; */
239  /* } */
240 
241  /* if (PREDICT_TRUE (fib_index0 != ~0)) */
242  /* { */
243 
244  /* mtrie0 = &vec_elt_at_index (im->fibs, fib_index0)->mtrie; */
245 
246  /* leaf0 = IP4_FIB_MTRIE_LEAF_ROOT; */
247 
248  /* leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, */
249  /* &ip0->src_address, 0); */
250 
251  /* leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, */
252  /* &ip0->src_address, 1); */
253 
254  /* leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, */
255  /* &ip0->src_address, 2); */
256 
257  /* leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, */
258  /* &ip0->src_address, 3); */
259 
260  /* adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0); */
261 
262  /* ASSERT (adj_index0 == ip4_fib_lookup_with_table (im, fib_index0, */
263  /* &ip0->src_address, */
264  /* 0 */
265  /* /\* use dflt rt *\/ */
266  /* )); */
267  /* adj0 = ip_get_adjacency (lm, adj_index0); */
268  /* } */
269 
270  /* if (is_tx) */
271  /* { */
272  /* if (ip1->protocol == IP_PROTOCOL_UDP) */
273  /* fib_index1 = */
274  /* c1->fib_index */
275  /* [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN]; */
276  /* if (ip1->protocol == IP_PROTOCOL_TCP) */
277  /* fib_index1 = */
278  /* c1->fib_index */
279  /* [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN]; */
280  /* } */
281  /* else */
282  /* { */
283  /* if (ip1->protocol == IP_PROTOCOL_UDP) */
284  /* fib_index1 = */
285  /* c1->fib_index */
286  /* [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT]; */
287  /* if (ip1->protocol == IP_PROTOCOL_TCP) */
288  /* fib_index1 = */
289  /* c1->fib_index */
290  /* [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT]; */
291  /* } */
292 
293  /* if (PREDICT_TRUE (fib_index1 != ~0)) */
294  /* { */
295 
296  /* mtrie1 = &vec_elt_at_index (im->fibs, fib_index1)->mtrie; */
297 
298  /* leaf1 = IP4_FIB_MTRIE_LEAF_ROOT; */
299 
300  /* leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, */
301  /* &ip1->src_address, 0); */
302 
303  /* leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, */
304  /* &ip1->src_address, 1); */
305 
306  /* leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, */
307  /* &ip1->src_address, 2); */
308 
309  /* leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, */
310  /* &ip1->src_address, 3); */
311 
312  /* adj_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1); */
313 
314  /* ASSERT (adj_index1 == ip4_fib_lookup_with_table (im, fib_index1, */
315  /* &ip1->src_address, */
316  /* 0)); */
317  /* adj1 = ip_get_adjacency (lm, adj_index1); */
318  /* } */
319 
320  /* pass0 = 0; */
321  /* pass0 |= adj0 == 0; */
322  /* pass0 |= ip4_address_is_multicast (&ip0->src_address); */
323  /* pass0 |= */
324  /* ip0->src_address.as_u32 == clib_host_to_net_u32 (0xFFFFFFFF); */
325  /* pass0 |= (ip0->protocol != IP_PROTOCOL_UDP) */
326  /* && (ip0->protocol != IP_PROTOCOL_TCP); */
327 
328  /* pass1 = 0; */
329  /* pass1 |= adj1 == 0; */
330  /* pass1 |= ip4_address_is_multicast (&ip1->src_address); */
331  /* pass1 |= */
332  /* ip1->src_address.as_u32 == clib_host_to_net_u32 (0xFFFFFFFF); */
333  /* pass1 |= (ip1->protocol != IP_PROTOCOL_UDP) */
334  /* && (ip1->protocol != IP_PROTOCOL_TCP); */
335 
336  /* save_next0 = next0; */
337  /* udp0 = ip4_next_header (ip0); */
338  /* save_next1 = next1; */
339  /* udp1 = ip4_next_header (ip1); */
340 
341  /* if (PREDICT_TRUE (pass0 == 0)) */
342  /* { */
343  /* good_packets++; */
344  /* next0 = check_adj_port_range_x1 */
345  /* (adj0, clib_net_to_host_u16 (udp0->dst_port), next0); */
346  /* good_packets -= (save_next0 != next0); */
347  /* b0->error = error_node->errors */
348  /* [IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_FAIL]; */
349  /* } */
350 
351  /* if (PREDICT_TRUE (pass1 == 0)) */
352  /* { */
353  /* good_packets++; */
354  /* next1 = check_adj_port_range_x1 */
355  /* (adj1, clib_net_to_host_u16 (udp1->dst_port), next1); */
356  /* good_packets -= (save_next1 != next1); */
357  /* b1->error = error_node->errors */
358  /* [IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_FAIL]; */
359  /* } */
360 
361  /* if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) */
362  /* && (b0->flags & VLIB_BUFFER_IS_TRACED))) */
363  /* { */
364  /* ip4_source_and_port_range_check_trace_t *t = */
365  /* vlib_add_trace (vm, node, b0, sizeof (*t)); */
366  /* t->pass = next0 == save_next0; */
367  /* t->bypass = pass0; */
368  /* t->fib_index = fib_index0; */
369  /* t->src_addr.as_u32 = ip0->src_address.as_u32; */
370  /* t->port = (pass0 == 0) ? */
371  /* clib_net_to_host_u16 (udp0->dst_port) : 0; */
372  /* t->is_tcp = ip0->protocol == IP_PROTOCOL_TCP; */
373  /* } */
374 
375  /* if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) */
376  /* && (b1->flags & VLIB_BUFFER_IS_TRACED))) */
377  /* { */
378  /* ip4_source_and_port_range_check_trace_t *t = */
379  /* vlib_add_trace (vm, node, b1, sizeof (*t)); */
380  /* t->pass = next1 == save_next1; */
381  /* t->bypass = pass1; */
382  /* t->fib_index = fib_index1; */
383  /* t->src_addr.as_u32 = ip1->src_address.as_u32; */
384  /* t->port = (pass1 == 0) ? */
385  /* clib_net_to_host_u16 (udp1->dst_port) : 0; */
386  /* t->is_tcp = ip1->protocol == IP_PROTOCOL_TCP; */
387  /* } */
388 
389  /* vlib_validate_buffer_enqueue_x2 (vm, node, next_index, */
390  /* to_next, n_left_to_next, */
391  /* bi0, bi1, next0, next1); */
392  /* } */
393 
394  while (n_left_from > 0 && n_left_to_next > 0)
395  {
396  vlib_buffer_t *b0;
397  ip4_header_t *ip0;
399  u32 bi0, next0, lb_index0, pass0, save_next0, fib_index0;
400  udp_header_t *udp0;
401  const protocol_port_range_dpo_t *ppr_dpo0 = NULL;
402  const dpo_id_t *dpo;
403  u32 sw_if_index0;
404 
405  bi0 = from[0];
406  to_next[0] = bi0;
407  from += 1;
408  to_next += 1;
409  n_left_from -= 1;
410  n_left_to_next -= 1;
411 
412  b0 = vlib_get_buffer (vm, bi0);
413  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
414 
415  fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
416 
417  if (is_tx)
418  vlib_buffer_advance (b0, sizeof (ethernet_header_t));
419 
420  ip0 = vlib_buffer_get_current (b0);
421 
422  c0 = vnet_feature_next_with_data (&next0, b0, sizeof (c0[0]));
423 
424  /* we can't use the default VRF here... */
426  {
427  ASSERT (c0->fib_index[i]);
428  }
429 
430 
431  if (is_tx)
432  {
433  if (ip0->protocol == IP_PROTOCOL_UDP)
434  fib_index0 =
435  c0->fib_index
437  if (ip0->protocol == IP_PROTOCOL_TCP)
438  fib_index0 =
439  c0->fib_index
441  }
442  else
443  {
444  if (ip0->protocol == IP_PROTOCOL_UDP)
445  fib_index0 =
446  c0->fib_index
448  if (ip0->protocol == IP_PROTOCOL_TCP)
449  fib_index0 =
450  c0->fib_index
452  }
453 
454  if (fib_index0 != ~0)
455  {
456  lb_index0 = ip4_fib_forwarding_lookup (fib_index0,
457  &ip0->src_address);
458 
459  dpo =
461 
462  if (ppr_dpo_type == dpo->dpoi_type)
463  {
464  ppr_dpo0 = protocol_port_range_dpo_get (dpo->dpoi_index);
465  }
466  /*
467  * else the lookup hit an enty that was no inserted
468  * by this range checker, which is the default route
469  */
470  }
471  /*
472  * $$$ which (src,dst) categories should we always pass?
473  */
474  pass0 = 0;
475  pass0 |= ip4_address_is_multicast (&ip0->src_address);
476  pass0 |=
477  ip0->src_address.as_u32 == clib_host_to_net_u32 (0xFFFFFFFF);
478  pass0 |= (ip0->protocol != IP_PROTOCOL_UDP)
479  && (ip0->protocol != IP_PROTOCOL_TCP);
480 
481  save_next0 = next0;
482  udp0 = ip4_next_header (ip0);
483 
484  if (PREDICT_TRUE (pass0 == 0))
485  {
486  good_packets++;
488  (ppr_dpo0, clib_net_to_host_u16 (udp0->dst_port), next0);
489  good_packets -= (save_next0 != next0);
490  b0->error = error_node->errors
491  [IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_FAIL];
492  }
493 
494  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
495  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
496  {
498  vlib_add_trace (vm, node, b0, sizeof (*t));
499  t->pass = next0 == save_next0;
500  t->bypass = pass0;
501  t->fib_index = fib_index0;
502  t->src_addr.as_u32 = ip0->src_address.as_u32;
503  t->port = (pass0 == 0) ?
504  clib_net_to_host_u16 (udp0->dst_port) : 0;
505  t->is_tcp = ip0->protocol == IP_PROTOCOL_TCP;
506  }
507 
508  if (is_tx)
509  vlib_buffer_advance (b0, -sizeof (ethernet_header_t));
510 
512  to_next, n_left_to_next,
513  bi0, next0);
514  }
515 
516  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
517  }
518 
519  if (is_tx)
521  IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_OK,
522  good_packets);
523  else
525  IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_OK,
526  good_packets);
527  return frame->n_vectors;
528 }
529 
530 static uword
534 {
536  0 /* !is_tx */ );
537 }
538 
539 static uword
543 {
545  1 /* is_tx */ );
546 }
547 
548 /* Note: Calling same function for both RX and TX nodes
549  as always checking dst_port, although
550  if this changes can easily make new function
551 */
552 
553 /* *INDENT-OFF* */
556  .name = "ip4-source-and-port-range-check-rx",
557  .vector_size = sizeof (u32),
558 
561 
563  .next_nodes = {
565  },
566 
567  .format_buffer = format_ip4_header,
569 };
570 /* *INDENT-ON* */
571 
572 /* *INDENT-OFF* */
575  .name = "ip4-source-and-port-range-check-tx",
576  .vector_size = sizeof (u32),
577 
580 
582  .next_nodes = {
584  },
585 
586  .format_buffer = format_ip4_header,
588 };
589 /* *INDENT-ON* */
590 
591 int
593  u32 * fib_index,
594  u32 sw_if_index, u32 is_add)
595 {
597  int rv = 0;
598  int i;
599 
601  {
602  config.fib_index[i] = fib_index[i];
603  }
604 
605  /* For OUT we are in the RX path */
606  if ((fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] != ~0) ||
608  {
609  vnet_feature_enable_disable ("ip4-unicast",
610  "ip4-source-and-port-range-check-rx",
611  sw_if_index, is_add, &config,
612  sizeof (config));
613  }
614 
615  /* For IN we are in the TX path */
616  if ((fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] != ~0) ||
618  {
619  vnet_feature_enable_disable ("ip4-output",
620  "ip4-source-and-port-range-check-tx",
621  sw_if_index, is_add, &config,
622  sizeof (config));
623  }
624  return rv;
625 }
626 
627 static clib_error_t *
629  unformat_input_t * input,
630  vlib_cli_command_t * cmd)
631 {
632  vnet_main_t *vnm = vnet_get_main ();
633  ip4_main_t *im = &ip4_main;
634  clib_error_t *error = 0;
635  u8 is_add = 1;
636  u32 sw_if_index = ~0;
639  int vrf_set = 0;
640  uword *p;
641  int rv = 0;
642  int i;
643 
644  sw_if_index = ~0;
646  {
647  fib_index[i] = ~0;
648  vrf_id[i] = ~0;
649  }
650 
652  {
653  if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
654  &sw_if_index))
655  ;
656  else
657  if (unformat
658  (input, "tcp-out-vrf %d",
660  vrf_set = 1;
661  else
662  if (unformat
663  (input, "udp-out-vrf %d",
665  vrf_set = 1;
666  else
667  if (unformat
668  (input, "tcp-in-vrf %d",
670  vrf_set = 1;
671  else
672  if (unformat
673  (input, "udp-in-vrf %d",
675  vrf_set = 1;
676  else if (unformat (input, "del"))
677  is_add = 0;
678  else
679  break;
680  }
681 
682  if (sw_if_index == ~0)
683  return clib_error_return (0, "Interface required but not specified");
684 
685  if (!vrf_set)
686  return clib_error_return (0,
687  "TCP or UDP VRF ID required but not specified");
688 
690  {
691 
692  if (vrf_id[i] == 0)
693  return clib_error_return (0,
694  "TCP, UDP VRF ID should not be 0 (default). Should be distinct VRF for this purpose. ");
695 
696  if (vrf_id[i] != ~0)
697  {
698  p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
699 
700  if (p == 0)
701  return clib_error_return (0, "Invalid VRF ID %d", vrf_id[i]);
702 
703  fib_index[i] = p[0];
704  }
705  }
706  rv =
707  set_ip_source_and_port_range_check (vm, fib_index, sw_if_index, is_add);
708 
709  switch (rv)
710  {
711  case 0:
712  break;
713 
714  default:
715  return clib_error_return
716  (0,
717  "set source and port-range on interface returned an unexpected value: %d",
718  rv);
719  }
720  return error;
721 }
722 
723 /*?
724  * Add the 'ip4-source-and-port-range-check-rx' or
725  * 'ip4-source-and-port-range-check-tx' graph node for a given
726  * interface. 'tcp-out-vrf' and 'udp-out-vrf' will add to
727  * the RX path. 'tcp-in-vrf' and 'udp-in-vrf' will add to
728  * the TX path. A graph node will be inserted into the chain when
729  * the range check is added to the first interface. It will not
730  * be removed from when range check is removed from the last
731  * interface.
732  *
733  * By adding the range check graph node to the interface, incoming
734  * or outgoing TCP/UDP packets will be validated using the
735  * provided IPv4 FIB table (VRF).
736  *
737  * @note 'ip4-source-and-port-range-check-rx' and
738  * 'ip4-source-and-port-range-check-tx' strings are too long, so
739  * they are truncated on the 'show vlib graph' output.
740  *
741  * @todo This content needs to be validated and potentially more detail added.
742  *
743  * @cliexpar
744  * @parblock
745  * Example of graph node before range checking is enabled:
746  * @cliexstart{show vlib graph ip4-source-and-port-range-check-tx}
747  * Name Next Previous
748  * ip4-source-and-port-range- ip4-drop [0]
749  * @cliexend
750  *
751  * Example of how to enable range checking on TX:
752  * @cliexcmd{set interface ip source-and-port-range-check GigabitEthernet2/0/0 udp-in-vrf 7}
753  *
754  * Example of graph node after range checking is enabled:
755  * @cliexstart{show vlib graph ip4-source-and-port-range-check-tx}
756  * Name Next Previous
757  * ip4-source-and-port-range- ip4-drop [0] ip4-rewrite
758  * interface-output [1]
759  * @cliexend
760  *
761  * Example of how to display the features enabed on an interface:
762  * @cliexstart{show ip interface features GigabitEthernet2/0/0}
763  * IP feature paths configured on GigabitEthernet2/0/0...
764  *
765  * ipv4 unicast:
766  * ip4-source-and-port-range-check-rx
767  * ip4-lookup
768  *
769  * ipv4 multicast:
770  * ip4-lookup-multicast
771  *
772  * ipv4 multicast:
773  * interface-output
774  *
775  * ipv6 unicast:
776  * ip6-lookup
777  *
778  * ipv6 multicast:
779  * ip6-lookup
780  *
781  * ipv6 multicast:
782  * interface-output
783  * @cliexend
784  * @endparblock
785 ?*/
786 /* *INDENT-OFF* */
788  .path = "set interface ip source-and-port-range-check",
790  .short_help = "set interface ip source-and-port-range-check <interface> [tcp-out-vrf <table-id>] [udp-out-vrf <table-id>] [tcp-in-vrf <table-id>] [udp-in-vrf <table-id>] [del]",
791 };
792 /* *INDENT-ON* */
793 
794 static u8 *
795 format_ppr_dpo (u8 * s, va_list * args)
796 {
797  index_t index = va_arg (*args, index_t);
798  CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
799 
800  protocol_port_range_dpo_t *ppr_dpo;
801  int i, j;
802  int printed = 0;
803 
805 
806  s = format (s, "allow ");
807 
808  for (i = 0; i < ppr_dpo->n_used_blocks; i++)
809  {
810  for (j = 0; j < 8; j++)
811  {
812  if (ppr_dpo->blocks[i].low.as_u16[j])
813  {
814  if (printed)
815  s = format (s, ", ");
816  if (ppr_dpo->blocks[i].hi.as_u16[j] >
817  (ppr_dpo->blocks[i].low.as_u16[j] + 1))
818  s =
819  format (s, "%d-%d", (u32) ppr_dpo->blocks[i].low.as_u16[j],
820  (u32) ppr_dpo->blocks[i].hi.as_u16[j] - 1);
821  else
822  s = format (s, "%d", ppr_dpo->blocks[i].low.as_u16[j]);
823  printed = 1;
824  }
825  }
826  }
827  return s;
828 }
829 
830 static void
832 {
833 }
834 
835 static void
837 {
838 }
839 
840 const static dpo_vft_t ppr_vft = {
842  .dv_unlock = ppr_dpo_unlock,
843  .dv_format = format_ppr_dpo,
844 };
845 
846 const static char *const ppr_ip4_nodes[] = {
847  "ip4-source-and-port-range-check-rx",
848  NULL,
849 };
850 
851 const static char *const *const ppr_nodes[DPO_PROTO_NUM] = {
853 };
854 
855 clib_error_t *
857 {
859 
860  srm->vlib_main = vm;
861  srm->vnet_main = vnet_get_main ();
862 
864 
865  return 0;
866 }
867 
869 
872 {
873  protocol_port_range_dpo_t *ppr_dpo;
874 
876  clib_memset (ppr_dpo, 0, sizeof (*ppr_dpo));
877 
879 
880  return (ppr_dpo);
881 }
882 
883 
884 static int
887  u32 length, u16 * low_ports, u16 * high_ports)
888 {
889  protocol_port_range_dpo_t *ppr_dpo;
890  dpo_id_t dpop = DPO_INVALID;
891  int i, j, k;
892 
893  fib_node_index_t fei;
894  fib_prefix_t pfx = {
896  .fp_len = length,
897  .fp_addr = {
898  .ip4 = *address,
899  },
900  };
901 
902  /*
903  * check to see if we have already sourced this prefix
904  */
905  fei = fib_table_lookup_exact_match (fib_index, &pfx);
906 
907  if (FIB_NODE_INDEX_INVALID == fei)
908  {
909  /*
910  * this is a first time add for this prefix.
911  */
912  ppr_dpo = protocol_port_range_dpo_alloc ();
913  }
914  else
915  {
916  /*
917  * the prefix is already there.
918  * check it was sourced by us, and if so get the ragne DPO from it.
919  */
920  dpo_id_t dpo = DPO_INVALID;
921  const dpo_id_t *bucket;
922 
924  {
925  /*
926  * there is existing state. we'll want to add the new ranges to it
927  */
928  bucket =
930  ppr_dpo = protocol_port_range_dpo_get (bucket->dpoi_index);
931  dpo_reset (&dpo);
932  }
933  else
934  {
935  /*
936  * there is no PPR state associated with this prefix,
937  * so we'll need a new DPO
938  */
939  ppr_dpo = protocol_port_range_dpo_alloc ();
940  }
941  }
942 
943  if (vec_len (low_ports) > ppr_dpo->n_free_ranges)
944  return VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
945 
946  j = k = 0;
947 
948  for (i = 0; i < vec_len (low_ports); i++)
949  {
950  for (; j < N_BLOCKS_PER_DPO; j++)
951  {
952  for (; k < 8; k++)
953  {
954  if (ppr_dpo->blocks[j].low.as_u16[k] == 0)
955  {
956  ppr_dpo->blocks[j].low.as_u16[k] = low_ports[i];
957  ppr_dpo->blocks[j].hi.as_u16[k] = high_ports[i];
958  goto doublebreak;
959  }
960  }
961  }
962  doublebreak:;
963  }
964  ppr_dpo->n_used_blocks = j + 1;
965 
966  /*
967  * add or update the entry in the FIB
968  */
969  dpo_set (&dpop, ppr_dpo_type, DPO_PROTO_IP4, (ppr_dpo - ppr_dpo_pool));
970 
971  if (FIB_NODE_INDEX_INVALID == fei)
972  {
974  &pfx,
976  FIB_ENTRY_FLAG_NONE, &dpop);
977  }
978  else
979  {
982  FIB_ENTRY_FLAG_NONE, &dpop);
983  }
984 
985  return 0;
986 }
987 
988 static int
991  u32 length, u16 * low_ports, u16 * high_ports)
992 {
993  protocol_port_range_dpo_t *ppr_dpo;
994  fib_node_index_t fei;
995  int i, j, k;
996 
997  fib_prefix_t pfx = {
999  .fp_len = length,
1000  .fp_addr = {
1001  .ip4 = *address,
1002  },
1003  };
1004 
1005  /*
1006  * check to see if we have sourced this prefix
1007  */
1008  fei = fib_table_lookup_exact_match (fib_index, &pfx);
1009 
1010  if (FIB_NODE_INDEX_INVALID == fei)
1011  {
1012  /*
1013  * not one of ours
1014  */
1015  return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE;
1016  }
1017  else
1018  {
1019  /*
1020  * the prefix is already there.
1021  * check it was sourced by us
1022  */
1023  dpo_id_t dpo = DPO_INVALID;
1024  const dpo_id_t *bucket;
1025 
1027  {
1028  /*
1029  * there is existing state. we'll want to add the new ranges to it
1030  */
1031  bucket =
1033  ppr_dpo = protocol_port_range_dpo_get (bucket->dpoi_index);
1034  dpo_reset (&dpo);
1035  }
1036  else
1037  {
1038  /*
1039  * not one of ours
1040  */
1041  return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE;
1042  }
1043  }
1044 
1045  for (i = 0; i < vec_len (low_ports); i++)
1046  {
1047  for (j = 0; j < N_BLOCKS_PER_DPO; j++)
1048  {
1049  for (k = 0; k < 8; k++)
1050  {
1051  if (low_ports[i] == ppr_dpo->blocks[j].low.as_u16[k] &&
1052  high_ports[i] == ppr_dpo->blocks[j].hi.as_u16[k])
1053  {
1054  ppr_dpo->blocks[j].low.as_u16[k] =
1055  ppr_dpo->blocks[j].hi.as_u16[k] = 0;
1056  goto doublebreak;
1057  }
1058  }
1059  }
1060  doublebreak:;
1061  }
1062 
1063  ppr_dpo->n_free_ranges = 0;
1064 
1065  /* Have we deleted all ranges yet? */
1066  for (i = 0; i < N_BLOCKS_PER_DPO; i++)
1067  {
1068  for (j = 0; j < 8; j++)
1069  {
1070  if (ppr_dpo->blocks[j].low.as_u16[i] == 0)
1071  ppr_dpo->n_free_ranges++;
1072  }
1073  }
1074 
1075  if (N_PORT_RANGES_PER_DPO == ppr_dpo->n_free_ranges)
1076  {
1077  /* Yes, lose the adjacency... */
1079  }
1080  else
1081  {
1082  /*
1083  * compact the ranges down to a contiguous block
1084  */
1085  // FIXME. TODO.
1086  }
1087 
1088  return 0;
1089 }
1090 
1091 // This will be moved to another file and implemented post API freeze.
1092 int
1094  u32 length,
1095  u32 vrf_id,
1096  u16 * low_ports,
1097  u16 * high_ports, int is_add)
1098 {
1099  u32 fib_index;
1100 
1101  fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
1102 
1103  ASSERT (~0 != fib_index);
1104 
1106 
1107  return 0;
1108 }
1109 
1110 int
1112  u32 length,
1113  u32 vrf_id,
1114  u16 * low_ports,
1115  u16 * high_ports, int is_add)
1116 {
1117  u32 fib_index;
1118 
1121 
1122  if (is_add == 0)
1123  {
1125  low_ports, high_ports);
1126  }
1127  else
1128  {
1130  low_ports, high_ports);
1131  }
1132 
1133  return 0;
1134 }
1135 
1136 static clib_error_t *
1138  unformat_input_t * input,
1139  vlib_cli_command_t * cmd)
1140 {
1141  u16 *low_ports = 0;
1142  u16 *high_ports = 0;
1143  u16 this_low;
1144  u16 this_hi;
1145  ip4_address_t ip4_addr;
1146  ip6_address_t ip6_addr; //This function will be moved to generic impl when v6 done.
1147  u32 length;
1148  u32 tmp, tmp2;
1149  u32 vrf_id = ~0;
1150  int is_add = 1, ip_ver = ~0;
1151  int rv;
1152 
1153 
1154  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1155  {
1156  if (unformat (input, "%U/%d", unformat_ip4_address, &ip4_addr, &length))
1157  ip_ver = 4;
1158  else
1159  if (unformat
1160  (input, "%U/%d", unformat_ip6_address, &ip6_addr, &length))
1161  ip_ver = 6;
1162  else if (unformat (input, "vrf %d", &vrf_id))
1163  ;
1164  else if (unformat (input, "del"))
1165  is_add = 0;
1166  else if (unformat (input, "port %d", &tmp))
1167  {
1168  if (tmp == 0 || tmp > 65535)
1169  return clib_error_return (0, "port %d out of range", tmp);
1170  this_low = tmp;
1171  this_hi = this_low + 1;
1172  vec_add1 (low_ports, this_low);
1173  vec_add1 (high_ports, this_hi);
1174  }
1175  else if (unformat (input, "range %d - %d", &tmp, &tmp2))
1176  {
1177  if (tmp > tmp2)
1178  return clib_error_return (0, "ports %d and %d out of order",
1179  tmp, tmp2);
1180  if (tmp == 0 || tmp > 65535)
1181  return clib_error_return (0, "low port %d out of range", tmp);
1182  if (tmp2 == 0 || tmp2 > 65535)
1183  return clib_error_return (0, "high port %d out of range", tmp2);
1184  this_low = tmp;
1185  this_hi = tmp2 + 1;
1186  vec_add1 (low_ports, this_low);
1187  vec_add1 (high_ports, this_hi);
1188  }
1189  else
1190  break;
1191  }
1192 
1193  if (ip_ver == ~0)
1194  return clib_error_return (0, " <address>/<mask> not specified");
1195 
1196  if (vrf_id == ~0)
1197  return clib_error_return (0, " VRF ID required, not specified");
1198 
1199  if (vec_len (low_ports) == 0)
1200  return clib_error_return (0,
1201  " Both VRF ID and range/port must be set for a protocol.");
1202 
1203  if (vrf_id == 0)
1204  return clib_error_return (0, " VRF ID can not be 0 (default).");
1205 
1206 
1207  if (ip_ver == 4)
1209  (&ip4_addr, length, vrf_id, low_ports, high_ports, is_add);
1210  else
1211  return clib_error_return (0, " IPv6 in subsequent patch");
1212 
1213  switch (rv)
1214  {
1215  case 0:
1216  break;
1217 
1218  case VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE:
1219  return clib_error_return
1220  (0, " Incorrect adjacency for add/del operation");
1221 
1222  case VNET_API_ERROR_EXCEEDED_NUMBER_OF_PORTS_CAPACITY:
1223  return clib_error_return (0, " Too many ports in add/del operation");
1224 
1225  case VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY:
1226  return clib_error_return
1227  (0, " Too many ranges requested for add operation");
1228 
1229  default:
1230  return clib_error_return (0, " returned an unexpected value: %d", rv);
1231  }
1232 
1233  return 0;
1234 }
1235 
1236 /*?
1237  * This command adds an IP Subnet and range of ports to be validated
1238  * by an IP FIB table (VRF).
1239  *
1240  * @todo This is incomplete. This needs a detailed description and a
1241  * practical example.
1242  *
1243  * @cliexpar
1244  * Example of how to add an IPv4 subnet and single port to an IPv4 FIB table:
1245  * @cliexcmd{set ip source-and-port-range-check vrf 7 172.16.1.0/24 port 23}
1246  * Example of how to add an IPv4 subnet and range of ports to an IPv4 FIB table:
1247  * @cliexcmd{set ip source-and-port-range-check vrf 7 172.16.1.0/24 range 23 - 100}
1248  * Example of how to delete an IPv4 subnet and single port from an IPv4 FIB table:
1249  * @cliexcmd{set ip source-and-port-range-check vrf 7 172.16.1.0/24 port 23 del}
1250  * Example of how to delete an IPv4 subnet and range of ports from an IPv4 FIB table:
1251  * @cliexcmd{set ip source-and-port-range-check vrf 7 172.16.1.0/24 range 23 - 100 del}
1252 ?*/
1253 /* *INDENT-OFF* */
1255  .path = "set ip source-and-port-range-check",
1257  .short_help =
1258  "set ip source-and-port-range-check vrf <table-id> <ip-addr>/<mask> {port nn | range <nn> - <nn>} [del]",
1259 };
1260 /* *INDENT-ON* */
1261 
1262 
1263 static clib_error_t *
1265  unformat_input_t * input,
1266  vlib_cli_command_t * cmd)
1267 {
1268  protocol_port_range_dpo_t *ppr_dpo;
1269  u32 fib_index;
1270  u8 addr_set = 0;
1271  u32 vrf_id = ~0;
1272  int rv, i, j;
1273  u32 port = 0;
1274  fib_prefix_t pfx = {
1276  .fp_len = 32,
1277  };
1278 
1279  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1280  {
1281  if (unformat (input, "%U", unformat_ip4_address, &pfx.fp_addr.ip4))
1282  addr_set = 1;
1283  else if (unformat (input, "vrf %d", &vrf_id))
1284  ;
1285  else if (unformat (input, "port %d", &port))
1286  ;
1287  else
1288  break;
1289  }
1290 
1291  if (addr_set == 0)
1292  return clib_error_return (0, "<address> not specified");
1293 
1294  if (vrf_id == ~0)
1295  return clib_error_return (0, "VRF ID required, not specified");
1296 
1297  fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
1298  if (~0 == fib_index)
1299  return clib_error_return (0, "VRF %d not found", vrf_id);
1300 
1301  /*
1302  * find the longest prefix match on the address requested,
1303  * check it was sourced by us
1304  */
1305  dpo_id_t dpo = DPO_INVALID;
1306  const dpo_id_t *bucket;
1307 
1308  if (!fib_entry_get_dpo_for_source (fib_table_lookup (fib_index, &pfx),
1309  FIB_SOURCE_SPECIAL, &dpo))
1310  {
1311  /*
1312  * not one of ours
1313  */
1314  vlib_cli_output (vm, "%U: src address drop", format_ip4_address,
1315  &pfx.fp_addr.ip4);
1316  return 0;
1317  }
1318 
1320  ppr_dpo = protocol_port_range_dpo_get (bucket->dpoi_index);
1321  dpo_reset (&dpo);
1322 
1323  if (port)
1324  {
1325  rv = check_adj_port_range_x1 (ppr_dpo, (u16) port, 1234);
1326  if (rv == 1234)
1327  vlib_cli_output (vm, "%U port %d PASS", format_ip4_address,
1328  &pfx.fp_addr.ip4, port);
1329  else
1330  vlib_cli_output (vm, "%U port %d FAIL", format_ip4_address,
1331  &pfx.fp_addr.ip4, port);
1332  return 0;
1333  }
1334  else
1335  {
1336  u8 *s;
1337 
1338  s = format (0, "%U: ", format_ip4_address, &pfx.fp_addr.ip4);
1339 
1340  for (i = 0; i < N_BLOCKS_PER_DPO; i++)
1341  {
1342  for (j = 0; j < 8; j++)
1343  {
1344  if (ppr_dpo->blocks[i].low.as_u16[j])
1345  s = format (s, "%d - %d ",
1346  (u32) ppr_dpo->blocks[i].low.as_u16[j],
1347  (u32) ppr_dpo->blocks[i].hi.as_u16[j]);
1348  }
1349  }
1350  vlib_cli_output (vm, "%s", s);
1351  vec_free (s);
1352  }
1353 
1354  return 0;
1355 }
1356 
1357 /*?
1358  * Display the range of ports being validated by an IPv4 FIB for a given
1359  * IP or subnet, or test if a given IP and port are being validated.
1360  *
1361  * @todo This is incomplete. This needs a detailed description and a
1362  * practical example.
1363  *
1364  * @cliexpar
1365  * Example of how to display the set of ports being validated for a given
1366  * IPv4 subnet:
1367  * @cliexstart{show ip source-and-port-range-check vrf 7 172.16.2.0}
1368  * 172.16.2.0: 23 - 101
1369  * @cliexend
1370  * Example of how to test to determine of a given Pv4 address and port
1371  * are being validated:
1372  * @cliexstart{show ip source-and-port-range-check vrf 7 172.16.2.2 port 23}
1373  * 172.16.2.2 port 23 PASS
1374  * @cliexend
1375  * @cliexstart{show ip source-and-port-range-check vrf 7 172.16.2.2 port 250}
1376  * 172.16.2.2 port 250 FAIL
1377  * @cliexend
1378  ?*/
1379 /* *INDENT-OFF* */
1381  .path = "show ip source-and-port-range-check",
1383  .short_help =
1384  "show ip source-and-port-range-check vrf <table-id> <ip-addr> [port <n>]",
1385 };
1386 /* *INDENT-ON* */
1387 
1388 /*
1389  * fd.io coding-style-patch-verification: ON
1390  *
1391  * Local Variables:
1392  * eval: (c-set-style "gnu")
1393  * End:
1394  */
load_balance.h
tmp
u32 * tmp
Definition: interface_output.c:1096
ip4_source_port_and_range_check_tx
vlib_node_registration_t ip4_source_port_and_range_check_tx
(constructor) VLIB_REGISTER_NODE (ip4_source_port_and_range_check_tx)
Definition: ip4_source_and_port_range_check.c:43
im
vnet_interface_main_t * im
Definition: interface_output.c:415
IP4_SOURCE_AND_PORT_RANGE_CHECK_N_NEXT
@ IP4_SOURCE_AND_PORT_RANGE_CHECK_N_NEXT
Definition: ip4_source_and_port_range_check.c:94
dpo_register_new_type
dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char *const *const *nodes)
Create and register a new DPO type.
Definition: dpo.c:349
dpo_id_t_::dpoi_index
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:190
DPO_INVALID
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:204
IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN
@ IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN
Definition: ip_source_and_port_range_check.h:34
fib_table_entry_special_dpo_add
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a 'special' entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:324
ip4_source_and_port_range_check_error_strings
static char * ip4_source_and_port_range_check_error_strings[]
Definition: ip4_source_and_port_range_check.c:57
dst_port
vl_api_ip_port_and_mask_t dst_port
Definition: flow_types.api:92
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
ip6_source_and_port_range_check_add_del
int ip6_source_and_port_range_check_add_del(ip6_address_t *address, u32 length, u32 vrf_id, u16 *low_ports, u16 *high_ports, int is_add)
Definition: ip4_source_and_port_range_check.c:1093
protocol_port_range_dpo_t_::blocks
protocol_port_range_t blocks[N_BLOCKS_PER_DPO]
the fixed size array of ranges
Definition: ip_source_and_port_range_check.h:125
ppr_dpo_unlock
static void ppr_dpo_unlock(dpo_id_t *dpo)
Definition: ip4_source_and_port_range_check.c:836
format_ip4_address
format_function_t format_ip4_address
Definition: format.h:73
ip4_source_and_port_range_check_init
clib_error_t * ip4_source_and_port_range_check_init(vlib_main_t *vm)
Definition: ip4_source_and_port_range_check.c:856
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
ip4_source_and_port_range_check_trace_t::bypass
u32 bypass
Definition: ip4_source_and_port_range_check.c:66
ip4_main
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1104
source_range_check_main
source_range_check_main_t source_range_check_main
Definition: ip4_source_and_port_range_check.c:21
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
dpo_id_t_::dpoi_type
dpo_type_t dpoi_type
the type
Definition: dpo.h:178
IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT
@ IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT
Definition: ip_source_and_port_range_check.h:31
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
ip_source_and_port_range_check_config_t
Definition: ip_source_and_port_range_check.h:38
ppr_dpo_pool
static protocol_port_range_dpo_t * ppr_dpo_pool
The pool of range chack DPOs.
Definition: ip4_source_and_port_range_check.c:35
pool_get_aligned
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:249
next
u16 * next
Definition: nat44_ei_out2in.c:718
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
clib_error_return
#define clib_error_return(e, args...)
Definition: error.h:99
u16x8vec_t::as_u16x8
u16x8 as_u16x8
Definition: ip_source_and_port_range_check.h:49
vlib_cli_command_t::path
char * path
Definition: cli.h:96
ip4_address_t::as_u32
u32 as_u32
Definition: ip4_packet.h:57
FIB_NODE_INDEX_INVALID
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:30
fib_table.h
u16
unsigned short u16
Definition: types.h:57
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
show_source_and_port_range_check
static vlib_cli_command_t show_source_and_port_range_check
(constructor) VLIB_CLI_COMMAND (show_source_and_port_range_check)
Definition: ip4_source_and_port_range_check.c:1380
port
u16 port
Definition: lb_types.api:73
ip4_source_and_port_range_check_trace_t::pass
u32 pass
Definition: ip4_source_and_port_range_check.c:65
fib_table_lookup
fib_node_index_t fib_table_lookup(u32 fib_index, const fib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
Definition: fib_table.c:68
ip4_source_and_port_range_check_trace_t
Definition: ip4_source_and_port_range_check.c:63
vnet_feature_next_with_data
static_always_inline void * vnet_feature_next_with_data(u32 *next0, vlib_buffer_t *b0, u32 n_data_bytes)
Definition: feature.h:309
unformat_input_t
struct _unformat_input_t unformat_input_t
vlib_frame_t
Definition: node.h:372
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
error
Definition: cJSON.c:88
IP4_SOURCE_AND_PORT_RANGE_CHECK_N_ERROR
@ IP4_SOURCE_AND_PORT_RANGE_CHECK_N_ERROR
Definition: ip4_source_and_port_range_check.c:54
key
typedef key
Definition: ipsec_types.api:91
ppr_dpo_type
static dpo_type_t ppr_dpo_type
Dynamically registered DPO type.
Definition: ip4_source_and_port_range_check.c:40
ppr_vft
const static dpo_vft_t ppr_vft
Definition: ip4_source_and_port_range_check.c:840
protocol_port_range_dpo_t_::n_used_blocks
u16 n_used_blocks
The number of blocks from the 'block' array below that have ranges configured.
Definition: ip_source_and_port_range_check.h:114
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
vec_elt
#define vec_elt(v, i)
Get vector value at index i.
Definition: vec_bootstrap.h:210
ip_source_and_port_range_check.h
ppr_nodes
const static char *const *const ppr_nodes[DPO_PROTO_NUM]
Definition: ip4_source_and_port_range_check.c:851
fib_table_entry_special_remove
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a 'special' entry from the FIB.
Definition: fib_table.c:424
vlib_node_runtime_t::errors
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:460
set_ip_source_and_port_range_check_fn
static clib_error_t * set_ip_source_and_port_range_check_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip4_source_and_port_range_check.c:628
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
ip4_address_is_multicast
static uword ip4_address_is_multicast(const ip4_address_t *a)
Definition: ip4_packet.h:446
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
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
set_ip_source_and_port_range_check
int set_ip_source_and_port_range_check(vlib_main_t *vm, u32 *fib_index, u32 sw_if_index, u32 is_add)
Definition: ip4_source_and_port_range_check.c:592
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
fib_entry_get_dpo_for_source
const int fib_entry_get_dpo_for_source(fib_node_index_t fib_entry_index, fib_source_t source, dpo_id_t *dpo)
Definition: fib_entry_src.c:1808
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
fib_entry_special_update
void fib_entry_special_update(fib_node_index_t fib_entry_index, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Definition: fib_entry.c:892
N_PORT_RANGES_PER_DPO
#define N_PORT_RANGES_PER_DPO
The number of supported ranges per-data path object.
Definition: ip_source_and_port_range_check.h:64
fib_table_find_or_create_and_lock
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, fib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1170
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
hash_get
#define hash_get(h, key)
Definition: hash.h:249
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
unformat_check_input
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS
@ IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS
Definition: ip_source_and_port_range_check.h:35
FIB_ENTRY_FLAG_NONE
@ FIB_ENTRY_FLAG_NONE
Definition: fib_entry.h:112
index_t
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:43
show_source_and_port_range_check_fn
static clib_error_t * show_source_and_port_range_check_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip4_source_and_port_range_check.c:1264
fib_node_index_t
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
uword
u64 uword
Definition: types.h:112
ethernet_header_t
Definition: packet.h:52
vlib_node_increment_counter
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1244
dpo_type_t
enum dpo_type_t_ dpo_type_t
Common types of data-path objects New types can be dynamically added using dpo_register_new_type()
load_balance_get_bucket_i
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:229
remove_port_range_adjacency
static int remove_port_range_adjacency(u32 fib_index, ip4_address_t *address, u32 length, u16 *low_ports, u16 *high_ports)
Definition: ip4_source_and_port_range_check.c:989
FIB_SOURCE_CLASSIFY
@ FIB_SOURCE_CLASSIFY
Classify.
Definition: fib_source.h:49
format_ip4_source_and_port_range_check_trace
static u8 * format_ip4_source_and_port_range_check_trace(u8 *s, va_list *va)
Definition: ip4_source_and_port_range_check.c:74
address
manual_print typedef address
Definition: ip_types.api:96
VLIB_CLI_COMMAND
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
source_range_check_main_t::vnet_main
vnet_main_t * vnet_main
Definition: ip_source_and_port_range_check.h:24
dpo_vft_t_::dv_lock
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:428
ip4_address_t
Definition: ip4_packet.h:50
FIB_PROTOCOL_IP4
@ FIB_PROTOCOL_IP4
Definition: fib_types.h:36
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:58
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
vlib_cli_output
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
fib_prefix_t_::fp_addr
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:225
ip4_source_and_port_range_check_trace_t::fib_index
u32 fib_index
Definition: ip4_source_and_port_range_check.c:70
IP4_SOURCE_AND_PORT_RANGE_CHECK_NEXT_DROP
@ IP4_SOURCE_AND_PORT_RANGE_CHECK_NEXT_DROP
Definition: ip4_source_and_port_range_check.c:93
ip_source_and_port_range_check_config_t::fib_index
u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS]
Definition: ip_source_and_port_range_check.h:40
fib_table_lookup_exact_match
fib_node_index_t fib_table_lookup_exact_match(u32 fib_index, const fib_prefix_t *prefix)
Perfom an exact match in the non-forwarding table.
Definition: fib_table.c:97
protocol_port_range_dpo_t_
The object that is in the data-path to perform the check.
Definition: ip_source_and_port_range_check.h:102
vnet_main_t
Definition: vnet.h:76
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
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
u16x8vec_t::as_u16
u16 as_u16[8]
Definition: ip_source_and_port_range_check.h:50
index
u32 index
Definition: flow_types.api:221
ip4_source_and_port_range_check_inline
static uword ip4_source_and_port_range_check_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_tx)
Definition: ip4_source_and_port_range_check.c:124
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
u16x8
_mm_packus_epi16 u16x8
Definition: vector_sse42.h:159
ip4_header_t::src_address
ip4_address_t src_address
Definition: ip4_packet.h:125
source_range_check_main_t::vlib_main
vlib_main_t * vlib_main
Definition: ip_source_and_port_range_check.h:23
unformat_vnet_sw_interface
unformat_function_t unformat_vnet_sw_interface
Definition: interface_funcs.h:462
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
ip.h
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
udp_header_t::dst_port
u16 dst_port
Definition: udp_packet.h:48
load_balance_get
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:220
ip4_source_and_port_range_check_trace_t::port
u16 port
Definition: ip4_source_and_port_range_check.c:69
protocol_port_range_t::low
u16x8vec_t low
Definition: ip_source_and_port_range_check.h:56
fib_prefix_t_::fp_proto
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:211
FIB_SOURCE_SPECIAL
@ FIB_SOURCE_SPECIAL
Special sources.
Definition: fib_source.h:45
vnet_feature_enable_disable
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: pnat_test_stubs.h:50
ip4_fib.h
format_ip4_header
format_function_t format_ip4_header
Definition: format.h:81
protocol_port_range_t::hi
u16x8vec_t hi
Definition: ip_source_and_port_range_check.h:57
length
char const int length
Definition: cJSON.h:163
foreach_ip4_source_and_port_range_check_error
#define foreach_ip4_source_and_port_range_check_error
Definition: ip4_source_and_port_range_check.c:45
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
format_ppr_dpo
static u8 * format_ppr_dpo(u8 *s, va_list *args)
Definition: ip4_source_and_port_range_check.c:795
vlib_node_t
Definition: node.h:247
dpo_vft_t_
A virtual function table regisitered for a DPO type.
Definition: dpo.h:423
ip4_source_port_and_range_check_rx
vlib_node_registration_t ip4_source_port_and_range_check_rx
(constructor) VLIB_REGISTER_NODE (ip4_source_port_and_range_check_rx)
Definition: ip4_source_and_port_range_check.c:42
ppr_ip4_nodes
const static char *const ppr_ip4_nodes[]
Definition: ip4_source_and_port_range_check.c:846
protocol_port_range_dpo_alloc
protocol_port_range_dpo_t * protocol_port_range_dpo_alloc(void)
Definition: ip4_source_and_port_range_check.c:871
vlib_add_trace
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
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
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
ip4_source_and_port_range_check_next_t
ip4_source_and_port_range_check_next_t
Definition: ip4_source_and_port_range_check.c:91
fib_table_unlock
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
Definition: fib_table.c:1342
i
int i
Definition: flowhash_template.h:376
DPO_PROTO_IP4
@ DPO_PROTO_IP4
Definition: dpo.h:64
ip4_source_and_port_range_check_rx
static uword ip4_source_and_port_range_check_rx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_source_and_port_range_check.c:531
protocol_port_range_dpo_t_::n_free_ranges
u16 n_free_ranges
The total number of free ranges from all blocks.
Definition: ip_source_and_port_range_check.h:120
dpo_id_t_
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:172
unformat_ip6_address
unformat_function_t unformat_ip6_address
Definition: format.h:89
rv
int __clib_unused rv
Definition: application.c:491
unformat_ip4_address
unformat_function_t unformat_ip4_address
Definition: format.h:68
check_adj_port_range_x1
static u32 check_adj_port_range_x1(const protocol_port_range_dpo_t *ppr_dpo, u16 dst_port, u32 next)
Definition: ip4_source_and_port_range_check.c:99
IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT
@ IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT
Definition: ip_source_and_port_range_check.h:32
vrf_id
u32 vrf_id
Definition: nat44_ed.api:1053
ip4_fib_forwarding_lookup
static index_t ip4_fib_forwarding_lookup(u32 fib_index, const ip4_address_t *addr)
Definition: ip4_fib.h:223
ppr_dpo_lock
static void ppr_dpo_lock(dpo_id_t *dpo)
Definition: ip4_source_and_port_range_check.c:831
source_range_check_main_t
Definition: ip_source_and_port_range_check.h:20
dpo_set
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:188
set_interface_ip_source_and_port_range_check_command
static vlib_cli_command_t set_interface_ip_source_and_port_range_check_command
(constructor) VLIB_CLI_COMMAND (set_interface_ip_source_and_port_range_check_command)
Definition: ip4_source_and_port_range_check.c:787
ip4_source_and_port_range_check_trace_t::is_tcp
u32 is_tcp
Definition: ip4_source_and_port_range_check.c:67
ip4_source_and_port_range_check_tx
static uword ip4_source_and_port_range_check_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_source_and_port_range_check.c:540
vlib_node_runtime_t
Definition: node.h:454
ip4_source_and_port_range_check_error_t
ip4_source_and_port_range_check_error_t
Definition: ip4_source_and_port_range_check.c:49
vlib_cli_command_t
Definition: cli.h:92
ip_source_and_port_range_check_command_fn
static clib_error_t * ip_source_and_port_range_check_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip4_source_and_port_range_check.c:1137
ip4_source_and_port_range_check_add_del
int ip4_source_and_port_range_check_add_del(ip4_address_t *address, u32 length, u32 vrf_id, u16 *low_ports, u16 *high_ports, int is_add)
Definition: ip4_source_and_port_range_check.c:1111
from
from
Definition: nat44_ei_hairpinning.c:415
PREDICT_TRUE
#define PREDICT_TRUE(x)
Definition: clib.h:125
ip4_main_t
IPv4 main type.
Definition: ip4.h:107
fib_table_find
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1111
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
add_port_range_adjacency
static int add_port_range_adjacency(u32 fib_index, ip4_address_t *address, u32 length, u16 *low_ports, u16 *high_ports)
Definition: ip4_source_and_port_range_check.c:885
ip_source_and_port_range_check_command
static vlib_cli_command_t ip_source_and_port_range_check_command
(constructor) VLIB_CLI_COMMAND (ip_source_and_port_range_check_command)
Definition: ip4_source_and_port_range_check.c:1254
dpo_reset
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:234
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
DPO_PROTO_NUM
#define DPO_PROTO_NUM
Definition: dpo.h:72
fib_prefix_t_
Aggregate type for a prefix.
Definition: fib_types.h:202
ip4_header_t::protocol
u8 protocol
Definition: ip4_packet.h:115
N_BLOCKS_PER_DPO
#define N_BLOCKS_PER_DPO
Definition: ip_source_and_port_range_check.h:66
UNFORMAT_END_OF_INPUT
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
ip4_next_header
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN
@ IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN
Definition: ip_source_and_port_range_check.h:33
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
ip4_source_and_port_range_check_trace_t::src_addr
ip4_address_t src_addr
Definition: ip4_source_and_port_range_check.c:68
protocol_port_range_dpo_get
static protocol_port_range_dpo_t * protocol_port_range_dpo_get(index_t index)
Definition: ip4_source_and_port_range_check.c:118