FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
ip6_input.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  * ip/ip6_input.c: IP v6 input node
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vnet/ip/ip6_input.h>
41 #include <vnet/ethernet/ethernet.h>
42 #include <vnet/ppp/ppp.h>
43 #include <vnet/hdlc/hdlc.h>
44 
45 typedef struct
46 {
47  u8 packet_data[64];
49 
50 static u8 *
51 format_ip6_input_trace (u8 * s, va_list * va)
52 {
53  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
54  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
55  ip6_input_trace_t *t = va_arg (*va, ip6_input_trace_t *);
56 
57  s = format (s, "%U",
58  format_ip6_header, t->packet_data, sizeof (t->packet_data));
59 
60  return s;
61 }
62 
63 /* Validate IP v6 packets and pass them either to forwarding code
64  or drop exception packets. */
67 {
68  vnet_main_t *vnm = vnet_get_main ();
69  ip6_main_t *im = &ip6_main;
70  ip_lookup_main_t *lm = &im->lookup_main;
71  u32 n_left_from, *from, *to_next;
72  ip6_input_next_t next_index;
73  vlib_node_runtime_t *error_node =
76  u32 thread_index = vm->thread_index;
77 
79  n_left_from = frame->n_vectors;
80  next_index = node->cached_next_index;
81 
82  if (node->flags & VLIB_NODE_FLAG_TRACE)
83  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
84  /* stride */ 1,
85  sizeof (ip6_input_trace_t));
86 
89 
90  while (n_left_from > 0)
91  {
92  u32 n_left_to_next;
93 
94  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
95 
96  while (n_left_from >= 4 && n_left_to_next >= 2)
97  {
98  vlib_buffer_t *p0, *p1;
99  ip6_header_t *ip0, *ip1;
100  u32 pi0, sw_if_index0, next0 = 0;
101  u32 pi1, sw_if_index1, next1 = 0;
102  u8 arc0, arc1;
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 
114  CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD);
115  CLIB_PREFETCH (p3->data, sizeof (ip1[0]), LOAD);
116  }
117 
118  pi0 = from[0];
119  pi1 = from[1];
120 
121  to_next[0] = pi0;
122  to_next[1] = pi1;
123  from += 2;
124  to_next += 2;
125  n_left_from -= 2;
126  n_left_to_next -= 2;
127 
128  p0 = vlib_get_buffer (vm, pi0);
129  p1 = vlib_get_buffer (vm, pi1);
130 
131  ip0 = vlib_buffer_get_current (p0);
132  ip1 = vlib_buffer_get_current (p1);
133 
134  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
135  sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX];
136 
138  {
139  arc0 = lm->mcast_feature_arc_index;
141  }
142  else
143  {
144  arc0 = lm->ucast_feature_arc_index;
145  next0 = IP6_INPUT_NEXT_LOOKUP;
146  }
147 
149  {
150  arc1 = lm->mcast_feature_arc_index;
152  }
153  else
154  {
155  arc1 = lm->ucast_feature_arc_index;
156  next1 = IP6_INPUT_NEXT_LOOKUP;
157  }
158 
159  vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
160  vnet_buffer (p1)->ip.adj_index[VLIB_RX] = ~0;
161 
162  vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
163  vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1);
164 
165  vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
166  vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1);
167  ip6_input_check_x2 (vm, error_node,
168  p0, p1, ip0, ip1, &next0, &next1);
169 
170  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
171  to_next, n_left_to_next,
172  pi0, pi1, next0, next1);
173  }
174 
175  while (n_left_from > 0 && n_left_to_next > 0)
176  {
177  vlib_buffer_t *p0;
178  ip6_header_t *ip0;
179  u32 pi0, sw_if_index0, next0 = 0;
180  u8 arc0;
181 
182  pi0 = from[0];
183  to_next[0] = pi0;
184  from += 1;
185  to_next += 1;
186  n_left_from -= 1;
187  n_left_to_next -= 1;
188 
189  p0 = vlib_get_buffer (vm, pi0);
190  ip0 = vlib_buffer_get_current (p0);
191 
192  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
194  {
195  arc0 = lm->mcast_feature_arc_index;
197  }
198  else
199  {
200  arc0 = lm->ucast_feature_arc_index;
201  next0 = IP6_INPUT_NEXT_LOOKUP;
202  }
203 
204  vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
205  vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
206 
207  vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
208  ip6_input_check_x1 (vm, error_node, p0, ip0, &next0);
209 
210  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
211  to_next, n_left_to_next,
212  pi0, next0);
213  }
214 
215  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
216  }
217 
218  return frame->n_vectors;
219 }
220 
221 #ifndef CLIB_MARCH_VARIANT
222 char *ip6_error_strings[] = {
223 #define _(sym,string) string,
225 #undef _
226 };
227 #endif /* CLIB_MARCH_VARIANT */
228 
229 /* *INDENT-OFF* */
231  .name = "ip6-input",
232  .vector_size = sizeof (u32),
233 
234  .n_errors = IP6_N_ERROR,
235  .error_strings = ip6_error_strings,
236 
237  .n_next_nodes = IP6_INPUT_N_NEXT,
238  .next_nodes = {
239  [IP6_INPUT_NEXT_DROP] = "error-drop",
240  [IP6_INPUT_NEXT_LOOKUP] = "ip6-lookup",
241  [IP6_INPUT_NEXT_ICMP_ERROR] = "ip6-icmp-error",
242  [IP6_INPUT_NEXT_LOOKUP_MULTICAST] = "ip6-mfib-forward-lookup",
243  },
244 
245  .format_buffer = format_ip6_header,
246  .format_trace = format_ip6_input_trace,
247 };
248 /* *INDENT-ON* */
249 
250 static clib_error_t *
252 {
253  ethernet_register_input_type (vm, ETHERNET_TYPE_IP6, ip6_input_node.index);
254  ppp_register_input_protocol (vm, PPP_PROTOCOL_ip6, ip6_input_node.index);
255  hdlc_register_input_protocol (vm, HDLC_PROTOCOL_ip6, ip6_input_node.index);
256 
257  {
258  pg_node_t *pn;
259  pn = pg_get_node (ip6_input_node.index);
261  }
262 
263  /* Set flow hash to something non-zero. */
264  ip6_main.flow_hash_seed = 0xdeadbeef;
265 
266  /* Default hop limit for packets we generate. */
267  ip6_main.host_config.ttl = 64;
268 
269 
270  uword *u = hash_get (ip_main.protocol_info_by_name, "IPV6_FRAGMENTATION");
271  if (u)
272  {
273  ip_protocol_info_t *info =
275  ASSERT (NULL == info->format_header);
277  }
278  return /* no error */ 0;
279 }
280 
282 
283 static clib_error_t *
285 {
286  ip6_main_t *im = &ip6_main;
288 
289  throttle_init (&im->nd_throttle, tm->n_vlib_mains, 1e-3);
290 
291  return 0;
292 }
293 
295 
296 /*
297  * fd.io coding-style-patch-verification: ON
298  *
299  * Local Variables:
300  * eval: (c-set-style "gnu")
301  * End:
302  */
uword * protocol_info_by_name
Definition: ip.h:117
struct ip6_main_t::@371 host_config
#define CLIB_UNUSED(x)
Definition: clib.h:87
static u8 * format_ip6_input_trace(u8 *s, va_list *va)
Definition: ip6_input.c:51
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define VLIB_MAIN_LOOP_ENTER_FUNCTION(x)
Definition: init.h:176
vnet_interface_main_t interface_main
Definition: vnet.h:59
u32 flow_hash_seed
Definition: ip6.h:227
u8 ttl
Definition: ip6.h:232
u32 thread_index
Definition: main.h:249
void throttle_init(throttle_t *t, u32 n_threads, f64 time)
Definition: throttle.c:19
static clib_error_t * ip6_init(vlib_main_t *vm)
Definition: ip6_input.c:251
vlib_main_t * vm
Definition: in2out_ed.c:1582
format_function_t format_ip6_frag_hdr
Definition: format.h:96
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
Definition: counter.h:78
#define VLIB_NODE_FN(node)
Definition: node.h:202
u8 mcast_feature_arc_index
Feature arc indices.
Definition: lookup.h:167
unsigned char u8
Definition: types.h:56
static pg_node_t * pg_get_node(uword node_index)
Definition: pg.h:374
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
vlib_node_registration_t ip6_input_node
(constructor) VLIB_REGISTER_NODE (ip6_input_node)
Definition: ip6_input.c:230
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
unsigned int u32
Definition: types.h:88
A collection of simple counters.
Definition: counter.h:57
throttle_t nd_throttle
ND throttling.
Definition: ip6.h:241
vnet_crypto_main_t * cm
Definition: quic_crypto.c:53
#define hash_get(h, key)
Definition: hash.h:249
format_function_t * format_header
Definition: ip.h:79
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
#define PREDICT_FALSE(x)
Definition: clib.h:120
ip6_main_t ip6_main
Definition: ip6_forward.c:2781
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:880
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#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
#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:391
vlib_thread_main_t vlib_thread_main
Definition: threads.c:35
static void ip6_input_check_x2(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, vlib_buffer_t *p1, ip6_header_t *ip0, ip6_header_t *ip1, u32 *next0, u32 *next1)
Definition: ip6_input.h:58
ip_protocol_info_t * protocol_infos
Definition: ip.h:110
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
ip_main_t ip_main
Definition: ip_init.c:42
static void ip6_input_check_x1(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, ip6_header_t *ip0, u32 *next0)
Definition: ip6_input.h:122
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:115
u8 data[]
Packet data.
Definition: buffer.h:181
unformat_function_t * unformat_edit
Definition: pg.h:321
char * ip6_error_strings[]
Definition: ip6_input.c:222
void hdlc_register_input_protocol(vlib_main_t *vm, hdlc_protocol_t protocol, u32 node_index)
Definition: node.c:347
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:483
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1582
#define ASSERT(truth)
ip6_input_next_t
Definition: ip6_input.h:48
ip_lookup_main_t lookup_main
Definition: ip6.h:181
format_function_t format_ip6_header
Definition: format.h:95
static uword ip6_address_is_multicast(const ip6_address_t *a)
Definition: ip6_packet.h:121
void ethernet_register_input_type(vlib_main_t *vm, ethernet_type_t type, u32 node_index)
Definition: node.c:2276
u8 ucast_feature_arc_index
Definition: lookup.h:168
void ppp_register_input_protocol(vlib_main_t *vm, ppp_protocol_t protocol, u32 node_index)
Definition: node.c:334
void vlib_trace_frame_buffers_only(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, uword n_buffers, uword next_buffer_stride, uword n_buffer_data_bytes_in_trace)
Definition: trace.c:47
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1583
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static clib_error_t * ip6_main_loop_enter(vlib_main_t *vm)
Definition: ip6_input.c:284
unformat_function_t unformat_pg_ip6_header
Definition: format.h:97
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
#define foreach_ip6_error
Definition: ip6_error.h:43
#define vnet_buffer(b)
Definition: buffer.h:417
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:301
u8 packet_data[64]
Definition: ip6_input.c:47
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
Definition: pg.h:318
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:310
static_always_inline void vnet_feature_arc_start(u8 arc, u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:302