FD.io VPP  v21.10.1-2-g0a485f517
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 #include <vnet/pg/pg.h>
45 
46 typedef struct
47 {
48  u8 packet_data[64];
50 
51 static u8 *
52 format_ip6_input_trace (u8 * s, va_list * va)
53 {
54  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
55  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
56  ip6_input_trace_t *t = va_arg (*va, ip6_input_trace_t *);
57 
58  s = format (s, "%U",
59  format_ip6_header, t->packet_data, sizeof (t->packet_data));
60 
61  return s;
62 }
63 
64 /* Validate IP v6 packets and pass them either to forwarding code
65  or drop exception packets. */
68 {
69  vnet_main_t *vnm = vnet_get_main ();
71  ip_lookup_main_t *lm = &im->lookup_main;
72  u32 n_left_from, *from, *to_next;
74  vlib_node_runtime_t *error_node =
78 
80  n_left_from = frame->n_vectors;
81  next_index = node->cached_next_index;
82 
83  if (node->flags & VLIB_NODE_FLAG_TRACE)
85  /* stride */ 1,
86  sizeof (ip6_input_trace_t));
87 
90 
91  while (n_left_from > 0)
92  {
93  u32 n_left_to_next;
94 
95  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
96 
97  while (n_left_from >= 4 && n_left_to_next >= 2)
98  {
99  vlib_buffer_t *p0, *p1;
100  ip6_header_t *ip0, *ip1;
101  u32 pi0, sw_if_index0, next0 = 0;
102  u32 pi1, sw_if_index1, next1 = 0;
103  u8 arc0, arc1;
104 
105  /* Prefetch next iteration. */
106  {
107  vlib_buffer_t *p2, *p3;
108 
109  p2 = vlib_get_buffer (vm, from[2]);
110  p3 = vlib_get_buffer (vm, from[3]);
111 
112  vlib_prefetch_buffer_header (p2, LOAD);
113  vlib_prefetch_buffer_header (p3, LOAD);
114 
115  CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD);
116  CLIB_PREFETCH (p3->data, sizeof (ip1[0]), LOAD);
117  }
118 
119  pi0 = from[0];
120  pi1 = from[1];
121 
122  to_next[0] = pi0;
123  to_next[1] = pi1;
124  from += 2;
125  to_next += 2;
126  n_left_from -= 2;
127  n_left_to_next -= 2;
128 
129  p0 = vlib_get_buffer (vm, pi0);
130  p1 = vlib_get_buffer (vm, pi1);
131 
132  ip0 = vlib_buffer_get_current (p0);
133  ip1 = vlib_buffer_get_current (p1);
134 
135  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
136  sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX];
137 
139  {
140  arc0 = lm->mcast_feature_arc_index;
142  }
143  else
144  {
145  arc0 = lm->ucast_feature_arc_index;
146  next0 = IP6_INPUT_NEXT_LOOKUP;
147  }
148 
150  {
151  arc1 = lm->mcast_feature_arc_index;
153  }
154  else
155  {
156  arc1 = lm->ucast_feature_arc_index;
157  next1 = IP6_INPUT_NEXT_LOOKUP;
158  }
159 
160  vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
161  vnet_buffer (p1)->ip.adj_index[VLIB_RX] = ~0;
162 
163  vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
164  vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1);
165 
166  vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
167  vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1);
168  ip6_input_check_x2 (vm, error_node,
169  p0, p1, ip0, ip1, &next0, &next1);
170 
172  to_next, n_left_to_next,
173  pi0, pi1, next0, next1);
174  }
175 
176  while (n_left_from > 0 && n_left_to_next > 0)
177  {
178  vlib_buffer_t *p0;
179  ip6_header_t *ip0;
180  u32 pi0, sw_if_index0, next0 = 0;
181  u8 arc0;
182 
183  pi0 = from[0];
184  to_next[0] = pi0;
185  from += 1;
186  to_next += 1;
187  n_left_from -= 1;
188  n_left_to_next -= 1;
189 
190  p0 = vlib_get_buffer (vm, pi0);
191  ip0 = vlib_buffer_get_current (p0);
192 
193  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
195  {
196  arc0 = lm->mcast_feature_arc_index;
198  }
199  else
200  {
201  arc0 = lm->ucast_feature_arc_index;
202  next0 = IP6_INPUT_NEXT_LOOKUP;
203  }
204 
205  vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
206  vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
207 
208  vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
209  ip6_input_check_x1 (vm, error_node, p0, ip0, &next0);
210 
212  to_next, n_left_to_next,
213  pi0, next0);
214  }
215 
216  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
217  }
218 
219  return frame->n_vectors;
220 }
221 
222 #ifndef CLIB_MARCH_VARIANT
223 char *ip6_error_strings[] = {
224 #define _(sym,string) string,
226 #undef _
227 };
228 #endif /* CLIB_MARCH_VARIANT */
229 
230 /* *INDENT-OFF* */
232  .name = "ip6-input",
233  .vector_size = sizeof (u32),
234 
235  .n_errors = IP6_N_ERROR,
236  .error_strings = ip6_error_strings,
237 
238  .n_next_nodes = IP6_INPUT_N_NEXT,
239  .next_nodes = {
240  [IP6_INPUT_NEXT_DROP] = "error-drop",
241  [IP6_INPUT_NEXT_LOOKUP] = "ip6-lookup",
242  [IP6_INPUT_NEXT_ICMP_ERROR] = "ip6-icmp-error",
243  [IP6_INPUT_NEXT_LOOKUP_MULTICAST] = "ip6-mfib-forward-lookup",
244  },
245 
246  .format_buffer = format_ip6_header,
247  .format_trace = format_ip6_input_trace,
248 };
249 /* *INDENT-ON* */
250 
251 static clib_error_t *
253 {
254  ethernet_register_input_type (vm, ETHERNET_TYPE_IP6, ip6_input_node.index);
255  ppp_register_input_protocol (vm, PPP_PROTOCOL_ip6, ip6_input_node.index);
256  hdlc_register_input_protocol (vm, HDLC_PROTOCOL_ip6, ip6_input_node.index);
257 
258  {
259  pg_node_t *pn;
260  pn = pg_get_node (ip6_input_node.index);
262  }
263 
264  /* Set flow hash to something non-zero. */
265  ip6_main.flow_hash_seed = 0xdeadbeef;
266 
267  /* Default hop limit for packets we generate. */
268  ip6_main.host_config.ttl = 64;
269 
270 
271  uword *u = hash_get (ip_main.protocol_info_by_name, "IPV6_FRAGMENTATION");
272  if (u)
273  {
274  ip_protocol_info_t *info =
276  ASSERT (NULL == info->format_header);
278  }
279  return /* no error */ 0;
280 }
281 
283 
284 /*
285  * fd.io coding-style-patch-verification: ON
286  *
287  * Local Variables:
288  * eval: (c-set-style "gnu")
289  * End:
290  */
im
vnet_interface_main_t * im
Definition: interface_output.c:415
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:495
vlib_prefetch_buffer_header
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
ip_lookup_main_t::ucast_feature_arc_index
u8 ucast_feature_arc_index
Definition: lookup.h:144
VNET_INTERFACE_COUNTER_IP6
@ VNET_INTERFACE_COUNTER_IP6
Definition: interface.h:907
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
pg.h
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
format_ip6_header
format_function_t format_ip6_header
Definition: format.h:95
vlib_trace_frame_buffers_only
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:48
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
unformat_pg_ip6_header
unformat_function_t unformat_pg_ip6_header
Definition: format.h:97
ip_main
ip_main_t ip_main
Definition: ip_init.c:42
ip_protocol_info_t::format_header
format_function_t * format_header
Definition: ip.h:79
hdlc.h
ip6_main_t::flow_hash_seed
u32 flow_hash_seed
Definition: ip6.h:154
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
ip_main_t::protocol_infos
ip_protocol_info_t * protocol_infos
Definition: ip.h:110
ip6_input.h
vnet_interface_main_t::sw_if_counters
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:1023
ip6_error_strings
char * ip6_error_strings[]
Definition: ip6_input.c:223
vlib_frame_t
Definition: node.h:372
hdlc_register_input_protocol
void hdlc_register_input_protocol(vlib_main_t *vm, hdlc_protocol_t protocol, u32 node_index)
Definition: node.c:358
ethernet.h
pg_node_t
Definition: pg.h:332
ip6_main_t::host_config
struct ip6_main_t::@389 host_config
CLIB_PREFETCH
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:76
vlib_increment_simple_counter
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:74
IP6_INPUT_NEXT_ICMP_ERROR
@ IP6_INPUT_NEXT_ICMP_ERROR
Definition: ip6_input.h:53
IP6_INPUT_NEXT_DROP
@ IP6_INPUT_NEXT_DROP
Definition: ip6_input.h:50
ip6_address_is_multicast
static uword ip6_address_is_multicast(const ip6_address_t *a)
Definition: ip6_packet.h:121
ip_main_t::protocol_info_by_name
uword * protocol_info_by_name
Definition: ip.h:117
VLIB_NODE_FN
#define VLIB_NODE_FN(node)
Definition: node.h:202
pg_node_t::unformat_edit
unformat_function_t * unformat_edit
Definition: pg.h:335
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
vec_elt_at_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Definition: vec_bootstrap.h:203
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
ip_lookup_main_t::mcast_feature_arc_index
u8 mcast_feature_arc_index
Feature arc indices.
Definition: lookup.h:143
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
hash_get
#define hash_get(h, key)
Definition: hash.h:249
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
ip6_input_trace_t::packet_data
u8 packet_data[64]
Definition: ip6_input.c:48
uword
u64 uword
Definition: types.h:112
pg_get_node
static pg_node_t * pg_get_node(uword node_index)
Definition: pg.h:391
vlib_main_t::thread_index
u32 thread_index
Definition: main.h:215
ip6_header_t::dst_address
ip6_address_t dst_address
Definition: ip6_packet.h:310
format_ip6_input_trace
static u8 * format_ip6_input_trace(u8 *s, va_list *va)
Definition: ip6_input.c:52
cm
vnet_feature_config_main_t * cm
Definition: nat44_ei_hairpinning.c:594
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
ip6_input_trace_t
Definition: ip6_input.c:46
ip6_main
ip6_main_t ip6_main
Definition: ip6_forward.c:2785
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
ip6_input_check_x1
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
ip6_input_node
vlib_node_registration_t ip6_input_node
(constructor) VLIB_REGISTER_NODE (ip6_input_node)
Definition: ip6_input.c:231
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
ip_protocol_info_t
Definition: ip.h:70
format_ip6_frag_hdr
format_function_t format_ip6_frag_hdr
Definition: format.h:96
IP6_INPUT_NEXT_LOOKUP
@ IP6_INPUT_NEXT_LOOKUP
Definition: ip6_input.h:51
vlib_node_get_runtime
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:116
ip6_header_t
Definition: ip6_packet.h:294
ip6_input_check_x2
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
ip6_main_t
Definition: ip6.h:110
ip_lookup_main_t
Definition: lookup.h:121
vlib_main_t
Definition: main.h:102
vlib_node_t
Definition: node.h:247
vlib_simple_counter_main_t
A collection of simple counters.
Definition: counter.h:57
ppp.h
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
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
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
vlib_buffer_t::data
u8 data[]
Packet data.
Definition: buffer.h:204
ppp_register_input_protocol
void ppp_register_input_protocol(vlib_main_t *vm, ppp_protocol_t protocol, u32 node_index)
Definition: node.c:345
vnet_feature_arc_start
static_always_inline void vnet_feature_arc_start(u8 arc, u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:302
vlib_validate_buffer_enqueue_x2
#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
ip6_main_t::ttl
u8 ttl
Definition: ip6.h:159
vlib_node_runtime_t
Definition: node.h:454
IP6_N_ERROR
@ IP6_N_ERROR
Definition: ip6_error.h:95
ip6_init
static clib_error_t * ip6_init(vlib_main_t *vm)
Definition: ip6_input.c:252
from
from
Definition: nat44_ei_hairpinning.c:415
IP6_INPUT_N_NEXT
@ IP6_INPUT_N_NEXT
Definition: ip6_input.h:54
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
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
ethernet_register_input_type
void ethernet_register_input_type(vlib_main_t *vm, ethernet_type_t type, u32 node_index)
Definition: node.c:2274
vnet_main_t::interface_main
vnet_interface_main_t interface_main
Definition: vnet.h:81
ip6_input_next_t
ip6_input_next_t
Definition: ip6_input.h:48
foreach_ip6_error
#define foreach_ip6_error
Definition: ip6_error.h:43
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
IP6_INPUT_NEXT_LOOKUP_MULTICAST
@ IP6_INPUT_NEXT_LOOKUP_MULTICAST
Definition: ip6_input.h:52