FD.io VPP  v21.01.1
Vector Packet Processing
node.c
Go to the documentation of this file.
1 /*
2  * node.c - skeleton vpp engine plug-in dual-loop node skeleton
3  *
4  * Copyright (c) <current-year> <your-organization>
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #include <vlib/vlib.h>
18 #include <vnet/vnet.h>
19 #include <vppinfra/error.h>
20 #include <mactime/mactime.h>
21 #include <vnet/ip/ip4.h>
22 
23 typedef struct
24 {
27  u8 src_mac[6];
28  u8 device_name[64];
30 
33 
34 #define foreach_mactime_error \
35 _(OK, "Permitted packets") \
36 _(STATIC_DROP, "Static drop packets") \
37 _(RANGE_DROP, "Range drop packets") \
38 _(QUOTA_DROP, "Data quota drop packets") \
39 _(DROP_10001, "Dropped UDP DST-port 10001")
40 
41 typedef enum
42 {
43 #define _(sym,str) MACTIME_ERROR_##sym,
45 #undef _
48 
49 static char *mactime_error_strings[] = {
50 #define _(sym,string) string,
52 #undef _
53 };
54 
55 typedef enum
56 {
61 
62 /* packet trace format function */
63 static u8 *
64 format_mactime_trace (u8 * s, va_list * args)
65 {
66  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
67  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
68  mactime_trace_t *t = va_arg (*args, mactime_trace_t *);
69 
70  s = format (s, "MACTIME: src mac %U device %s result %s\n",
72  (t->device_index != ~0) ? t->device_name : (u8 *) "unknown",
73  t->next_index == MACTIME_NEXT_DROP ? "drop" : "pass");
74  return s;
75 }
76 
77 static uword
80  int is_tx)
81 {
82  u32 n_left_from, *from, *to_next;
83  mactime_next_t next_index;
85  mactime_device_t *dp;
87  clib_bihash_8_8_t *lut = &mm->lookup_table;
88  u32 packets_ok = 0;
89  f64 now;
90  u32 thread_index = vm->thread_index;
91  vnet_main_t *vnm = vnet_get_main ();
93  u8 arc = im->output_feature_arc_index;
95 
96  if (is_tx)
97  fcm = vnet_feature_get_config_main (arc);
98 
99  now = clib_timebase_now (&mm->timebase);
100 
101  if (PREDICT_FALSE ((now - mm->sunday_midnight) > 86400.0 * 7.0))
103 
104  from = vlib_frame_vector_args (frame);
105  n_left_from = frame->n_vectors;
106  next_index = node->cached_next_index;
107 
108  while (n_left_from > 0)
109  {
110  u32 n_left_to_next;
111 
112  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
113 
114  while (n_left_from > 0 && n_left_to_next > 0)
115  {
116  u32 bi0;
117  vlib_buffer_t *b0;
118  u32 next0;
119  u32 device_index0;
120  u32 len0;
121  ethernet_header_t *en0;
122  int has_dynamic_range_allow = 0;
123  int i;
124 
125  /* speculatively enqueue b0 to the current next frame */
126  bi0 = from[0];
127  to_next[0] = bi0;
128  from += 1;
129  to_next += 1;
130  n_left_from -= 1;
131  n_left_to_next -= 1;
132 
133  b0 = vlib_get_buffer (vm, bi0);
134 
135  /* Set next0 to e.g. interface-tx */
136  if (is_tx)
138  &b0->current_config_index, &next0,
139  /* # bytes of config data */ 0);
140  else
142 
143  vlib_buffer_advance (b0, -(word) vnet_buffer (b0)->l2_hdr_offset);
144 
145  len0 = vlib_buffer_length_in_chain (vm, b0);
146  en0 = vlib_buffer_get_current (b0);
147  kv.key = 0;
148  if (is_tx)
149  clib_memcpy_fast (&kv.key, en0->dst_address, 6);
150  else
151  clib_memcpy_fast (&kv.key, en0->src_address, 6);
152 
153  /* Lookup the src/dst mac address */
154  if (clib_bihash_search_8_8 (lut, &kv, &kv) < 0)
155  {
156  /* Create a table entry... */
158  (is_tx ? en0->dst_address : en0->src_address);
159 
160  /* and let this packet pass */
161  device_index0 = ~0;
162  dp = 0;
163  packets_ok++;
164  goto trace0;
165  }
166  else
167  device_index0 = kv.value;
168 
169  dp = pool_elt_at_index (mm->devices, device_index0);
170 
171  /* Known device, check for an always-on traffic quota */
173  && PREDICT_FALSE (dp->data_quota))
174  {
175  vlib_counter_t device_current_count;
177  dp - mm->devices,
178  &device_current_count);
179  if (device_current_count.bytes >= dp->data_quota)
180  {
181  next0 = MACTIME_NEXT_DROP;
182  b0->error = node->errors[MACTIME_ERROR_QUOTA_DROP];
184  (&mm->drop_counters, thread_index, dp - mm->devices, 1,
185  len0);
186  goto trace0;
187  }
188  }
189 
190  /* Static drop / allow? */
191  if (PREDICT_FALSE
192  (dp->flags &
195  {
197  {
198  next0 = MACTIME_NEXT_DROP;
199  b0->error = node->errors[MACTIME_ERROR_STATIC_DROP];
201  (&mm->drop_counters, thread_index, dp - mm->devices, 1,
202  len0);
203  }
204  else /* note next0 set to allow */
205  {
206  /*
207  * Special-case mini-ACL for a certain species of
208  * home security DVR which likes to "call home."
209  */
210  if (PREDICT_FALSE
212  {
213  ip4_header_t *ip = (void *) (((u8 *) en0) + 14);
214  udp_header_t *udp = (udp_header_t *) (ip + 1);
215  if (ip->protocol != IP_PROTOCOL_UDP)
216  goto pass;
217  if (clib_net_to_host_u16 (udp->dst_port) == 10001 ||
218  clib_net_to_host_u16 (udp->dst_port) == 9603)
219  {
220  next0 = MACTIME_NEXT_DROP;
221  b0->error = node->errors[MACTIME_ERROR_DROP_10001];
222  }
223  else
224  goto pass;
225  }
226  else
227  {
228  pass:
230  (&mm->allow_counters, thread_index, dp - mm->devices,
231  1, len0);
232  packets_ok++;
233  }
234  }
235  goto trace0;
236  }
237 
238  /* Known device, see if traffic allowed at the moment */
239  for (i = 0; i < vec_len (dp->ranges); i++)
240  {
241  clib_timebase_range_t *r = dp->ranges + i;
242  f64 start0, end0;
243 
244  start0 = r->start + mm->sunday_midnight;
245  end0 = r->end + mm->sunday_midnight;
247  has_dynamic_range_allow = 1;
248 
249  /* Packet within time range */
250  if (now >= start0 && now <= end0)
251  {
252  /* And it's a drop range, drop it */
254  {
256  (&mm->drop_counters, thread_index,
257  dp - mm->devices, 1, len0);
258  next0 = MACTIME_NEXT_DROP;
259  b0->error = node->errors[MACTIME_ERROR_RANGE_DROP];
260  goto trace0;
261  }
262  /* Quota-check allow range? */
263  else if (has_dynamic_range_allow)
264  {
265  if (dp->data_used_in_range + len0 >= dp->data_quota)
266  {
267  next0 = MACTIME_NEXT_DROP;
268  b0->error = node->errors[MACTIME_ERROR_QUOTA_DROP];
270  (&mm->drop_counters, thread_index,
271  dp - mm->devices, 1, len0);
272  goto trace0;
273  }
274  else
275  {
276  dp->data_used_in_range += len0;
277  goto allow0;
278  }
279  }
280  else
281  { /* it's an allow range, allow it */
282  allow0:
284  (&mm->allow_counters, thread_index,
285  dp - mm->devices, 1, len0);
286  packets_ok++;
287  goto trace0;
288  }
289  }
290  }
291  /*
292  * Didn't hit a range, so *drop* if allow configured, or
293  * *allow* if drop configured.
294  */
296  {
297  next0 = MACTIME_NEXT_DROP;
298  b0->error = node->errors[MACTIME_ERROR_STATIC_DROP];
300  (&mm->drop_counters, thread_index, dp - mm->devices, 1, len0);
301  }
302  else /* DYNAMIC_DROP, DYNAMIC_RANGE_ALLOW_QUOTA */
303  {
305  (&mm->allow_counters, thread_index, dp - mm->devices, 1,
306  len0);
307  /* Clear the data quota accumulater */
308  dp->data_used_in_range = 0;
309  packets_ok++;
310  }
311 
312  trace0:
314  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
315  {
316  mactime_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
318  sizeof (t->src_mac));
319 
320  t->next_index = next0;
321  t->device_index = device_index0;
322 
323  if (dp)
324  {
326  ARRAY_LEN (t->device_name));
327  t->device_name[ARRAY_LEN (t->device_name) - 1] = 0;
328  }
329  }
330 
331  /* verify speculative enqueue, maybe switch current next frame */
332  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
333  to_next, n_left_to_next,
334  bi0, next0);
335  }
336 
337  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
338  }
339 
341  MACTIME_ERROR_OK, packets_ok);
342  return frame->n_vectors;
343 }
344 
345 static uword
348 {
349  return mactime_node_inline (vm, node, frame, 0 /* is_tx */ );
350 }
351 
352 /* *INDENT-OFF* */
354 {
355  .function = mactime_node_fn,
356  .name = "mactime",
357  .vector_size = sizeof (u32),
358  .format_trace = format_mactime_trace,
360 
361  .n_errors = ARRAY_LEN(mactime_error_strings),
362  .error_strings = mactime_error_strings,
363 
364  .n_next_nodes = MACTIME_N_NEXT,
365 
366  /* edit / add dispositions here */
367  .next_nodes =
368  {
369  [MACTIME_NEXT_ETHERNET_INPUT] = "ethernet-input",
370  [MACTIME_NEXT_DROP] = "error-drop",
371  },
372 };
373 /* *INDENT-ON* */
374 
375 static uword
378 {
379  return mactime_node_inline (vm, node, frame, 1 /* is_tx */ );
380 }
381 
382 /* *INDENT-OFF* */
384 {
385  .function = mactime_tx_node_fn,
386  .name = "mactime-tx",
387  .vector_size = sizeof (u32),
388  .format_trace = format_mactime_trace,
390 
391  .n_errors = ARRAY_LEN(mactime_error_strings),
392  .error_strings = mactime_error_strings,
393 
394  .n_next_nodes = MACTIME_N_NEXT,
395 
396  /* edit / add dispositions here */
397  .next_nodes =
398  {
399  [MACTIME_NEXT_DROP] = "error-drop",
400  [MACTIME_NEXT_ETHERNET_INPUT] = "ethernet-input", /* notused */
401  },
402 };
403 /* *INDENT-ON* */
404 
405 /*
406  * fd.io coding-style-patch-verification: ON
407  *
408  * Local Variables:
409  * eval: (c-set-style "gnu")
410  * End:
411  */
u32 device_index
Definition: node.c:26
vnet_config_main_t config_main
Definition: feature.h:82
#define MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA
static char * mactime_error_strings[]
Definition: node.c:49
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
vlib_combined_counter_main_t drop_counters
Definition: mactime.h:63
#define foreach_mactime_error
Definition: node.c:34
#define CLIB_UNUSED(x)
Definition: clib.h:87
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:239
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vnet_interface_main_t interface_main
Definition: vnet.h:65
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
clib_timebase_t timebase
Definition: mactime.h:49
u8 src_address[6]
Definition: packet.h:56
u32 thread_index
Definition: main.h:250
#define MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW
Combined counter to hold both packets and byte differences.
Definition: counter_types.h:26
vlib_main_t * vm
Definition: in2out_ed.c:1580
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
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:402
vlib_node_registration_t mactime_tx_node
(constructor) VLIB_REGISTER_NODE (mactime_tx_node)
Definition: node.c:32
unsigned char u8
Definition: types.h:56
#define MACTIME_DEVICE_FLAG_DROP_UDP_10001
double f64
Definition: types.h:142
clib_timebase_range_t * ranges
i64 word
Definition: types.h:111
u8 dst_address[6]
Definition: packet.h:55
static f64 clib_timebase_now(clib_timebase_t *tb)
Definition: time_range.h:88
description fragment has unexpected format
Definition: map.api:433
unsigned int u32
Definition: types.h:88
u8 src_mac[6]
Definition: node.c:27
#define MACTIME_DEVICE_FLAG_STATIC_ALLOW
u8 device_name[64]
Definition: node.c:28
mactime_error_t
Definition: node.c:41
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
static uword mactime_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_tx)
Definition: node.c:78
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
mactime_main_t mactime_main
Definition: mactime.c:38
static uword mactime_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:346
vlib_combined_counter_main_t allow_counters
Definition: mactime.h:62
u64 key
the key
Definition: bihash_8_8.h:43
mactime_next_t
Definition: node.c:55
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
#define MACTIME_DEVICE_FLAG_DYNAMIC_DROP
static void * vnet_get_config_data(vnet_config_main_t *cm, u32 *config_index, u32 *next_index, u32 n_data_bytes)
Definition: config.h:123
vlib_node_registration_t mactime_node
(constructor) VLIB_REGISTER_NODE (mactime_node)
Definition: node.c:31
#define PREDICT_FALSE(x)
Definition: clib.h:121
u32 node_index
Node index.
Definition: node.h:488
#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
#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:391
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1231
u64 value
the value
Definition: bihash_8_8.h:44
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
u16 n_vectors
Definition: node.h:397
static void vlib_get_combined_counter(const vlib_combined_counter_main_t *cm, u32 index, vlib_counter_t *result)
Get the value of a combined counter, never called in the speed path Scrapes the entire set of per-thr...
Definition: counter.h:278
u32 next_index
Definition: node.c:25
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
f64 sunday_midnight
Definition: mactime.h:52
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:147
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
#define ARRAY_LEN(x)
Definition: clib.h:67
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:483
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
vl_api_mac_address_t src_mac
Definition: acl_types.api:94
mactime_device_t * devices
Definition: mactime.h:58
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:511
static uword mactime_tx_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:376
static u8 * format_mactime_trace(u8 *s, va_list *args)
Definition: node.c:64
#define MACTIME_DEVICE_FLAG_STATIC_DROP
Always drop packets from this device.
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:252
clib_bihash_8_8_t lookup_table
Definition: mactime.h:55
void mactime_send_create_entry_message(u8 *mac_address)
Create a lookup table entry for the indicated mac address.
Definition: mactime.c:248
struct _vlib_node_registration vlib_node_registration_t
counter_t bytes
byte counter
Definition: counter_types.h:29
vl_api_address_t ip
Definition: l2.api:501
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1581
VLIB buffer representation.
Definition: buffer.h:102
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:297
u8 * format_mac_address(u8 *s, va_list *args)
Definition: format.c:58
#define vnet_buffer(b)
Definition: buffer.h:417
u16 flags
Copy of main node flags.
Definition: node.h:501
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302
static_always_inline vnet_feature_config_main_t * vnet_feature_get_config_main(u16 arc)
Definition: feature.h:244
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
__clib_export f64 clib_timebase_find_sunday_midnight(f64 start_time)
Definition: time_range.c:221