FD.io VPP  v19.08.3-2-gbabecb413
Vector Packet Processing
l3xc_node.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 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 
16 #include <plugins/l3xc/l3xc.h>
17 #include <vnet/feature/feature.h>
18 
19 typedef enum l3xc_next_t_
20 {
23 } l3xc_next_t;
24 
25 typedef struct l3xc_input_trace_t_
26 {
30 
31 typedef enum
32 {
33 #define l3xc_error(n,s) L3XC_ERROR_##n,
34 #include "l3xc_error.def"
35 #undef l3xc_error
36  L3XC_N_ERROR,
37 } l3xc_error_t;
38 
41  vlib_node_runtime_t * node,
42  vlib_frame_t * frame, fib_protocol_t fproto)
43 {
44  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
45  u16 nexts[VLIB_FRAME_SIZE], *next;
46  u32 n_left, *from;
47 
48  from = vlib_frame_vector_args (frame);
49  n_left = frame->n_vectors;
50  b = bufs;
51  next = nexts;
52 
53  vlib_get_buffers (vm, from, bufs, n_left);
54 
55  while (n_left >= 8)
56  {
57  const l3xc_t *l3xc0, *l3xc1, *l3xc2, *l3xc3;
58  u32 l3xci0, l3xci1, l3xci2, l3xci3;
59  u32 next_u32;
60 
61  /* Prefetch next iteration. */
62  {
63  vlib_prefetch_buffer_header (b[4], LOAD);
64  vlib_prefetch_buffer_header (b[5], LOAD);
65  vlib_prefetch_buffer_header (b[6], LOAD);
66  vlib_prefetch_buffer_header (b[7], LOAD);
67  }
68 
69  l3xci0 =
70  *(u32 *) vnet_feature_next_with_data (&next_u32, b[0],
71  sizeof (l3xci0));
72  l3xci1 =
73  *(u32 *) vnet_feature_next_with_data (&next_u32, b[1],
74  sizeof (l3xci1));
75  l3xci2 =
76  *(u32 *) vnet_feature_next_with_data (&next_u32, b[2],
77  sizeof (l3xci2));
78  l3xci3 =
79  *(u32 *) vnet_feature_next_with_data (&next_u32, b[3],
80  sizeof (l3xci3));
81 
82  l3xc0 = l3xc_get (l3xci0);
83  l3xc1 = l3xc_get (l3xci1);
84  l3xc2 = l3xc_get (l3xci2);
85  l3xc3 = l3xc_get (l3xci3);
86 
87  next[0] = l3xc0->l3xc_dpo.dpoi_next_node;
88  next[1] = l3xc1->l3xc_dpo.dpoi_next_node;
89  next[2] = l3xc2->l3xc_dpo.dpoi_next_node;
90  next[3] = l3xc3->l3xc_dpo.dpoi_next_node;
91 
92  vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = l3xc0->l3xc_dpo.dpoi_index;
93  vnet_buffer (b[1])->ip.adj_index[VLIB_TX] = l3xc1->l3xc_dpo.dpoi_index;
94  vnet_buffer (b[2])->ip.adj_index[VLIB_TX] = l3xc2->l3xc_dpo.dpoi_index;
95  vnet_buffer (b[3])->ip.adj_index[VLIB_TX] = l3xc3->l3xc_dpo.dpoi_index;
96 
98  {
99  if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
100  {
101  l3xc_input_trace_t *tr;
102 
103  tr = vlib_add_trace (vm, node, b[0], sizeof (*tr));
104  tr->l3xci = l3xci0;
105  tr->lbi = vnet_buffer (b[0])->ip.adj_index[VLIB_TX];
106  }
107  if (PREDICT_FALSE (b[1]->flags & VLIB_BUFFER_IS_TRACED))
108  {
109  l3xc_input_trace_t *tr;
110 
111  tr = vlib_add_trace (vm, node, b[1], sizeof (*tr));
112  tr->l3xci = l3xci1;
113  tr->lbi = vnet_buffer (b[1])->ip.adj_index[VLIB_TX];
114  }
115  if (PREDICT_FALSE (b[2]->flags & VLIB_BUFFER_IS_TRACED))
116  {
117  l3xc_input_trace_t *tr;
118 
119  tr = vlib_add_trace (vm, node, b[2], sizeof (*tr));
120  tr->l3xci = l3xci2;
121  tr->lbi = vnet_buffer (b[2])->ip.adj_index[VLIB_TX];
122  }
123  if (PREDICT_FALSE (b[3]->flags & VLIB_BUFFER_IS_TRACED))
124  {
125  l3xc_input_trace_t *tr;
126 
127  tr = vlib_add_trace (vm, node, b[3], sizeof (*tr));
128  tr->l3xci = l3xci3;
129  tr->lbi = vnet_buffer (b[3])->ip.adj_index[VLIB_TX];
130  }
131  }
132 
133  b += 4;
134  next += 4;
135  n_left -= 4;
136  }
137 
138  while (n_left > 0)
139  {
140  u32 l3xci0, next_u32;
141  const l3xc_t *l3xc0;
142 
143  l3xci0 =
144  *(u32 *) vnet_feature_next_with_data (&next_u32, b[0],
145  sizeof (l3xci0));
146 
147  l3xc0 = l3xc_get (l3xci0);
148 
149  next[0] = l3xc0->l3xc_dpo.dpoi_next_node;
150 
151  vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = l3xc0->l3xc_dpo.dpoi_index;
152 
153  if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
154  {
155  l3xc_input_trace_t *tr;
156 
157  tr = vlib_add_trace (vm, node, b[0], sizeof (*tr));
158  tr->l3xci = l3xci0;
159  tr->lbi = vnet_buffer (b[0])->ip.adj_index[VLIB_TX];
160  }
161 
162  b += 1;
163  next += 1;
164  n_left -= 1;
165  }
166 
167  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
168  return frame->n_vectors;
169 }
170 
171 static uword
173  vlib_node_runtime_t * node, vlib_frame_t * frame)
174 {
175  return l3xc_input_inline (vm, node, frame, FIB_PROTOCOL_IP4);
176 }
177 
178 static uword
180  vlib_node_runtime_t * node, vlib_frame_t * frame)
181 {
182  return l3xc_input_inline (vm, node, frame, FIB_PROTOCOL_IP6);
183 }
184 
185 static u8 *
186 format_l3xc_input_trace (u8 * s, va_list * args)
187 {
188  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
189  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
190  l3xc_input_trace_t *t = va_arg (*args, l3xc_input_trace_t *);
191 
192  s = format (s, "l3xc-index:%d lb-index:%d", t->l3xci, t->lbi);
193  return s;
194 }
195 
196 static char *l3xc_error_strings[] = {
197 #define l3xc_error(n,s) s,
198 #include "l3xc_error.def"
199 #undef l3xc_error
200 };
201 
202 /* *INDENT-OFF* */
203 VLIB_REGISTER_NODE (l3xc_ip4_node) =
204 {
205  .function = l3xc_input_ip4,
206  .name = "l3xc-input-ip4",
207  .vector_size = sizeof (u32),
208  .format_trace = format_l3xc_input_trace,
210  .n_errors = L3XC_N_ERROR,
211  .error_strings = l3xc_error_strings,
212  .n_next_nodes = L3XC_N_NEXT,
213  .next_nodes =
214  {
215  [L3XC_NEXT_DROP] = "error-drop",
216  }
217 };
218 
219 VLIB_REGISTER_NODE (l3xc_ip6_node) =
220 {
221  .function = l3xc_input_ip6,
222  .name = "l3xc-input-ip6",
223  .vector_size = sizeof (u32),
224  .format_trace = format_l3xc_input_trace,
226  .n_errors = 0,
227  .n_next_nodes = L3XC_N_NEXT,
228 
229  .next_nodes =
230  {
231  [L3XC_NEXT_DROP] = "error-drop",
232  }
233 };
234 
235 VNET_FEATURE_INIT (l3xc_ip4_feat, static) =
236 {
237  .arc_name = "ip4-unicast",
238  .node_name = "l3xc-input-ip4",
239  .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
240 };
241 
242 VNET_FEATURE_INIT (l3xc_ip6_feat, static) =
243 {
244  .arc_name = "ip6-unicast",
245  .node_name = "l3xc-input-ip6",
246  .runs_after = VNET_FEATURES ("acl-plugin-in-ip6-fa"),
247 };
248 /* *INDENT-ON* */
249 
250 /*
251  * fd.io coding-style-patch-verification: ON
252  *
253  * Local Variables:
254  * eval: (c-set-style "gnu")
255  * End:
256  */
u32 flags
Definition: vhost_user.h:141
Definition: l3xc.h:33
static uword l3xc_input_ip6(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: l3xc_node.c:179
#define CLIB_UNUSED(x)
Definition: clib.h:83
l3xc_next_t_
Definition: l3xc_node.c:19
l3xc_error_t
Definition: l3xc_node.c:31
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:41
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
struct l3xc_input_trace_t_ l3xc_input_trace_t
static u8 * format_l3xc_input_trace(u8 *s, va_list *args)
Definition: l3xc_node.c:186
dpo_id_t l3xc_dpo
DPO for forwarding.
Definition: l3xc.h:61
unsigned char u8
Definition: types.h:56
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
VNET_FEATURE_INIT(l3xc_ip4_feat, static)
#define always_inline
Definition: clib.h:99
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
unsigned int u32
Definition: types.h:88
static_always_inline l3xc_t * l3xc_get(u32 index)
Definition: l3xc.h:102
#define VLIB_FRAME_SIZE
Definition: node.h:378
vl_api_fib_path_type_t type
Definition: fib_types.api:123
static_always_inline void * vnet_feature_next_with_data(u32 *next0, vlib_buffer_t *b0, u32 n_data_bytes)
Definition: feature.h:289
unsigned short u16
Definition: types.h:57
static uword l3xc_input_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, fib_protocol_t fproto)
Definition: l3xc_node.c:40
#define PREDICT_FALSE(x)
Definition: clib.h:112
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:397
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:332
#define VNET_FEATURES(...)
Definition: feature.h:442
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
Definition: defs.h:47
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static uword l3xc_input_ip4(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: l3xc_node.c:172
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define vnet_buffer(b)
Definition: buffer.h:365
enum l3xc_next_t_ l3xc_next_t
u16 flags
Copy of main node flags.
Definition: node.h:509
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:244
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302