FD.io VPP  v18.04-17-g3a0d853
Vector Packet Processing
ip4_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/ip4_input.c: IP v4 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/ip4_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_ip4_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  ip4_input_trace_t *t = va_arg (*va, ip4_input_trace_t *);
56 
57  s = format (s, "%U",
58  format_ip4_header, t->packet_data, sizeof (t->packet_data));
59 
60  return s;
61 }
62 
63 /* Validate IP v4 packets and pass them either to forwarding code
64  or drop/punt exception packets. */
67  vlib_node_runtime_t * node,
68  vlib_frame_t * frame, int verify_checksum)
69 {
70  ip4_main_t *im = &ip4_main;
71  vnet_main_t *vnm = vnet_get_main ();
72  ip_lookup_main_t *lm = &im->lookup_main;
73  u32 n_left_from, *from, *to_next;
74  ip4_input_next_t next_index;
75  vlib_node_runtime_t *error_node =
78  u32 thread_index = vlib_get_thread_index ();
79 
80  from = vlib_frame_vector_args (frame);
81  n_left_from = frame->n_vectors;
82  next_index = node->cached_next_index;
83 
84  if (node->flags & VLIB_NODE_FLAG_TRACE)
85  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
86  /* stride */ 1,
87  sizeof (ip4_input_trace_t));
88 
91 
92  while (n_left_from > 0)
93  {
94  u32 n_left_to_next;
95 
96  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
97 
98  while (n_left_from >= 4 && n_left_to_next >= 2)
99  {
100  vlib_buffer_t *p0, *p1;
101  ip4_header_t *ip0, *ip1;
102  u32 sw_if_index0, pi0, next0;
103  u32 sw_if_index1, pi1, next1;
104  u8 arc0, arc1;
105 
106  /* Prefetch next iteration. */
107  {
108  vlib_buffer_t *p2, *p3;
109 
110  p2 = vlib_get_buffer (vm, from[2]);
111  p3 = vlib_get_buffer (vm, from[3]);
112 
113  vlib_prefetch_buffer_header (p2, LOAD);
114  vlib_prefetch_buffer_header (p3, LOAD);
115 
116  CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD);
117  CLIB_PREFETCH (p3->data, sizeof (ip1[0]), LOAD);
118  }
119 
120  to_next[0] = pi0 = from[0];
121  to_next[1] = pi1 = from[1];
122  from += 2;
123  to_next += 2;
124  n_left_from -= 2;
125  n_left_to_next -= 2;
126 
127  p0 = vlib_get_buffer (vm, pi0);
128  p1 = vlib_get_buffer (vm, pi1);
129 
130  ip0 = vlib_buffer_get_current (p0);
131  ip1 = vlib_buffer_get_current (p1);
132 
133  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
134  sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX];
135 
137  {
138  arc0 = lm->mcast_feature_arc_index;
140  }
141  else
142  {
143  arc0 = lm->ucast_feature_arc_index;
144  next0 = IP4_INPUT_NEXT_LOOKUP;
145  }
146 
148  {
149  arc1 = lm->mcast_feature_arc_index;
151  }
152  else
153  {
154  arc1 = lm->ucast_feature_arc_index;
155  next1 = IP4_INPUT_NEXT_LOOKUP;
156  }
157 
158  vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
159  vnet_buffer (p1)->ip.adj_index[VLIB_RX] = ~0;
160 
161  vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
162  vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1);
163 
164  vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
165  vlib_increment_simple_counter (cm, thread_index, sw_if_index1, 1);
166  ip4_input_check_x2 (vm, error_node,
167  p0, p1, ip0, ip1,
168  &next0, &next1, verify_checksum);
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  while (n_left_from > 0 && n_left_to_next > 0)
175  {
176  vlib_buffer_t *p0;
177  ip4_header_t *ip0;
178  u32 sw_if_index0, pi0, next0;
179  u8 arc0;
180 
181  pi0 = from[0];
182  to_next[0] = pi0;
183  from += 1;
184  to_next += 1;
185  n_left_from -= 1;
186  n_left_to_next -= 1;
187 
188  p0 = vlib_get_buffer (vm, pi0);
189  ip0 = vlib_buffer_get_current (p0);
190 
191  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
192 
194  {
195  arc0 = lm->mcast_feature_arc_index;
197  }
198  else
199  {
200  arc0 = lm->ucast_feature_arc_index;
201  next0 = IP4_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  ip4_input_check_x1 (vm, error_node, p0, ip0, &next0,
209  verify_checksum);
210 
211  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
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 /** \brief IPv4 input node.
223  @node ip4-input
224 
225  This is the IPv4 input node: validates ip4 header checksums,
226  verifies ip header lengths, discards pkts with expired TTLs,
227  and sends pkts to the set of ip feature nodes configured on
228  the rx interface.
229 
230  @param vm vlib_main_t corresponding to the current thread
231  @param node vlib_node_runtime_t
232  @param frame vlib_frame_t whose contents should be dispatched
233 
234  @par Graph mechanics: buffer metadata, next index usage
235 
236  @em Uses:
237  - vnet_feature_config_main_t cm corresponding to each pkt's dst address unicast /
238  multicast status.
239  - <code>b->current_config_index</code> corresponding to each pkt's
240  rx sw_if_index.
241  - This sets the per-packet graph trajectory, ensuring that
242  each packet visits the per-interface features in order.
243 
244  - <code>vnet_buffer(b)->sw_if_index[VLIB_RX]</code>
245  - Indicates the @c sw_if_index value of the interface that the
246  packet was received on.
247 
248  @em Sets:
249  - <code>vnet_buffer(b)->ip.adj_index[VLIB_TX]</code>
250  - The lookup result adjacency index.
251 
252  <em>Next Indices:</em>
253  - Dispatches pkts to the (first) feature node:
254  <code> vnet_get_config_data (... &next0 ...); </code>
255  or @c error-drop
256 */
257 static uword
259 {
260  return ip4_input_inline (vm, node, frame, /* verify_checksum */ 1);
261 }
262 
263 static uword
265  vlib_node_runtime_t * node, vlib_frame_t * frame)
266 {
267  return ip4_input_inline (vm, node, frame, /* verify_checksum */ 0);
268 }
269 
270 char *ip4_error_strings[] = {
271 #define _(sym,string) string,
273 #undef _
274 };
275 
276 /* *INDENT-OFF* */
278  .function = ip4_input,
279  .name = "ip4-input",
280  .vector_size = sizeof (u32),
281 
282  .n_errors = IP4_N_ERROR,
283  .error_strings = ip4_error_strings,
284 
285  .n_next_nodes = IP4_INPUT_N_NEXT,
286  .next_nodes = {
287  [IP4_INPUT_NEXT_DROP] = "error-drop",
288  [IP4_INPUT_NEXT_PUNT] = "error-punt",
289  [IP4_INPUT_NEXT_LOOKUP] = "ip4-lookup",
290  [IP4_INPUT_NEXT_LOOKUP_MULTICAST] = "ip4-mfib-forward-lookup",
291  [IP4_INPUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
292  [IP4_INPUT_NEXT_REASSEMBLY] = "ip4-reassembly",
293  },
294 
295  .format_buffer = format_ip4_header,
296  .format_trace = format_ip4_input_trace,
297 };
298 /* *INDENT-ON* */
299 
301 
302 /* *INDENT-OFF* */
304  .function = ip4_input_no_checksum,
305  .name = "ip4-input-no-checksum",
306  .vector_size = sizeof (u32),
307 
308  .n_next_nodes = IP4_INPUT_N_NEXT,
309  .next_nodes = {
310  [IP4_INPUT_NEXT_DROP] = "error-drop",
311  [IP4_INPUT_NEXT_PUNT] = "error-punt",
312  [IP4_INPUT_NEXT_LOOKUP] = "ip4-lookup",
313  [IP4_INPUT_NEXT_LOOKUP_MULTICAST] = "ip4-mfib-forward-lookup",
314  [IP4_INPUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
315  [IP4_INPUT_NEXT_REASSEMBLY] = "ip4-reassembly",
316  },
317 
318  .format_buffer = format_ip4_header,
319  .format_trace = format_ip4_input_trace,
320 };
321 /* *INDENT-ON* */
322 
325 
326 static clib_error_t *
328 {
329  clib_error_t *error;
330 
331  ethernet_register_input_type (vm, ETHERNET_TYPE_IP4, ip4_input_node.index);
332  ppp_register_input_protocol (vm, PPP_PROTOCOL_ip4, ip4_input_node.index);
333  hdlc_register_input_protocol (vm, HDLC_PROTOCOL_ip4, ip4_input_node.index);
334 
335  {
336  pg_node_t *pn;
337  pn = pg_get_node (ip4_input_node.index);
341  }
342 
343  if ((error = vlib_call_init_function (vm, ip4_cli_init)))
344  return error;
345 
347  return error;
348 
349  if ((error = vlib_call_init_function
351  return error;
352 
353  /* Set flow hash to something non-zero. */
354  ip4_main.flow_hash_seed = 0xdeadbeef;
355 
356  /* Default TTL for packets we generate. */
357  ip4_main.host_config.ttl = 64;
358 
359  return error;
360 }
361 
363 
364 /*
365  * fd.io coding-style-patch-verification: ON
366  *
367  * Local Variables:
368  * eval: (c-set-style "gnu")
369  * End:
370  */
#define CLIB_UNUSED(x)
Definition: clib.h:79
static uword ip4_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
IPv4 input node.
Definition: ip4_input.c:258
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
vnet_interface_main_t interface_main
Definition: vnet.h:56
format_function_t format_ip4_header
Definition: format.h:86
unformat_function_t unformat_pg_ip4_header
Definition: format.h:91
ip_lookup_main_t lookup_main
Definition: ip4.h:97
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
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
static clib_error_t * ip4_cli_init(vlib_main_t *vm)
Definition: ip46_cli.c:307
u8 mcast_feature_arc_index
Feature arc indices.
Definition: lookup.h:135
static pg_node_t * pg_get_node(uword node_index)
Definition: pg.h:350
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static clib_error_t * ip4_init(vlib_main_t *vm)
Definition: ip4_input.c:327
#define always_inline
Definition: clib.h:92
ip4_address_t dst_address
Definition: ip4_packet.h:164
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:191
char * ip4_error_strings[]
Definition: ip4_input.c:270
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static void ip4_input_check_x1(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, ip4_header_t *ip0, u32 *next0, int verify_checksum)
Definition: ip4_input.h:156
A collection of simple counters.
Definition: counter.h:58
#define vlib_call_init_function(vm, x)
Definition: init.h:162
static vlib_node_registration_t ip4_input_no_checksum_node
(constructor) VLIB_REGISTER_NODE (ip4_input_no_checksum_node)
Definition: ip4_input.c:303
static u8 * format_ip4_input_trace(u8 *s, va_list *va)
Definition: ip4_input.c:51
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:209
static uword ip4_address_is_multicast(ip4_address_t *a)
Definition: ip4_packet.h:310
#define PREDICT_FALSE(x)
Definition: clib.h:105
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:717
#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: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
u8 packet_data[64]
Definition: ip4_input.c:47
#define foreach_ip4_error
Definition: ip4_error.h:43
static uword ip4_input_no_checksum(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_input.c:264
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u16 n_vectors
Definition: node.h:344
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:221
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:74
vlib_main_t * vm
Definition: buffer.c:294
clib_error_t * ip4_source_check_init(vlib_main_t *vm)
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:89
unformat_function_t * unformat_edit
Definition: pg.h:307
void hdlc_register_input_protocol(vlib_main_t *vm, hdlc_protocol_t protocol, u32 node_index)
Definition: node.c:351
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:454
static uword ip4_input_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int verify_checksum)
Definition: ip4_input.c:66
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:456
unsigned int u32
Definition: types.h:88
IPv4 main type.
Definition: ip4.h:95
ip4_input_next_t
Definition: ip4_input.h:48
void ethernet_register_input_type(vlib_main_t *vm, ethernet_type_t type, u32 node_index)
Definition: node.c:1333
u64 uword
Definition: types.h:112
u8 ucast_feature_arc_index
Definition: lookup.h:136
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:45
static void ip4_input_check_x2(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, vlib_buffer_t *p1, ip4_header_t *ip0, ip4_header_t *ip1, u32 *next0, u32 *next1, int verify_checksum)
Definition: ip4_input.h:60
clib_error_t * ip4_source_and_port_range_check_init(vlib_main_t *vm)
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
#define vnet_buffer(b)
Definition: buffer.h:372
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:818
u8 data[0]
Packet data.
Definition: buffer.h:179
vlib_node_registration_t ip4_input_node
(constructor) VLIB_REGISTER_NODE (ip4_input_node)
Definition: ip4_input.c:277
struct ip4_main_t::@197 host_config
Template information for VPP generated packets.
void ppp_register_input_protocol(vlib_main_t *vm, ppp_protocol_t protocol, u32 node_index)
Definition: node.c:338
u16 flags
Copy of main node flags.
Definition: node.h:450
u32 flow_hash_seed
Seed for Jenkins hash used to compute ip4 flow hash.
Definition: ip4.h:138
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
u8 ttl
TTL to use for host generated packets.
Definition: ip4.h:144
VLIB_NODE_FUNCTION_MULTIARCH(ip4_input_node, ip4_input)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
Definition: pg.h:304
Definition: defs.h:46
static_always_inline void vnet_feature_arc_start(u8 arc, u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:201