FD.io VPP  v16.06
Vector Packet Processing
ip4_hop_by_hop.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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 <vlib/vlib.h>
17 #include <vnet/vnet.h>
18 #include <vnet/pg/pg.h>
19 #include <vppinfra/error.h>
20 
21 #include <vnet/ip/ip.h>
22 
23 #include <vppinfra/hash.h>
24 #include <vppinfra/error.h>
25 #include <vppinfra/elog.h>
26 
27 typedef struct {
28  /* convenience */
32 
34 
36 
37 typedef struct {
40 
41 /* packet trace format function */
42 static u8 * format_ip4_hop_by_hop_trace (u8 * s, va_list * args)
43 {
44  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
45  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
46  ip4_hop_by_hop_trace_t * t = va_arg (*args, ip4_hop_by_hop_trace_t *);
47 
48  s = format (s, "IP4_HOP_BY_HOP: next index %d",
49  t->next_index);
50  return s;
51 }
52 
54 
55 #define foreach_ip4_hop_by_hop_error \
56 _(PROCESSED, "Pkts with ip4 hop-by-hop options")
57 
58 typedef enum {
59 #define _(sym,str) IP4_HOP_BY_HOP_ERROR_##sym,
61 #undef _
64 
65 static char * ip4_hop_by_hop_error_strings[] = {
66 #define _(sym,string) string,
68 #undef _
69 };
70 
71 static uword
73  vlib_node_runtime_t * node,
74  vlib_frame_t * frame)
75 {
76  ip4_main_t * im = &ip4_main;
77  ip_lookup_main_t * lm = &im->lookup_main;
78  u32 n_left_from, * from, * to_next;
79  ip_lookup_next_t next_index;
80  u32 processed = 0;
81 
82  from = vlib_frame_vector_args (frame);
83  n_left_from = frame->n_vectors;
84  next_index = node->cached_next_index;
85 
86  while (n_left_from > 0)
87  {
88  u32 n_left_to_next;
89 
90  vlib_get_next_frame (vm, node, next_index,
91  to_next, n_left_to_next);
92 
93 #if 0
94  while (n_left_from >= 4 && n_left_to_next >= 2)
95  {
96  u32 next0 = IP4_HOP_BY_HOP_NEXT_INTERFACE_OUTPUT;
97  u32 next1 = IP4_HOP_BY_HOP_NEXT_INTERFACE_OUTPUT;
98  u32 sw_if_index0, sw_if_index1;
99  u8 tmp0[6], tmp1[6];
100  ethernet_header_t *en0, *en1;
101  u32 bi0, bi1;
102  vlib_buffer_t * b0, * b1;
103 
104  /* Prefetch next iteration. */
105  {
106  vlib_buffer_t * p2, * p3;
107 
108  p2 = vlib_get_buffer (vm, from[2]);
109  p3 = vlib_get_buffer (vm, from[3]);
110 
111  vlib_prefetch_buffer_header (p2, LOAD);
112  vlib_prefetch_buffer_header (p3, LOAD);
113 
116  }
117 
118  /* speculatively enqueue b0 and b1 to the current next frame */
119  to_next[0] = bi0 = from[0];
120  to_next[1] = bi1 = from[1];
121  from += 2;
122  to_next += 2;
123  n_left_from -= 2;
124  n_left_to_next -= 2;
125 
126  b0 = vlib_get_buffer (vm, bi0);
127  b1 = vlib_get_buffer (vm, bi1);
128 
129  /* $$$$$ Dual loop: process 2 x packets here $$$$$ */
130  ASSERT (b0->current_data == 0);
131  ASSERT (b1->current_data == 0);
132 
133  ip0 = vlib_buffer_get_current (b0);
134  ip1 = vlib_buffer_get_current (b0);
135 
136  sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
137  sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
138 
139  /* $$$$$ End of processing 2 x packets $$$$$ */
140 
142  {
143  if (b0->flags & VLIB_BUFFER_IS_TRACED)
144  {
146  vlib_add_trace (vm, node, b0, sizeof (*t));
147  t->sw_if_index = sw_if_index0;
148  t->next_index = next0;
149  }
150  if (b1->flags & VLIB_BUFFER_IS_TRACED)
151  {
153  vlib_add_trace (vm, node, b1, sizeof (*t));
154  t->sw_if_index = sw_if_index1;
155  t->next_index = next1;
156  }
157  }
158 
159  /* verify speculative enqueues, maybe switch current next frame */
160  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
161  to_next, n_left_to_next,
162  bi0, bi1, next0, next1);
163  }
164 #endif
165 
166  while (n_left_from > 0 && n_left_to_next > 0)
167  {
168  u32 bi0;
169  vlib_buffer_t * b0;
170  u32 next0;
171  u32 adj_index0;
172  ip_adjacency_t * adj0;
173 
174  /* speculatively enqueue b0 to the current next frame */
175  bi0 = from[0];
176  to_next[0] = bi0;
177  from += 1;
178  to_next += 1;
179  n_left_from -= 1;
180  n_left_to_next -= 1;
181 
182  b0 = vlib_get_buffer (vm, bi0);
183 
184  adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
185  adj0 = ip_get_adjacency (lm, adj_index0);
186 
187  /* $$$$$$$$$$$$ process one (or more) hop-by-hop header(s) here */
188 
189 
190  /* $$$$$$$$$$$$ */
191 
192  /* Send the packet e.g. to ip4_rewrite */
193  next0 = adj0->lookup_next_index;
194 
196  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
197  {
199  vlib_add_trace (vm, node, b0, sizeof (*t));
200  t->next_index = next0;
201  }
202 
203  processed++;
204 
205  /* $$$$$ Done processing 1 packet here $$$$$ */
206 
207  /* verify speculative enqueue, maybe switch current next frame */
208  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
209  to_next, n_left_to_next,
210  bi0, next0);
211  }
212 
213  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
214  }
215 
217  IP4_HOP_BY_HOP_ERROR_PROCESSED, processed);
218  return frame->n_vectors;
219 }
220 
222  .function = ip4_hop_by_hop_node_fn,
223  .name = "ip4-hop-by-hop",
224  .vector_size = sizeof (u32),
225  .format_trace = format_ip4_hop_by_hop_trace,
227 
229  .error_strings = ip4_hop_by_hop_error_strings,
230 
231  /* See ip/lookup.h */
232  .n_next_nodes = IP_LOOKUP_N_NEXT,
233  .next_nodes = IP4_LOOKUP_NEXT_NODES,
234 };
235 
237  .function = ip4_hop_by_hop_node_fn,
238  .name = "ip4-add-hop-by-hop",
239  .vector_size = sizeof (u32),
240  .format_trace = format_ip4_hop_by_hop_trace,
242 
244  .error_strings = ip4_hop_by_hop_error_strings,
245 
246  /* See ip/lookup.h */
247  .n_next_nodes = IP_LOOKUP_N_NEXT,
248  .next_nodes = IP4_LOOKUP_NEXT_NODES,
249 };
250 
252  .function = ip4_hop_by_hop_node_fn,
253  .name = "ip4-pop-hop-by-hop",
254  .vector_size = sizeof (u32),
255  .format_trace = format_ip4_hop_by_hop_trace,
257 
259  .error_strings = ip4_hop_by_hop_error_strings,
260 
261  /* See ip/lookup.h */
262  .n_next_nodes = IP_LOOKUP_N_NEXT,
263  .next_nodes = IP4_LOOKUP_NEXT_NODES,
264 };
265 
266 static clib_error_t *
268 {
270 
271  hm->vlib_main = vm;
272  hm->vnet_main = vnet_get_main();
273 
274  return 0;
275 }
276 
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Definition: main.c:459
ip_lookup_next_t
Definition: lookup.h:49
#define CLIB_UNUSED(x)
Definition: clib.h:79
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
vlib_main_t * vlib_main
ip_lookup_next_t lookup_next_index
Definition: lookup.h:163
static uword ip4_hop_by_hop_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vlib_node_registration_t ip4_add_hop_by_hop_node
(constructor) VLIB_REGISTER_NODE (ip4_add_hop_by_hop_node)
ip4_hop_by_hop_main_t ip4_hop_by_hop_main
struct _vlib_node_registration vlib_node_registration_t
ip_lookup_main_t lookup_main
Definition: ip4.h:129
vlib_node_registration_t ip4_pop_hop_by_hop_node
(constructor) VLIB_REGISTER_NODE (ip4_pop_hop_by_hop_node)
always_inline void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:184
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:77
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:109
ip6_hop_by_hop_main_t * hm
ip4_hop_by_hop_error_t
#define IP4_LOOKUP_NEXT_NODES
Definition: lookup.h:93
static u8 * format_ip4_hop_by_hop_trace(u8 *s, va_list *args)
vnet_main_t * vnet_main
always_inline void * vlib_frame_vector_args(vlib_frame_t *f)
Definition: node_funcs.h:202
static char * ip4_hop_by_hop_error_strings[]
#define PREDICT_FALSE(x)
Definition: clib.h:97
always_inline void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:970
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Definition: buffer_node.h:43
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Definition: buffer_node.h:83
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:265
static clib_error_t * ip4_hop_by_hop_init(vlib_main_t *vm)
u16 n_vectors
Definition: node.h:307
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
#define foreach_ip4_hop_by_hop_error
#define ARRAY_LEN(x)
Definition: clib.h:59
u16 cached_next_index
Definition: node.h:422
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
#define vnet_buffer(b)
Definition: buffer.h:300
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:225
vlib_node_registration_t ip4_hop_by_hop_node
(constructor) VLIB_REGISTER_NODE (ip4_hop_by_hop_node)
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:91
always_inline ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:423
u64 uword
Definition: types.h:112
Definition: defs.h:46
unsigned char u8
Definition: types.h:56
always_inline 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
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:162
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:140
ip4_main_t ip4_main
Definition: ip4_forward.c:1394
u8 data[0]
Packet data.
Definition: buffer.h:150
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:84
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
Definition: defs.h:45