FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
urpf_dp.h
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_source_check.c: IP v4 check source address (unicast RPF check)
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 __URPF_DP_H__
41 #define __URPF_DP_H__
42 
43 #include <vnet/fib/ip4_fib.h>
44 #include <vnet/fib/ip6_fib.h>
45 #include <vnet/fib/fib_urpf_list.h>
46 #include <vnet/dpo/load_balance.h>
47 
48 #include <urpf/urpf.h>
49 
50 /**
51  * @file
52  * @brief Unicast Reverse Path forwarding.
53  *
54  * This file contains the interface unicast source check.
55  */
56 typedef struct
57 {
59 } urpf_trace_t;
60 
61 static u8 *
62 format_urpf_trace (u8 * s, va_list * va)
63 {
64  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
65  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
66  urpf_trace_t *t = va_arg (*va, urpf_trace_t *);
67 
68  s = format (s, "uRPF:%d", t->urpf);
69 
70  return s;
71 }
72 
73 #define foreach_urpf_error \
74  _(DROP, "uRPF Drop") \
75 
76 typedef enum urpf_error_t_
77 {
78 #define _(a,b) URPF_ERROR_##a,
80 #undef _
82 } urpf_error_t;
83 
84 typedef enum
85 {
88 } urpf_next_t;
89 
95 {
96  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
97  u16 nexts[VLIB_FRAME_SIZE], *next;
98  u32 n_left, *from;
99 
100  from = vlib_frame_vector_args (frame);
101  n_left = frame->n_vectors;
102  b = bufs;
103  next = nexts;
104 
105  vlib_get_buffers (vm, from, bufs, n_left);
106 
107  while (n_left >= 4)
108  {
109  u32 pass0, lb_index0, pass1, lb_index1;
110  const load_balance_t *lb0, *lb1;
111  u32 fib_index0, fib_index1;
112  const u8 *h0, *h1;
113 
114  /* Prefetch next iteration. */
115  {
116  vlib_prefetch_buffer_header (b[2], LOAD);
117  vlib_prefetch_buffer_header (b[3], LOAD);
118  vlib_prefetch_buffer_data (b[2], LOAD);
119  vlib_prefetch_buffer_data (b[3], LOAD);
120  }
121 
122  h0 = (u8 *) vlib_buffer_get_current (b[0]);
123  h1 = (u8 *) vlib_buffer_get_current (b[1]);
124 
125  if (VLIB_TX == dir)
126  {
127  h0 += vnet_buffer (b[0])->ip.save_rewrite_length;
128  h1 += vnet_buffer (b[1])->ip.save_rewrite_length;
129  }
130 
131  if (AF_IP4 == af)
132  {
133  const ip4_header_t *ip0, *ip1;
134 
135  ip0 = (ip4_header_t *) h0;
136  ip1 = (ip4_header_t *) h1;
137 
139  [vnet_buffer (b[0])->sw_if_index[dir]];
141  [vnet_buffer (b[1])->sw_if_index[dir]];
142 
143  ip4_fib_forwarding_lookup_x2 (fib_index0,
144  fib_index1,
145  &ip0->src_address,
146  &ip1->src_address,
147  &lb_index0, &lb_index1);
148  /* Pass multicast. */
149  pass0 = (ip4_address_is_multicast (&ip0->src_address) ||
151  pass1 = (ip4_address_is_multicast (&ip1->src_address) ||
153  }
154  else
155  {
156  const ip6_header_t *ip0, *ip1;
157 
159  [vnet_buffer (b[0])->sw_if_index[dir]];
161  [vnet_buffer (b[1])->sw_if_index[dir]];
162 
163  ip0 = (ip6_header_t *) h0;
164  ip1 = (ip6_header_t *) h1;
165 
166  lb_index0 = ip6_fib_table_fwding_lookup (fib_index0,
167  &ip0->src_address);
168  lb_index1 = ip6_fib_table_fwding_lookup (fib_index1,
169  &ip1->src_address);
170  pass0 = ip6_address_is_multicast (&ip0->src_address);
171  pass1 = ip6_address_is_multicast (&ip1->src_address);
172  }
173 
174  lb0 = load_balance_get (lb_index0);
175  lb1 = load_balance_get (lb_index1);
176 
177  if (URPF_MODE_STRICT == mode)
178  {
179  /* for RX the check is: would this source adddress be forwarded
180  * out of the interface on which it was recieved, if yes allow.
181  * For TX it's; would this source address be forwarded out of the
182  * interface through which it is being sent, if yes drop.
183  */
184  int res0, res1;
185 
186  res0 = fib_urpf_check (lb0->lb_urpf,
187  vnet_buffer (b[0])->sw_if_index[dir]);
188  res1 = fib_urpf_check (lb1->lb_urpf,
189  vnet_buffer (b[1])->sw_if_index[dir]);
190 
191  if (VLIB_RX == dir)
192  {
193  pass0 |= res0;
194  pass1 |= res1;
195  }
196  else
197  {
198  pass0 |= !res0 && fib_urpf_check_size (lb0->lb_urpf);
199  pass1 |= !res1 && fib_urpf_check_size (lb1->lb_urpf);
200 
201  /* allow locally generated */
202  pass0 |= b[0]->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
203  pass1 |= b[1]->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
204  }
205  }
206  else
207  {
208  pass0 |= fib_urpf_check_size (lb0->lb_urpf);
209  pass1 |= fib_urpf_check_size (lb1->lb_urpf);
210  }
211 
212  if (PREDICT_TRUE (pass0))
213  vnet_feature_next_u16 (&next[0], b[0]);
214  else
215  {
216  next[0] = URPF_NEXT_DROP;
217  b[0]->error = node->errors[URPF_ERROR_DROP];
218  }
219  if (PREDICT_TRUE (pass1))
220  vnet_feature_next_u16 (&next[1], b[1]);
221  else
222  {
223  next[1] = URPF_NEXT_DROP;
224  b[1]->error = node->errors[URPF_ERROR_DROP];
225  }
226 
227  if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
228  {
229  urpf_trace_t *t;
230 
231  t = vlib_add_trace (vm, node, b[0], sizeof (*t));
232  t->urpf = lb0->lb_urpf;
233  }
234  if (b[1]->flags & VLIB_BUFFER_IS_TRACED)
235  {
236  urpf_trace_t *t;
237 
238  t = vlib_add_trace (vm, node, b[1], sizeof (*t));
239  t->urpf = lb1->lb_urpf;
240  }
241 
242  b += 2;
243  next += 2;
244  n_left -= 2;
245  }
246 
247  while (n_left)
248  {
249  u32 pass0, lb_index0, fib_index0;
250  const load_balance_t *lb0;
251  const u8 *h0;
252 
253  h0 = (u8 *) vlib_buffer_get_current (b[0]);
254 
255  if (VLIB_TX == dir)
256  h0 += vnet_buffer (b[0])->ip.save_rewrite_length;
257 
258  if (AF_IP4 == af)
259  {
260  const ip4_header_t *ip0;
261 
263  [vnet_buffer (b[0])->sw_if_index[dir]];
264  ip0 = (ip4_header_t *) h0;
265 
266  lb_index0 = ip4_fib_forwarding_lookup (fib_index0,
267  &ip0->src_address);
268 
269  /* Pass multicast. */
270  pass0 = (ip4_address_is_multicast (&ip0->src_address) ||
272  }
273  else
274  {
275  const ip6_header_t *ip0;
276 
277  ip0 = (ip6_header_t *) h0;
279  [vnet_buffer (b[0])->sw_if_index[dir]];
280 
281  lb_index0 = ip6_fib_table_fwding_lookup (fib_index0,
282  &ip0->src_address);
283  pass0 = ip6_address_is_multicast (&ip0->src_address);
284  }
285 
286  lb0 = load_balance_get (lb_index0);
287 
288  if (URPF_MODE_STRICT == mode)
289  {
290  int res0;
291 
292  res0 = fib_urpf_check (lb0->lb_urpf,
293  vnet_buffer (b[0])->sw_if_index[dir]);
294  if (VLIB_RX == dir)
295  pass0 |= res0;
296  else
297  {
298  pass0 |= !res0 && fib_urpf_check_size (lb0->lb_urpf);
299  pass0 |= b[0]->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
300  }
301  }
302  else
303  pass0 |= fib_urpf_check_size (lb0->lb_urpf);
304 
305  if (PREDICT_TRUE (pass0))
306  vnet_feature_next_u16 (&next[0], b[0]);
307  else
308  {
309  next[0] = URPF_NEXT_DROP;
310  b[0]->error = node->errors[URPF_ERROR_DROP];
311  }
312 
313  if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
314  {
315  urpf_trace_t *t;
316 
317  t = vlib_add_trace (vm, node, b[0], sizeof (*t));
318  t->urpf = lb0->lb_urpf;
319  }
320  b++;
321  next++;
322  n_left--;
323  }
324 
325  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
326 
327  return frame->n_vectors;
328 }
329 
330 #endif
331 
332 /*
333  * fd.io coding-style-patch-verification: ON
334  *
335  * Local Variables:
336  * eval: (c-set-style "gnu")
337  * End:
338  */
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
#define CLIB_UNUSED(x)
Definition: clib.h:87
static u32 ip6_fib_table_fwding_lookup(u32 fib_index, const ip6_address_t *dst)
Definition: ip6_fib.h:67
static int fib_urpf_check_size(index_t ui)
Data-Plane function to check the size of an uRPF list, (i.e.
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:103
ip4_address_t src_address
Definition: ip4_packet.h:125
#define PREDICT_TRUE(x)
Definition: clib.h:121
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
static int fib_urpf_check(index_t ui, u32 sw_if_index)
Data-Plane function to check an input interface against an uRPF list.
vlib_main_t * vm
Definition: in2out_ed.c:1582
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:122
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static uword ip4_address_is_multicast(const ip4_address_t *a)
Definition: ip4_packet.h:434
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:469
ip6_address_t src_address
Definition: ip6_packet.h:310
unsigned char u8
Definition: types.h:56
static_always_inline uword urpf_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, ip_address_family_t af, vlib_dir_t dir, urpf_mode_t mode)
Definition: urpf_dp.h:91
static_always_inline void vnet_feature_next_u16(u16 *next0, vlib_buffer_t *b0)
Definition: feature.h:328
vlib_rx_or_tx_t
Definition: defs.h:44
#define static_always_inline
Definition: clib.h:108
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
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:176
static u8 * format_urpf_trace(u8 *s, va_list *va)
Definition: urpf_dp.h:62
urpf_error_t_
Definition: urpf_dp.h:76
unsigned int u32
Definition: types.h:88
index_t urpf
Definition: urpf_dp.h:58
#define VLIB_FRAME_SIZE
Definition: node.h:377
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
The FIB DPO provieds;.
Definition: load_balance.h:106
ip6_main_t ip6_main
Definition: ip6_forward.c:2781
urpf_next_t
Definition: urpf_dp.h:84
vl_api_tunnel_mode_t mode
Definition: gre.api:48
u16 n_vectors
Definition: node.h:396
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:339
#define vlib_prefetch_buffer_data(b, type)
Definition: buffer.h:204
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1582
index_t lb_urpf
This is the index of the uRPF list for this LB.
Definition: load_balance.h:156
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:220
static index_t ip4_fib_forwarding_lookup(u32 fib_index, const ip4_address_t *addr)
Definition: ip4_fib.h:160
static uword ip6_address_is_multicast(const ip6_address_t *a)
Definition: ip6_packet.h:121
enum ip_address_family_t_ ip_address_family_t
Definition: defs.h:47
#define foreach_urpf_error
Definition: urpf_dp.h:73
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 void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
#define vnet_buffer(b)
Definition: buffer.h:417
static uword ip4_address_is_global_broadcast(const ip4_address_t *a)
Definition: ip4_packet.h:440
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1144
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:577
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:280
u32 * fib_index_by_sw_if_index
Definition: ip6.h:196
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
enum urpf_error_t_ urpf_error_t
Definition: defs.h:46
enum urpf_mode_t_ urpf_mode_t