FD.io VPP  v19.08-27-gf4dcae4
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 <vnet/pg/pg.h>
20 #include <vppinfra/error.h>
21 #include <mactime/mactime.h>
22 #include <vnet/ip/ip4.h>
23 
24 typedef struct
25 {
28  u8 src_mac[6];
29  u8 device_name[64];
31 
34 
35 #define foreach_mactime_error \
36 _(OK, "Permitted packets") \
37 _(STATIC_DROP, "Static drop packets") \
38 _(RANGE_DROP, "Range drop packets") \
39 _(QUOTA_DROP, "Data quota drop packets") \
40 _(DROP_10001, "Dropped UDP DST-port 10001")
41 
42 typedef enum
43 {
44 #define _(sym,str) MACTIME_ERROR_##sym,
46 #undef _
49 
50 static char *mactime_error_strings[] = {
51 #define _(sym,string) string,
53 #undef _
54 };
55 
56 typedef enum
57 {
62 
63 /* packet trace format function */
64 static u8 *
65 format_mactime_trace (u8 * s, va_list * args)
66 {
67  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
68  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
69  mactime_trace_t *t = va_arg (*args, mactime_trace_t *);
70 
71  s = format (s, "MACTIME: src mac %U device %s result %s\n",
73  (t->device_index != ~0) ? t->device_name : (u8 *) "unknown",
74  t->next_index == MACTIME_NEXT_DROP ? "drop" : "pass");
75  return s;
76 }
77 
78 static uword
80  vlib_node_runtime_t * node, vlib_frame_t * frame,
81  int is_tx)
82 {
83  u32 n_left_from, *from, *to_next;
84  mactime_next_t next_index;
86  mactime_device_t *dp;
88  clib_bihash_8_8_t *lut = &mm->lookup_table;
89  u32 packets_ok = 0;
90  f64 now;
91  u32 thread_index = vm->thread_index;
92  vnet_main_t *vnm = vnet_get_main ();
94  u8 arc = im->output_feature_arc_index;
96 
97  if (is_tx)
98  fcm = vnet_feature_get_config_main (arc);
99 
100  now = clib_timebase_now (&mm->timebase);
101 
102  if (PREDICT_FALSE ((now - mm->sunday_midnight) > 86400.0 * 7.0))
104 
105  from = vlib_frame_vector_args (frame);
106  n_left_from = frame->n_vectors;
107  next_index = node->cached_next_index;
108 
109  while (n_left_from > 0)
110  {
111  u32 n_left_to_next;
112 
113  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
114 
115  while (n_left_from > 0 && n_left_to_next > 0)
116  {
117  u32 bi0;
118  vlib_buffer_t *b0;
119  u32 next0;
120  u32 device_index0;
121  u32 len0;
122  ethernet_header_t *en0;
123  int has_dynamic_range_allow = 0;
124  int i;
125 
126  /* speculatively enqueue b0 to the current next frame */
127  bi0 = from[0];
128  to_next[0] = bi0;
129  from += 1;
130  to_next += 1;
131  n_left_from -= 1;
132  n_left_to_next -= 1;
133 
134  b0 = vlib_get_buffer (vm, bi0);
135 
136  /* Set next0 to e.g. interface-tx */
137  if (is_tx)
139  &b0->current_config_index, &next0,
140  /* # bytes of config data */ 0);
141  else
143 
144  vlib_buffer_advance (b0, -(word) vnet_buffer (b0)->l2_hdr_offset);
145 
146  len0 = vlib_buffer_length_in_chain (vm, b0);
147  en0 = vlib_buffer_get_current (b0);
148  kv.key = 0;
149  if (is_tx)
150  clib_memcpy_fast (&kv.key, en0->dst_address, 6);
151  else
152  clib_memcpy_fast (&kv.key, en0->src_address, 6);
153 
154  /* Lookup the src/dst mac address */
155  if (clib_bihash_search_8_8 (lut, &kv, &kv) < 0)
156  {
157  /* Create a table entry... */
159  (is_tx ? en0->dst_address : en0->src_address);
160 
161  /* and let this packet pass */
162  device_index0 = ~0;
163  dp = 0;
164  packets_ok++;
165  goto trace0;
166  }
167  else
168  device_index0 = kv.value;
169 
170  dp = pool_elt_at_index (mm->devices, device_index0);
171 
172  /* Known device, check for an always-on traffic quota */
174  && PREDICT_FALSE (dp->data_quota))
175  {
176  vlib_counter_t device_current_count;
178  dp - mm->devices,
179  &device_current_count);
180  if (device_current_count.bytes >= dp->data_quota)
181  {
182  next0 = MACTIME_NEXT_DROP;
183  b0->error = node->errors[MACTIME_ERROR_QUOTA_DROP];
185  (&mm->drop_counters, thread_index, dp - mm->devices, 1,
186  len0);
187  goto trace0;
188  }
189  }
190 
191  /* Static drop / allow? */
192  if (PREDICT_FALSE
193  (dp->flags &
196  {
198  {
199  next0 = MACTIME_NEXT_DROP;
200  b0->error = node->errors[MACTIME_ERROR_STATIC_DROP];
202  (&mm->drop_counters, thread_index, dp - mm->devices, 1,
203  len0);
204  }
205  else /* note next0 set to allow */
206  {
207  /*
208  * Special-case mini-ACL for a certain species of
209  * home security DVR which likes to "call home."
210  */
211  if (PREDICT_FALSE
213  {
214  ip4_header_t *ip = (void *) (((u8 *) en0) + 14);
215  udp_header_t *udp = (udp_header_t *) (ip + 1);
216  if (ip->protocol != IP_PROTOCOL_UDP)
217  goto pass;
218  if (clib_net_to_host_u16 (udp->dst_port) == 10001 ||
219  clib_net_to_host_u16 (udp->dst_port) == 9603)
220  {
221  next0 = MACTIME_NEXT_DROP;
222  b0->error = node->errors[MACTIME_ERROR_DROP_10001];
223  }
224  else
225  goto pass;
226  }
227  else
228  {
229  pass:
231  (&mm->allow_counters, thread_index, dp - mm->devices,
232  1, len0);
233  packets_ok++;
234  }
235  }
236  goto trace0;
237  }
238 
239  /* Known device, see if traffic allowed at the moment */
240  for (i = 0; i < vec_len (dp->ranges); i++)
241  {
242  clib_timebase_range_t *r = dp->ranges + i;
243  f64 start0, end0;
244 
245  start0 = r->start + mm->sunday_midnight;
246  end0 = r->end + mm->sunday_midnight;
248  has_dynamic_range_allow = 1;
249 
250  /* Packet within time range */
251  if (now >= start0 && now <= end0)
252  {
253  /* And it's a drop range, drop it */
255  {
257  (&mm->drop_counters, thread_index,
258  dp - mm->devices, 1, len0);
259  next0 = MACTIME_NEXT_DROP;
260  b0->error = node->errors[MACTIME_ERROR_RANGE_DROP];
261  goto trace0;
262  }
263  /* Quota-check allow range? */
264  else if (has_dynamic_range_allow)
265  {
266  if (dp->data_used_in_range + len0 >= dp->data_quota)
267  {
268  next0 = MACTIME_NEXT_DROP;
269  b0->error = node->errors[MACTIME_ERROR_QUOTA_DROP];
271  (&mm->drop_counters, thread_index,
272  dp - mm->devices, 1, len0);
273  goto trace0;
274  }
275  else
276  {
277  dp->data_used_in_range += len0;
278  goto allow0;
279  }
280  }
281  else
282  { /* it's an allow range, allow it */
283  allow0:
285  (&mm->allow_counters, thread_index,
286  dp - mm->devices, 1, len0);
287  packets_ok++;
288  goto trace0;
289  }
290  }
291  }
292  /*
293  * Didn't hit a range, so *drop* if allow configured, or
294  * *allow* if drop configured.
295  */
297  {
298  next0 = MACTIME_NEXT_DROP;
299  b0->error = node->errors[MACTIME_ERROR_STATIC_DROP];
301  (&mm->drop_counters, thread_index, dp - mm->devices, 1, len0);
302  }
303  else /* DYNAMIC_DROP, DYNAMIC_RANGE_ALLOW_QUOTA */
304  {
306  (&mm->allow_counters, thread_index, dp - mm->devices, 1,
307  len0);
308  /* Clear the data quota accumulater */
309  dp->data_used_in_range = 0;
310  packets_ok++;
311  }
312 
313  trace0:
315  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
316  {
317  mactime_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
319  sizeof (t->src_mac));
320 
321  t->next_index = next0;
322  t->device_index = device_index0;
323 
324  if (dp)
325  {
327  ARRAY_LEN (t->device_name));
328  t->device_name[ARRAY_LEN (t->device_name) - 1] = 0;
329  }
330  }
331 
332  /* verify speculative enqueue, maybe switch current next frame */
333  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
334  to_next, n_left_to_next,
335  bi0, next0);
336  }
337 
338  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
339  }
340 
342  MACTIME_ERROR_OK, packets_ok);
343  return frame->n_vectors;
344 }
345 
346 static uword
348  vlib_node_runtime_t * node, vlib_frame_t * frame)
349 {
350  return mactime_node_inline (vm, node, frame, 0 /* is_tx */ );
351 }
352 
353 /* *INDENT-OFF* */
355 {
356  .function = mactime_node_fn,
357  .name = "mactime",
358  .vector_size = sizeof (u32),
359  .format_trace = format_mactime_trace,
361 
362  .n_errors = ARRAY_LEN(mactime_error_strings),
363  .error_strings = mactime_error_strings,
364 
365  .n_next_nodes = MACTIME_N_NEXT,
366 
367  /* edit / add dispositions here */
368  .next_nodes =
369  {
370  [MACTIME_NEXT_ETHERNET_INPUT] = "ethernet-input",
371  [MACTIME_NEXT_DROP] = "error-drop",
372  },
373 };
374 /* *INDENT-ON* */
375 
376 static uword
378  vlib_node_runtime_t * node, vlib_frame_t * frame)
379 {
380  return mactime_node_inline (vm, node, frame, 1 /* is_tx */ );
381 }
382 
383 /* *INDENT-OFF* */
385 {
386  .function = mactime_tx_node_fn,
387  .name = "mactime-tx",
388  .vector_size = sizeof (u32),
389  .format_trace = format_mactime_trace,
391 
392  .n_errors = ARRAY_LEN(mactime_error_strings),
393  .error_strings = mactime_error_strings,
394 
395  .n_next_nodes = MACTIME_N_NEXT,
396 
397  /* edit / add dispositions here */
398  .next_nodes =
399  {
400  [MACTIME_NEXT_DROP] = "error-drop",
401  [MACTIME_NEXT_ETHERNET_INPUT] = "ethernet-input", /* notused */
402  },
403 };
404 /* *INDENT-ON* */
405 
406 /*
407  * fd.io coding-style-patch-verification: ON
408  *
409  * Local Variables:
410  * eval: (c-set-style "gnu")
411  * End:
412  */
u32 device_index
Definition: node.c:27
vnet_config_main_t config_main
Definition: feature.h:82
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:81
static char * mactime_error_strings[]
Definition: node.c:50
#define CLIB_UNUSED(x)
Definition: clib.h:82
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:220
#define MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA
Definition: mactime.h:50
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vnet_interface_main_t interface_main
Definition: vnet.h:56
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
clib_timebase_t timebase
Definition: mactime.h:68
u8 src_address[6]
Definition: packet.h:56
mactime_next_t
Definition: node.c:56
u32 thread_index
Definition: main.h:197
Combined counter to hold both packets and byte differences.
Definition: counter_types.h:26
int i
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:468
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:366
#define MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW
Definition: mactime.h:49
unsigned char u8
Definition: types.h:56
double f64
Definition: types.h:142
clib_timebase_range_t * ranges
Definition: mactime.h:42
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:92
#define foreach_mactime_error
Definition: node.c:35
unsigned int u32
Definition: types.h:88
u8 src_mac[6]
Definition: node.c:28
u8 device_name[64]
Definition: node.c:29
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
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
mactime_main_t mactime_main
Definition: mactime.c:53
vlib_combined_counter_main_t allow_counters
Definition: mactime.h:80
u64 key
the key
Definition: bihash_8_8.h:35
u64 data_used_in_range
Definition: mactime.h:40
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
static void * vnet_get_config_data(vnet_config_main_t *cm, u32 *config_index, u32 *next_index, u32 n_data_bytes)
Definition: config.h:122
vlib_node_registration_t mactime_tx_node
(constructor) VLIB_REGISTER_NODE (mactime_tx_node)
Definition: node.c:33
#define PREDICT_FALSE(x)
Definition: clib.h:111
u32 node_index
Node index.
Definition: node.h:494
#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
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:338
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
static uword mactime_tx_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:377
u64 value
the value
Definition: bihash_8_8.h:36
#define MACTIME_DEVICE_FLAG_DROP_UDP_10001
Definition: mactime.h:51
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:395
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:259
vlib_main_t * vm
Definition: buffer.c:312
u32 next_index
Definition: node.c:26
f64 sunday_midnight
Definition: mactime.h:71
f64 clib_timebase_find_sunday_midnight(f64 start_time)
Definition: time_range.c:213
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:33
#define ARRAY_LEN(x)
Definition: clib.h:62
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:458
#define MACTIME_DEVICE_FLAG_STATIC_DROP
Always drop packets from this device.
Definition: mactime.h:46
mactime_device_t * devices
Definition: mactime.h:77
mactime_error_t
Definition: node.c:42
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
clib_bihash_8_8_t lookup_table
Definition: mactime.h:74
void mactime_send_create_entry_message(u8 *mac_address)
Create a lookup table entry for the indicated mac address.
Definition: mactime.c:188
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
struct _vlib_node_registration vlib_node_registration_t
counter_t bytes
byte counter
Definition: counter_types.h:29
static u8 * format_mactime_trace(u8 *s, va_list *args)
Definition: node.c:65
vl_api_address_t ip
Definition: l2.api:489
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
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:244
static uword mactime_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_tx)
Definition: node.c:79
#define MACTIME_DEVICE_FLAG_STATIC_ALLOW
Definition: mactime.h:47
static uword mactime_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:347
u8 * format_mac_address(u8 *s, va_list *args)
Definition: format.c:58
vlib_node_registration_t mactime_node
(constructor) VLIB_REGISTER_NODE (mactime_node)
Definition: node.c:32
#define vnet_buffer(b)
Definition: buffer.h:361
u8 * device_name
Definition: mactime.h:37
#define MACTIME_DEVICE_FLAG_DYNAMIC_DROP
Definition: mactime.h:48
u16 flags
Copy of main node flags.
Definition: node.h:507
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:301
static_always_inline vnet_feature_config_main_t * vnet_feature_get_config_main(u16 arc)
Definition: feature.h:234
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