FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
ip4_forward.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-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  * ip/ip4_forward.h: IP v4 forwarding
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 #ifndef __included_ip4_forward_h__
41 #define __included_ip4_forward_h__
42 
43 #include <vppinfra/cache.h>
44 #include <vnet/fib/ip4_fib.h>
46 #include <vnet/ip/ip4_inlines.h>
47 
48 /**
49  * @file
50  * @brief IPv4 Forwarding.
51  *
52  * This file contains the source code for IPv4 forwarding.
53  */
54 
58 {
61  u32 n_left, *from;
64  vlib_buffer_t **b = bufs;
66 
68  n_left = frame->n_vectors;
69  next = nexts;
71 
72 #if (CLIB_N_PREFETCHES >= 8)
73  while (n_left >= 4)
74  {
75  ip4_header_t *ip0, *ip1, *ip2, *ip3;
76  const load_balance_t *lb0, *lb1, *lb2, *lb3;
77  ip4_address_t *dst_addr0, *dst_addr1, *dst_addr2, *dst_addr3;
78  u32 lb_index0, lb_index1, lb_index2, lb_index3;
79  flow_hash_config_t flow_hash_config0, flow_hash_config1;
80  flow_hash_config_t flow_hash_config2, flow_hash_config3;
81  u32 hash_c0, hash_c1, hash_c2, hash_c3;
82  const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3;
83 
84  /* Prefetch next iteration. */
85  if (n_left >= 8)
86  {
87  vlib_prefetch_buffer_header (b[4], LOAD);
88  vlib_prefetch_buffer_header (b[5], LOAD);
89  vlib_prefetch_buffer_header (b[6], LOAD);
90  vlib_prefetch_buffer_header (b[7], LOAD);
91 
92  CLIB_PREFETCH (b[4]->data, sizeof (ip0[0]), LOAD);
93  CLIB_PREFETCH (b[5]->data, sizeof (ip0[0]), LOAD);
94  CLIB_PREFETCH (b[6]->data, sizeof (ip0[0]), LOAD);
95  CLIB_PREFETCH (b[7]->data, sizeof (ip0[0]), LOAD);
96  }
97 
98  ip0 = vlib_buffer_get_current (b[0]);
99  ip1 = vlib_buffer_get_current (b[1]);
100  ip2 = vlib_buffer_get_current (b[2]);
101  ip3 = vlib_buffer_get_current (b[3]);
102 
103  dst_addr0 = &ip0->dst_address;
104  dst_addr1 = &ip1->dst_address;
105  dst_addr2 = &ip2->dst_address;
106  dst_addr3 = &ip3->dst_address;
107 
108  ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]);
109  ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[1]);
110  ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[2]);
111  ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[3]);
112 
114  vnet_buffer (b[0])->ip.fib_index, vnet_buffer (b[1])->ip.fib_index,
115  vnet_buffer (b[2])->ip.fib_index, vnet_buffer (b[3])->ip.fib_index,
116  dst_addr0, dst_addr1, dst_addr2, dst_addr3, &lb_index0, &lb_index1,
117  &lb_index2, &lb_index3);
118 
119  ASSERT (lb_index0 && lb_index1 && lb_index2 && lb_index3);
120  lb0 = load_balance_get (lb_index0);
121  lb1 = load_balance_get (lb_index1);
122  lb2 = load_balance_get (lb_index2);
123  lb3 = load_balance_get (lb_index3);
124 
125  ASSERT (lb0->lb_n_buckets > 0);
126  ASSERT (is_pow2 (lb0->lb_n_buckets));
127  ASSERT (lb1->lb_n_buckets > 0);
128  ASSERT (is_pow2 (lb1->lb_n_buckets));
129  ASSERT (lb2->lb_n_buckets > 0);
130  ASSERT (is_pow2 (lb2->lb_n_buckets));
131  ASSERT (lb3->lb_n_buckets > 0);
132  ASSERT (is_pow2 (lb3->lb_n_buckets));
133 
134  /* Use flow hash to compute multipath adjacency. */
135  hash_c0 = vnet_buffer (b[0])->ip.flow_hash = 0;
136  hash_c1 = vnet_buffer (b[1])->ip.flow_hash = 0;
137  hash_c2 = vnet_buffer (b[2])->ip.flow_hash = 0;
138  hash_c3 = vnet_buffer (b[3])->ip.flow_hash = 0;
139  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
140  {
141  flow_hash_config0 = lb0->lb_hash_config;
142  hash_c0 = vnet_buffer (b[0])->ip.flow_hash =
143  ip4_compute_flow_hash (ip0, flow_hash_config0);
144  dpo0 =
146  (hash_c0 &
147  (lb0->lb_n_buckets_minus_1)));
148  }
149  else
150  {
151  dpo0 = load_balance_get_bucket_i (lb0, 0);
152  }
153  if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
154  {
155  flow_hash_config1 = lb1->lb_hash_config;
156  hash_c1 = vnet_buffer (b[1])->ip.flow_hash =
157  ip4_compute_flow_hash (ip1, flow_hash_config1);
158  dpo1 =
160  (hash_c1 &
161  (lb1->lb_n_buckets_minus_1)));
162  }
163  else
164  {
165  dpo1 = load_balance_get_bucket_i (lb1, 0);
166  }
167  if (PREDICT_FALSE (lb2->lb_n_buckets > 1))
168  {
169  flow_hash_config2 = lb2->lb_hash_config;
170  hash_c2 = vnet_buffer (b[2])->ip.flow_hash =
171  ip4_compute_flow_hash (ip2, flow_hash_config2);
172  dpo2 =
174  (hash_c2 &
175  (lb2->lb_n_buckets_minus_1)));
176  }
177  else
178  {
179  dpo2 = load_balance_get_bucket_i (lb2, 0);
180  }
181  if (PREDICT_FALSE (lb3->lb_n_buckets > 1))
182  {
183  flow_hash_config3 = lb3->lb_hash_config;
184  hash_c3 = vnet_buffer (b[3])->ip.flow_hash =
185  ip4_compute_flow_hash (ip3, flow_hash_config3);
186  dpo3 =
188  (hash_c3 &
189  (lb3->lb_n_buckets_minus_1)));
190  }
191  else
192  {
193  dpo3 = load_balance_get_bucket_i (lb3, 0);
194  }
195 
196  next[0] = dpo0->dpoi_next_node;
197  vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
198  next[1] = dpo1->dpoi_next_node;
199  vnet_buffer (b[1])->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
200  next[2] = dpo2->dpoi_next_node;
201  vnet_buffer (b[2])->ip.adj_index[VLIB_TX] = dpo2->dpoi_index;
202  next[3] = dpo3->dpoi_next_node;
203  vnet_buffer (b[3])->ip.adj_index[VLIB_TX] = dpo3->dpoi_index;
204 
206  (cm, thread_index, lb_index0, 1,
209  (cm, thread_index, lb_index1, 1,
212  (cm, thread_index, lb_index2, 1,
215  (cm, thread_index, lb_index3, 1,
217 
218  b += 4;
219  next += 4;
220  n_left -= 4;
221  }
222 #elif (CLIB_N_PREFETCHES >= 4)
223  while (n_left >= 4)
224  {
225  ip4_header_t *ip0, *ip1;
226  const load_balance_t *lb0, *lb1;
227  ip4_address_t *dst_addr0, *dst_addr1;
228  u32 lb_index0, lb_index1;
229  flow_hash_config_t flow_hash_config0, flow_hash_config1;
230  u32 hash_c0, hash_c1;
231  const dpo_id_t *dpo0, *dpo1;
232 
233  /* Prefetch next iteration. */
234  {
235  vlib_prefetch_buffer_header (b[2], LOAD);
236  vlib_prefetch_buffer_header (b[3], LOAD);
237 
238  CLIB_PREFETCH (b[2]->data, sizeof (ip0[0]), LOAD);
239  CLIB_PREFETCH (b[3]->data, sizeof (ip0[0]), LOAD);
240  }
241 
242  ip0 = vlib_buffer_get_current (b[0]);
243  ip1 = vlib_buffer_get_current (b[1]);
244 
245  dst_addr0 = &ip0->dst_address;
246  dst_addr1 = &ip1->dst_address;
247 
248  ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]);
249  ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[1]);
250 
252  vnet_buffer (b[0])->ip.fib_index, vnet_buffer (b[1])->ip.fib_index,
253  dst_addr0, dst_addr1, &lb_index0, &lb_index1);
254 
255  ASSERT (lb_index0 && lb_index1);
256  lb0 = load_balance_get (lb_index0);
257  lb1 = load_balance_get (lb_index1);
258 
259  ASSERT (lb0->lb_n_buckets > 0);
260  ASSERT (is_pow2 (lb0->lb_n_buckets));
261  ASSERT (lb1->lb_n_buckets > 0);
262  ASSERT (is_pow2 (lb1->lb_n_buckets));
263 
264  /* Use flow hash to compute multipath adjacency. */
265  hash_c0 = vnet_buffer (b[0])->ip.flow_hash = 0;
266  hash_c1 = vnet_buffer (b[1])->ip.flow_hash = 0;
267  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
268  {
269  flow_hash_config0 = lb0->lb_hash_config;
270  hash_c0 = vnet_buffer (b[0])->ip.flow_hash =
271  ip4_compute_flow_hash (ip0, flow_hash_config0);
272  dpo0 =
274  (hash_c0 &
275  (lb0->lb_n_buckets_minus_1)));
276  }
277  else
278  {
279  dpo0 = load_balance_get_bucket_i (lb0, 0);
280  }
281  if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
282  {
283  flow_hash_config1 = lb1->lb_hash_config;
284  hash_c1 = vnet_buffer (b[1])->ip.flow_hash =
285  ip4_compute_flow_hash (ip1, flow_hash_config1);
286  dpo1 =
288  (hash_c1 &
289  (lb1->lb_n_buckets_minus_1)));
290  }
291  else
292  {
293  dpo1 = load_balance_get_bucket_i (lb1, 0);
294  }
295 
296  next[0] = dpo0->dpoi_next_node;
297  vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
298  next[1] = dpo1->dpoi_next_node;
299  vnet_buffer (b[1])->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
300 
302  (cm, thread_index, lb_index0, 1,
305  (cm, thread_index, lb_index1, 1,
307 
308  b += 2;
309  next += 2;
310  n_left -= 2;
311  }
312 #endif
313  while (n_left > 0)
314  {
315  ip4_header_t *ip0;
316  const load_balance_t *lb0;
317  ip4_address_t *dst_addr0;
318  u32 lbi0;
319  flow_hash_config_t flow_hash_config0;
320  const dpo_id_t *dpo0;
321  u32 hash_c0;
322 
323  ip0 = vlib_buffer_get_current (b[0]);
324  dst_addr0 = &ip0->dst_address;
325  ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]);
326 
327  lbi0 = ip4_fib_forwarding_lookup (vnet_buffer (b[0])->ip.fib_index,
328  dst_addr0);
329 
330  ASSERT (lbi0);
331  lb0 = load_balance_get (lbi0);
332 
333  ASSERT (lb0->lb_n_buckets > 0);
334  ASSERT (is_pow2 (lb0->lb_n_buckets));
335 
336  /* Use flow hash to compute multipath adjacency. */
337  hash_c0 = vnet_buffer (b[0])->ip.flow_hash = 0;
338  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
339  {
340  flow_hash_config0 = lb0->lb_hash_config;
341 
342  hash_c0 = vnet_buffer (b[0])->ip.flow_hash =
343  ip4_compute_flow_hash (ip0, flow_hash_config0);
344  dpo0 =
346  (hash_c0 &
347  (lb0->lb_n_buckets_minus_1)));
348  }
349  else
350  {
351  dpo0 = load_balance_get_bucket_i (lb0, 0);
352  }
353 
354  next[0] = dpo0->dpoi_next_node;
355  vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
356 
359  b[0]));
360 
361  b += 1;
362  next += 1;
363  n_left -= 1;
364  }
365 
367 
368  if (node->flags & VLIB_NODE_FLAG_TRACE)
370 
371  return frame->n_vectors;
372 }
373 
374 #endif /* __included_ip4_forward_h__ */
375 
376 /*
377  * fd.io coding-style-patch-verification: ON
378  *
379  * Local Variables:
380  * eval: (c-set-style "gnu")
381  * End:
382  */
dpo_id_t_::dpoi_next_node
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:186
im
vnet_interface_main_t * im
Definition: interface_output.c:415
load_balance_t_::lb_n_buckets
u16 lb_n_buckets
number of buckets in the load-balance.
Definition: load_balance.h:116
dpo_id_t_::dpoi_index
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:190
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:495
bufs
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
Definition: nat44_ei_out2in.c:717
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
ip4_forward_next_trace
void ip4_forward_next_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vlib_rx_or_tx_t which_adj_index)
Definition: ip4_forward.c:1239
ip4_main
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1104
load_balance_map.h
ip4_inlines.h
vlib_get_buffers
vlib_get_buffers(vm, from, b, n_left_from)
next
u16 * next
Definition: nat44_ei_out2in.c:718
VLIB_FRAME_SIZE
#define VLIB_FRAME_SIZE
Definition: node.h:368
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
load_balance_t_::lb_hash_config
flow_hash_config_t lb_hash_config
the hash config to use when selecting a bucket.
Definition: load_balance.h:161
u16
unsigned short u16
Definition: types.h:57
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
vlib_buffer_enqueue_to_next
vlib_buffer_enqueue_to_next(vm, node, from,(u16 *) nexts, frame->n_vectors)
vlib_frame_t
Definition: node.h:372
vlib_buffer_length_in_chain
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:433
ip4_header_t
Definition: ip4_packet.h:87
CLIB_PREFETCH
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:76
load_balance_main
load_balance_main_t load_balance_main
The one instance of load-balance main.
Definition: load_balance.c:59
load_balance_get_fwd_bucket
static const dpo_id_t * load_balance_get_fwd_bucket(const load_balance_t *lb, u16 bucket)
Definition: load_balance_map.h:94
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
ip4_lookup_inline
static uword ip4_lookup_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.h:56
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
flow_hash_config_t
enum flow_hash_config_t_ flow_hash_config_t
A flow hash configuration is a mask of the flow hash options.
uword
u64 uword
Definition: types.h:112
vlib_main_t::thread_index
u32 thread_index
Definition: main.h:215
ip4_fib_forwarding_lookup_x4
static_always_inline void ip4_fib_forwarding_lookup_x4(u32 fib_index0, u32 fib_index1, u32 fib_index2, u32 fib_index3, const ip4_address_t *addr0, const ip4_address_t *addr1, const ip4_address_t *addr2, const ip4_address_t *addr3, index_t *lb0, index_t *lb1, index_t *lb2, index_t *lb3)
Definition: ip4_fib.h:267
load_balance_get_bucket_i
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:229
cm
vnet_feature_config_main_t * cm
Definition: nat44_ei_hairpinning.c:594
ip4_address_t
Definition: ip4_packet.h:50
ip4_fib_forwarding_lookup_x2
static_always_inline void ip4_fib_forwarding_lookup_x2(u32 fib_index0, u32 fib_index1, const ip4_address_t *addr0, const ip4_address_t *addr1, index_t *lb0, index_t *lb1)
Definition: ip4_fib.h:240
ip4_header_t::dst_address
ip4_address_t dst_address
Definition: ip4_packet.h:125
data
u8 data[128]
Definition: ipsec_types.api:95
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
load_balance_main_t_::lbm_to_counters
vlib_combined_counter_main_t lbm_to_counters
Definition: load_balance.h:46
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
cache.h
vlib_combined_counter_main_t
A collection of combined counters.
Definition: counter.h:203
u32
unsigned int u32
Definition: types.h:88
load_balance_get
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:220
n_left
u32 n_left
Definition: interface_output.c:1096
ip4_compute_flow_hash
static u32 ip4_compute_flow_hash(const ip4_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip4_inlines.h:51
ip4_fib.h
ip_lookup_set_buffer_fib_index
static void ip_lookup_set_buffer_fib_index(u32 *fib_index_by_sw_if_index, vlib_buffer_t *b)
Definition: lookup.h:168
vlib_main_t
Definition: main.h:102
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
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
ip
vl_api_address_t ip
Definition: l2.api:558
dpo_id_t_
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:172
nexts
u16 nexts[VLIB_FRAME_SIZE]
Definition: nat44_ei_out2in.c:718
load_balance_t_::lb_n_buckets_minus_1
u16 lb_n_buckets_minus_1
number of buckets in the load-balance - 1.
Definition: load_balance.h:121
ip4_fib_forwarding_lookup
static index_t ip4_fib_forwarding_lookup(u32 fib_index, const ip4_address_t *addr)
Definition: ip4_fib.h:223
load_balance_t_
The FIB DPO provieds;.
Definition: load_balance.h:106
vlib_node_runtime_t
Definition: node.h:454
from
from
Definition: nat44_ei_hairpinning.c:415
is_pow2
static uword is_pow2(uword x)
Definition: clib.h:267
ip4_main_t
IPv4 main type.
Definition: ip4.h:107
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
vlib_increment_combined_counter
vlib_increment_combined_counter(ccm, ti, sw_if_index, n_buffers, n_bytes)
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111