FD.io VPP  v21.10.1-2-g0a485f517
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;
85  mactime_device_t *dp;
87  clib_bihash_8_8_t *lut = &mm->lookup_table;
88  u32 packets_ok = 0;
89  f64 now;
91  vnet_main_t *vnm = vnet_get_main ();
95 
96  if (is_tx)
98 
100 
101  if (PREDICT_FALSE ((now - mm->sunday_midnight) > 86400.0 * 7.0))
103 
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  {
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];
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:
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:
313  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
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 */
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 
340  vlib_node_increment_counter (vm, node->node_index,
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  */
vlib.h
mactime_main_t::timebase
clib_timebase_t timebase
Definition: mactime.h:49
vnet_feature_config_main_t_
Definition: feature.h:80
im
vnet_interface_main_t * im
Definition: interface_output.c:415
mactime_trace_t::next_index
u32 next_index
Definition: node.c:25
vnet_feature_config_main_t_::config_main
vnet_config_main_t config_main
Definition: feature.h:82
MACTIME_DEVICE_FLAG_DYNAMIC_DROP
#define MACTIME_DEVICE_FLAG_DYNAMIC_DROP
Definition: mactime_device.h:40
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:495
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
mactime_send_create_entry_message
void mactime_send_create_entry_message(u8 *mac_address)
Create a lookup table entry for the indicated mac address.
Definition: mactime.c:248
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
src_mac
vl_api_mac_address_t src_mac
Definition: acl_types.api:94
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
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
ethernet_header_t::dst_address
u8 dst_address[6]
Definition: packet.h:55
MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA
#define MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW_QUOTA
Definition: mactime_device.h:42
ethernet_header_t::src_address
u8 src_address[6]
Definition: packet.h:56
mactime_device_t::device_name
u8 * device_name
Definition: mactime_device.h:27
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
mactime_main_t::drop_counters
vlib_combined_counter_main_t drop_counters
Definition: mactime.h:63
mactime_next_t
mactime_next_t
Definition: node.c:55
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
MACTIME_DEVICE_FLAG_STATIC_DROP
#define MACTIME_DEVICE_FLAG_STATIC_DROP
Always drop packets from this device.
Definition: mactime_device.h:38
clib_bihash_kv_8_8_t::value
u64 value
the value
Definition: bihash_8_8.h:44
clib_bihash_kv_8_8_t::key
u64 key
the key
Definition: bihash_8_8.h:43
vnet_interface_main_t
Definition: interface.h:990
MACTIME_N_ERROR
@ MACTIME_N_ERROR
Definition: node.c:46
MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW
#define MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW
Definition: mactime_device.h:41
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
format_mactime_trace
static u8 * format_mactime_trace(u8 *s, va_list *args)
Definition: node.c:64
clib_timebase_range_t
Definition: time_range.h:49
mactime_trace_t::device_index
u32 device_index
Definition: node.c:26
r
vnet_hw_if_output_node_runtime_t * r
Definition: interface_output.c:1089
vlib_frame_t
Definition: node.h:372
vlib_buffer_length_in_chain
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:433
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
mactime_tx_node
vlib_node_registration_t mactime_tx_node
(constructor) VLIB_REGISTER_NODE (mactime_tx_node)
Definition: node.c:32
format_mac_address
u8 * format_mac_address(u8 *s, va_list *args)
Definition: format.c:58
mactime_device_t
Definition: mactime_device.h:25
mactime_error_t
mactime_error_t
Definition: node.c:41
mactime_node_inline
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
mactime_trace_t::src_mac
u8 src_mac[6]
Definition: node.c:27
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
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
mactime.h
error.h
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
vlib_counter_t
Combined counter to hold both packets and byte differences.
Definition: counter_types.h:26
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
MACTIME_NEXT_ETHERNET_INPUT
@ MACTIME_NEXT_ETHERNET_INPUT
Definition: node.c:58
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
mactime_device_t::ranges
clib_timebase_range_t * ranges
Definition: mactime_device.h:34
mactime_main_t::sunday_midnight
f64 sunday_midnight
Definition: mactime.h:52
uword
u64 uword
Definition: types.h:112
ethernet_header_t
Definition: packet.h:52
vlib_main_t::thread_index
u32 thread_index
Definition: main.h:215
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
MACTIME_N_NEXT
@ MACTIME_N_NEXT
Definition: node.c:59
mactime_node
vlib_node_registration_t mactime_node
(constructor) VLIB_REGISTER_NODE (mactime_node)
Definition: node.c:31
mactime_main_t::allow_counters
vlib_combined_counter_main_t allow_counters
Definition: mactime.h:62
f64
double f64
Definition: types.h:142
mactime_error_strings
static char * mactime_error_strings[]
Definition: node.c:49
mactime_node_fn
static uword mactime_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:346
mactime_device_t::data_used_in_range
u64 data_used_in_range
Definition: mactime_device.h:30
mactime_device_t::flags
u32 flags
Definition: mactime_device.h:31
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
mactime_main_t::devices
mactime_device_t * devices
Definition: mactime.h:58
mactime_trace_t
Definition: node.c:23
MACTIME_NEXT_DROP
@ MACTIME_NEXT_DROP
Definition: node.c:57
vlib_buffer_t::current_config_index
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:156
arc
u8 arc
Definition: interface_output.c:426
vlib_get_combined_counter
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:272
vnet_main_t
Definition: vnet.h:76
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
mactime_tx_node_fn
static uword mactime_tx_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:376
format
description fragment has unexpected format
Definition: map.api:433
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
foreach_mactime_error
#define foreach_mactime_error
Definition: node.c:34
mactime_main
mactime_main_t mactime_main
Definition: mactime.c:38
u32
unsigned int u32
Definition: types.h:88
udp_header_t::dst_port
u16 dst_port
Definition: udp_packet.h:48
clib_timebase_now
static f64 clib_timebase_now(clib_timebase_t *tb)
Definition: time_range.h:88
vlib_counter_t::bytes
counter_t bytes
byte counter
Definition: counter_types.h:29
clib_bihash_kv_8_8_t
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
mactime_main_t
Definition: mactime.h:43
MACTIME_DEVICE_FLAG_STATIC_ALLOW
#define MACTIME_DEVICE_FLAG_STATIC_ALLOW
Definition: mactime_device.h:39
ip4.h
now
f64 now
Definition: nat44_ei_out2in.c:710
vlib_main_t
Definition: main.h:102
vnet_feature_get_config_main
static_always_inline vnet_feature_config_main_t * vnet_feature_get_config_main(u16 arc)
Definition: feature.h:244
vlib_node_t
Definition: node.h:247
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
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
ip
vl_api_address_t ip
Definition: l2.api:558
vnet_get_config_data
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
i
int i
Definition: flowhash_template.h:376
word
i64 word
Definition: types.h:111
mactime_main_t::lookup_table
clib_bihash_8_8_t lookup_table
Definition: mactime.h:55
vnet.h
vlib_node_runtime_t
Definition: node.h:454
clib_timebase_find_sunday_midnight
__clib_export f64 clib_timebase_find_sunday_midnight(f64 start_time)
Definition: time_range.c:221
from
from
Definition: nat44_ei_hairpinning.c:415
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
vnet_interface_main_t::output_feature_arc_index
u8 output_feature_arc_index
Definition: interface.h:1043
mactime_device_t::data_quota
u64 data_quota
Definition: mactime_device.h:29
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vnet_main_t::interface_main
vnet_interface_main_t interface_main
Definition: vnet.h:81
vlib_increment_combined_counter
vlib_increment_combined_counter(ccm, ti, sw_if_index, n_buffers, n_bytes)
mactime_trace_t::device_name
u8 device_name[64]
Definition: node.c:28
MACTIME_DEVICE_FLAG_DROP_UDP_10001
#define MACTIME_DEVICE_FLAG_DROP_UDP_10001
Definition: mactime_device.h:43
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
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169