FD.io VPP  v18.10-34-gcce845e
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 
23 typedef struct
24 {
27  u8 src_mac[6];
28  u8 device_name[64];
30 
33 
34 #define foreach_mactime_error \
35 _(DROP, "Dropped packets") \
36 _(OK, "Permitted packets")
37 
38 typedef enum
39 {
40 #define _(sym,str) MACTIME_ERROR_##sym,
42 #undef _
45 
46 static char *mactime_error_strings[] = {
47 #define _(sym,string) string,
49 #undef _
50 };
51 
52 typedef enum
53 {
58 
59 /* packet trace format function */
60 static u8 *
61 format_mactime_trace (u8 * s, va_list * args)
62 {
63  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
64  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
65  mactime_trace_t *t = va_arg (*args, mactime_trace_t *);
66 
67  s = format (s, "MACTIME: src mac %U device %s result %s\n",
69  (t->device_index != ~0) ? t->device_name : (u8 *) "unknown",
70  t->next_index == MACTIME_NEXT_DROP ? "drop" : "pass");
71  return s;
72 }
73 
74 static uword
76  vlib_node_runtime_t * node, vlib_frame_t * frame,
77  int is_tx)
78 {
79  u32 n_left_from, *from, *to_next;
80  mactime_next_t next_index;
82  mactime_device_t *dp;
84  clib_bihash_8_8_t *lut = &mm->lookup_table;
85  u32 packets_ok = 0, packets_dropped = 0;
86  f64 now;
87  u32 thread_index = vm->thread_index;
88  vnet_main_t *vnm = vnet_get_main ();
90  u8 arc = im->output_feature_arc_index;
92 
93  if (is_tx)
94  fcm = vnet_feature_get_config_main (arc);
95 
96  now = clib_timebase_now (&mm->timebase);
97 
98  if (PREDICT_FALSE ((now - mm->sunday_midnight) > 86400.0 * 7.0))
100 
101  from = vlib_frame_vector_args (frame);
102  n_left_from = frame->n_vectors;
103  next_index = node->cached_next_index;
104 
105  while (n_left_from > 0)
106  {
107  u32 n_left_to_next;
108 
109  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
110 
111  while (n_left_from > 0 && n_left_to_next > 0)
112  {
113  u32 bi0;
114  vlib_buffer_t *b0;
115  u32 next0;
116  u32 device_index0;
117  u32 len0;
118  ethernet_header_t *en0;
119  int i;
120 
121  /* speculatively enqueue b0 to the current next frame */
122  bi0 = from[0];
123  to_next[0] = bi0;
124  from += 1;
125  to_next += 1;
126  n_left_from -= 1;
127  n_left_to_next -= 1;
128 
129  b0 = vlib_get_buffer (vm, bi0);
130 
131  /* Set next0 to e.g. interface-tx */
132  if (is_tx)
134  &b0->current_config_index, &next0,
135  /* # bytes of config data */ 0);
136  else
138 
139  vlib_buffer_advance (b0, -(word) vnet_buffer (b0)->l2_hdr_offset);
140 
141  len0 = vlib_buffer_length_in_chain (vm, b0);
142  en0 = vlib_buffer_get_current (b0);
143  kv.key = 0;
144  if (is_tx)
145  clib_memcpy (&kv.key, en0->dst_address, 6);
146  else
147  clib_memcpy (&kv.key, en0->src_address, 6);
148 
149  /* Lookup the src/dst mac address */
150  if (clib_bihash_search_8_8 (lut, &kv, &kv) < 0)
151  {
152  /* Create a table entry... */
154  (is_tx ? en0->dst_address : en0->src_address);
155 
156  /* and let this packet pass */
157  device_index0 = ~0;
158  dp = 0;
159  packets_ok++;
160  goto trace0;
161  }
162  else
163  device_index0 = kv.value;
164 
165  dp = pool_elt_at_index (mm->devices, device_index0);
166 
167  /* Static drop / allow? */
168  if (PREDICT_FALSE
169  (dp->flags &
172  {
174  {
175  next0 = MACTIME_NEXT_DROP;
177  (&mm->drop_counters, thread_index, dp - mm->devices, 1,
178  len0);
179  packets_dropped++;
180  }
181  else /* note next0 set to allow */
182  {
184  (&mm->allow_counters, thread_index, dp - mm->devices, 1,
185  len0);
186  packets_ok++;
187  }
188  goto trace0;
189  }
190 
191  /* Known device, see if traffic allowed at the moment */
192  for (i = 0; i < vec_len (dp->ranges); i++)
193  {
194  clib_timebase_range_t *r = dp->ranges + i;
195  f64 start0, end0;
196 
197  start0 = r->start + mm->sunday_midnight;
198  end0 = r->end + mm->sunday_midnight;
199  /* Packet within time range */
200  if (now >= start0 && now <= end0)
201  {
202  /* And it's a drop range, drop it */
204  {
206  (&mm->drop_counters, thread_index,
207  dp - mm->devices, 1, len0);
208  packets_dropped++;
209  next0 = MACTIME_NEXT_DROP;
210  }
211  else /* it's an allow range, allow it */
212  {
214  (&mm->allow_counters, thread_index,
215  dp - mm->devices, 1, len0);
216  packets_ok++;
217  }
218  goto trace0;
219  }
220  }
221  /*
222  * Didn't hit a range, so *drop* if allow configured, or
223  * *allow* if drop configured.
224  */
226  {
227  next0 = MACTIME_NEXT_DROP;
229  (&mm->drop_counters, thread_index, dp - mm->devices, 1, len0);
230  packets_dropped++;
231  }
232  else
233  {
235  (&mm->allow_counters, thread_index, dp - mm->devices, 1,
236  len0);
237  packets_ok++;
238  }
239 
240  trace0:
242  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
243  {
244  mactime_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
245  clib_memcpy (t->src_mac, en0->src_address, sizeof (t->src_mac));
246 
247  t->next_index = next0;
248  t->device_index = device_index0;
249 
250  if (dp)
251  {
253  ARRAY_LEN (t->device_name));
254  t->device_name[ARRAY_LEN (t->device_name) - 1] = 0;
255  }
256  }
257 
258  /* verify speculative enqueue, maybe switch current next frame */
259  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
260  to_next, n_left_to_next,
261  bi0, next0);
262  }
263 
264  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
265  }
266 
268  MACTIME_ERROR_DROP, packets_dropped);
270  MACTIME_ERROR_OK, packets_ok);
271  return frame->n_vectors;
272 }
273 
274 static uword
276  vlib_node_runtime_t * node, vlib_frame_t * frame)
277 {
278  return mactime_node_inline (vm, node, frame, 0 /* is_tx */ );
279 }
280 
281 /* *INDENT-OFF* */
283 {
284  .function = mactime_node_fn,
285  .name = "mactime",
286  .vector_size = sizeof (u32),
287  .format_trace = format_mactime_trace,
288  .type = VLIB_NODE_TYPE_INTERNAL,
289 
290  .n_errors = ARRAY_LEN(mactime_error_strings),
291  .error_strings = mactime_error_strings,
292 
293  .n_next_nodes = MACTIME_N_NEXT,
294 
295  /* edit / add dispositions here */
296  .next_nodes =
297  {
298  [MACTIME_NEXT_ETHERNET_INPUT] = "ethernet-input",
299  [MACTIME_NEXT_DROP] = "error-drop",
300  },
301 };
302 /* *INDENT-ON* */
303 
304 static uword
306  vlib_node_runtime_t * node, vlib_frame_t * frame)
307 {
308  return mactime_node_inline (vm, node, frame, 1 /* is_tx */ );
309 }
310 
311 /* *INDENT-OFF* */
313 {
314  .function = mactime_tx_node_fn,
315  .name = "mactime-tx",
316  .vector_size = sizeof (u32),
317  .format_trace = format_mactime_trace,
318  .type = VLIB_NODE_TYPE_INTERNAL,
319 
320  .n_errors = ARRAY_LEN(mactime_error_strings),
321  .error_strings = mactime_error_strings,
322 
323  .n_next_nodes = MACTIME_N_NEXT,
324 
325  /* edit / add dispositions here */
326  .next_nodes =
327  {
328  [MACTIME_NEXT_DROP] = "error-drop",
329  [MACTIME_NEXT_ETHERNET_INPUT] = "ethernet-input", /* notused */
330  },
331 };
332 /* *INDENT-ON* */
333 
334 /*
335  * fd.io coding-style-patch-verification: ON
336  *
337  * Local Variables:
338  * eval: (c-set-style "gnu")
339  * End:
340  */
u32 device_index
Definition: node.c:26
vnet_config_main_t config_main
Definition: feature.h:65
vlib_combined_counter_main_t drop_counters
Definition: mactime.h:77
static char * mactime_error_strings[]
Definition: node.c:46
#define CLIB_UNUSED(x)
Definition: clib.h:81
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:204
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:135
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
vnet_interface_main_t interface_main
Definition: vnet.h:56
clib_timebase_t timebase
Definition: mactime.h:64
u8 src_address[6]
Definition: packet.h:56
mactime_next_t
Definition: node.c:52
u32 thread_index
Definition: main.h:179
int i
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:263
#define MACTIME_DEVICE_FLAG_DYNAMIC_ALLOW
Definition: mactime.h:47
unsigned char u8
Definition: types.h:56
double f64
Definition: types.h:142
clib_timebase_range_t * ranges
Definition: mactime.h:40
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:34
unsigned int u32
Definition: types.h:88
u8 src_mac[6]
Definition: node.c:27
u8 device_name[64]
Definition: node.c:28
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
mactime_main_t mactime_main
Definition: mactime.c:53
vlib_combined_counter_main_t allow_counters
Definition: mactime.h:76
u64 key
the key
Definition: bihash_8_8.h:33
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:205
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:32
#define PREDICT_FALSE(x)
Definition: clib.h:107
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:364
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1176
static uword mactime_tx_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:305
u64 value
the value
Definition: bihash_8_8.h:34
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:155
u16 n_vectors
Definition: node.h:401
vlib_main_t * vm
Definition: buffer.c:294
u32 next_index
Definition: node.c:25
f64 sunday_midnight
Definition: mactime.h:67
#define clib_memcpy(a, b, c)
Definition: string.h:75
f64 clib_timebase_find_sunday_midnight(f64 start_time)
Definition: time_range.c:213
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:31
#define ARRAY_LEN(x)
Definition: clib.h:61
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:455
#define MACTIME_DEVICE_FLAG_STATIC_DROP
Always drop packets from this device.
Definition: mactime.h:44
mactime_device_t * devices
Definition: mactime.h:73
mactime_error_t
Definition: node.c:38
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:218
clib_bihash_8_8_t lookup_table
Definition: mactime.h:70
void mactime_send_create_entry_message(u8 *mac_address)
Create a lookup table entry for the indicated mac address.
Definition: mactime.c:191
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:57
struct _vlib_node_registration vlib_node_registration_t
static u8 * format_mactime_trace(u8 *s, va_list *args)
Definition: node.c:61
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
static uword mactime_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_tx)
Definition: node.c:75
#define MACTIME_DEVICE_FLAG_STATIC_ALLOW
Definition: mactime.h:45
static uword mactime_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:275
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:31
#define vnet_buffer(b)
Definition: buffer.h:344
u8 * device_name
Definition: mactime.h:37
#define MACTIME_DEVICE_FLAG_DYNAMIC_DROP
Definition: mactime.h:46
u16 flags
Copy of main node flags.
Definition: node.h:507
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:310
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:116
static_always_inline vnet_feature_config_main_t * vnet_feature_get_config_main(u16 arc)
Definition: feature.h:185
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:58