blob: 16c524745be07348d5e8b0f7b30c000d3b0a601b [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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_fib.h: ip4 mtrie fib
17 *
18 * Copyright (c) 2012 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_ip_ip4_fib_h
41#define included_ip_ip4_fib_h
42
43#include <vppinfra/cache.h>
44#include <vppinfra/vector.h>
45#include <vnet/ip/lookup.h>
46#include <vnet/ip/ip4_packet.h> /* for ip4_address_t */
47
48/* ip4 fib leafs: 4 ply 8-8-8-8 mtrie.
49 1 + 2*adj_index for terminal leaves.
Neale Rannsa3af3372017-03-28 03:49:52 -070050 0 + 2*next_ply_index for non-terminals, i.e. PLYs
Ed Warnickecb9cada2015-12-08 15:45:58 -070051 1 => empty (adjacency index of zero is special miss adjacency). */
Neale Ranns6bb2db02021-08-06 12:24:14 +000052typedef u32 ip4_mtrie_leaf_t;
Ed Warnickecb9cada2015-12-08 15:45:58 -070053
Neale Ranns6bb2db02021-08-06 12:24:14 +000054#define IP4_MTRIE_LEAF_EMPTY (1 + 2 * 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -070055
Neale Ranns04a75e32017-03-23 06:46:01 -070056/**
Neale Rannsa3af3372017-03-28 03:49:52 -070057 * @brief the 16 way stride that is the top PLY of the mtrie
58 * We do not maintain the count of 'real' leaves in this PLY, since
59 * it is never removed. The FIB will destroy the mtrie and the ply once
60 * the FIB is destroyed.
61 */
62#define PLY_16_SIZE (1<<16)
Neale Ranns6bb2db02021-08-06 12:24:14 +000063typedef struct ip4_mtrie_16_ply_t_
Neale Rannsa3af3372017-03-28 03:49:52 -070064{
65 /**
66 * The leaves/slots/buckets to be filed with leafs
67 */
Damjan Marion9ff617c2021-12-23 13:19:15 +010068 ip4_mtrie_leaf_t leaves[PLY_16_SIZE];
Neale Rannsa3af3372017-03-28 03:49:52 -070069
70 /**
71 * Prefix length for terminal leaves.
72 */
73 u8 dst_address_bits_of_leaves[PLY_16_SIZE];
Neale Ranns6bb2db02021-08-06 12:24:14 +000074} ip4_mtrie_16_ply_t;
Neale Rannsa3af3372017-03-28 03:49:52 -070075
76/**
Neale Ranns04a75e32017-03-23 06:46:01 -070077 * @brief One ply of the 4 ply mtrie fib.
78 */
Neale Ranns6bb2db02021-08-06 12:24:14 +000079typedef struct ip4_mtrie_8_ply_t_
Dave Barachd7cb1b52016-12-09 09:52:16 -050080{
Damjan Marion9ff617c2021-12-23 13:19:15 +010081 CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
Neale Ranns04a75e32017-03-23 06:46:01 -070082 /**
83 * The leaves/slots/buckets to be filed with leafs
84 */
Damjan Marion9ff617c2021-12-23 13:19:15 +010085 ip4_mtrie_leaf_t leaves[256];
Neale Ranns04a75e32017-03-23 06:46:01 -070086
87 /**
88 * Prefix length for leaves/ply.
89 */
90 u8 dst_address_bits_of_leaves[256];
91
92 /**
93 * Number of non-empty leafs (whether terminal or not).
94 */
95 i32 n_non_empty_leafs;
96
97 /**
Lijian.Zhang33af8c12019-09-16 16:22:36 +080098 * The length of the ply's covering prefix. Also a measure of its depth
Neale Ranns04a75e32017-03-23 06:46:01 -070099 * If a leaf in a slot has a mask length longer than this then it is
100 * 'non-empty'. Otherwise it is the value of the cover.
101 */
102 i32 dst_address_bits_base;
Neale Ranns6bb2db02021-08-06 12:24:14 +0000103} ip4_mtrie_8_ply_t;
Neale Ranns04a75e32017-03-23 06:46:01 -0700104
Neale Ranns6bb2db02021-08-06 12:24:14 +0000105STATIC_ASSERT (0 == sizeof (ip4_mtrie_8_ply_t) % CLIB_CACHE_LINE_BYTES,
Neale Ranns04a75e32017-03-23 06:46:01 -0700106 "IP4 Mtrie ply cache line");
107
Neale Rannsa3af3372017-03-28 03:49:52 -0700108/**
Neale Ranns7244a702021-08-06 13:12:00 +0000109 * @brief The mutiway-TRIE with a 16-8-8 stride.
Neale Rannsa3af3372017-03-28 03:49:52 -0700110 * There is no data associated with the mtrie apart from the top PLY
111 */
Neale Ranns04a75e32017-03-23 06:46:01 -0700112typedef struct
113{
Neale Rannsa3af3372017-03-28 03:49:52 -0700114 /**
115 * Embed the PLY with the mtrie struct. This means that the Data-plane
116 * 'get me the mtrie' returns the first ply, and not an indirect 'pointer'
Lijian.Zhang33af8c12019-09-16 16:22:36 +0800117 * to it. therefore no cacheline misses in the data-path.
Neale Rannsa3af3372017-03-28 03:49:52 -0700118 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000119 ip4_mtrie_16_ply_t root_ply;
120} ip4_mtrie_16_t;
Neale Ranns04a75e32017-03-23 06:46:01 -0700121
Neale Rannsa3af3372017-03-28 03:49:52 -0700122/**
Neale Ranns7244a702021-08-06 13:12:00 +0000123 * @brief The mutiway-TRIE with a 8-8-8-8 stride.
124 * There is no data associated with the mtrie apart from the top PLY
125 */
126typedef struct
127{
128 /* pool index of the root ply */
129 u32 root_ply;
130} ip4_mtrie_8_t;
131
132/**
Neale Rannsa3af3372017-03-28 03:49:52 -0700133 * @brief Initialise an mtrie
134 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000135void ip4_mtrie_16_init (ip4_mtrie_16_t *m);
Neale Ranns7244a702021-08-06 13:12:00 +0000136void ip4_mtrie_8_init (ip4_mtrie_8_t *m);
Neale Ranns04a75e32017-03-23 06:46:01 -0700137
Neale Rannsa3af3372017-03-28 03:49:52 -0700138/**
Neale Ranns7244a702021-08-06 13:12:00 +0000139 * @brief Free an mtrie, It must be empty when free'd
Neale Rannsa3af3372017-03-28 03:49:52 -0700140 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000141void ip4_mtrie_16_free (ip4_mtrie_16_t *m);
Neale Ranns7244a702021-08-06 13:12:00 +0000142void ip4_mtrie_8_free (ip4_mtrie_8_t *m);
Neale Ranns04a75e32017-03-23 06:46:01 -0700143
Neale Rannsa3af3372017-03-28 03:49:52 -0700144/**
Lijian.Zhang33af8c12019-09-16 16:22:36 +0800145 * @brief Add a route/entry to the mtrie
Neale Rannsa3af3372017-03-28 03:49:52 -0700146 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000147void ip4_mtrie_16_route_add (ip4_mtrie_16_t *m,
148 const ip4_address_t *dst_address,
149 u32 dst_address_length, u32 adj_index);
Neale Ranns7244a702021-08-06 13:12:00 +0000150void ip4_mtrie_8_route_add (ip4_mtrie_8_t *m, const ip4_address_t *dst_address,
151 u32 dst_address_length, u32 adj_index);
152
Neale Rannsa3af3372017-03-28 03:49:52 -0700153/**
Lijian.Zhang33af8c12019-09-16 16:22:36 +0800154 * @brief remove a route/entry to the mtrie
Neale Rannsa3af3372017-03-28 03:49:52 -0700155 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000156void ip4_mtrie_16_route_del (ip4_mtrie_16_t *m,
157 const ip4_address_t *dst_address,
158 u32 dst_address_length, u32 adj_index,
159 u32 cover_address_length, u32 cover_adj_index);
Neale Ranns7244a702021-08-06 13:12:00 +0000160void ip4_mtrie_8_route_del (ip4_mtrie_8_t *m, const ip4_address_t *dst_address,
161 u32 dst_address_length, u32 adj_index,
162 u32 cover_address_length, u32 cover_adj_index);
Neale Ranns04a75e32017-03-23 06:46:01 -0700163
Neale Rannsa3af3372017-03-28 03:49:52 -0700164/**
Neale Rannsc87aafa2017-11-29 00:59:31 -0800165 * @brief return the memory used by the table
166 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000167uword ip4_mtrie_16_memory_usage (ip4_mtrie_16_t *m);
Neale Ranns7244a702021-08-06 13:12:00 +0000168uword ip4_mtrie_8_memory_usage (ip4_mtrie_8_t *m);
Neale Rannsc87aafa2017-11-29 00:59:31 -0800169
170/**
Neale Rannsa3af3372017-03-28 03:49:52 -0700171 * @brief Format/display the contents of the mtrie
172 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000173format_function_t format_ip4_mtrie_16;
Neale Ranns7244a702021-08-06 13:12:00 +0000174format_function_t format_ip4_mtrie_8;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700175
Neale Rannsa3af3372017-03-28 03:49:52 -0700176/**
177 * @brief A global pool of 8bit stride plys
178 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000179extern ip4_mtrie_8_ply_t *ip4_ply_pool;
Neale Rannsa3af3372017-03-28 03:49:52 -0700180
181/**
Lijian.Zhang33af8c12019-09-16 16:22:36 +0800182 * Is the leaf terminal (i.e. an LB index) or non-terminal (i.e. a PLY index)
Neale Rannsa3af3372017-03-28 03:49:52 -0700183 */
Dave Barachd7cb1b52016-12-09 09:52:16 -0500184always_inline u32
Neale Ranns6bb2db02021-08-06 12:24:14 +0000185ip4_mtrie_leaf_is_terminal (ip4_mtrie_leaf_t n)
Dave Barachd7cb1b52016-12-09 09:52:16 -0500186{
187 return n & 1;
188}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700189
Neale Rannsa3af3372017-03-28 03:49:52 -0700190/**
191 * From the stored slot value extract the LB index value
192 */
Dave Barachd7cb1b52016-12-09 09:52:16 -0500193always_inline u32
Neale Ranns6bb2db02021-08-06 12:24:14 +0000194ip4_mtrie_leaf_get_adj_index (ip4_mtrie_leaf_t n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700195{
Neale Ranns6bb2db02021-08-06 12:24:14 +0000196 ASSERT (ip4_mtrie_leaf_is_terminal (n));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700197 return n >> 1;
198}
199
Neale Rannsa3af3372017-03-28 03:49:52 -0700200/**
201 * @brief Lookup step. Processes 1 byte of 4 byte ip4 address.
202 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000203always_inline ip4_mtrie_leaf_t
Neale Ranns7244a702021-08-06 13:12:00 +0000204ip4_mtrie_16_lookup_step (ip4_mtrie_leaf_t current_leaf,
Neale Ranns6bb2db02021-08-06 12:24:14 +0000205 const ip4_address_t *dst_address,
206 u32 dst_address_byte_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700207{
Neale Ranns6bb2db02021-08-06 12:24:14 +0000208 ip4_mtrie_8_ply_t *ply;
Neale Rannsa3af3372017-03-28 03:49:52 -0700209
Neale Ranns6bb2db02021-08-06 12:24:14 +0000210 uword current_is_terminal = ip4_mtrie_leaf_is_terminal (current_leaf);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700211
Neale Ranns04a75e32017-03-23 06:46:01 -0700212 if (!current_is_terminal)
213 {
Neale Rannsa3af3372017-03-28 03:49:52 -0700214 ply = ip4_ply_pool + (current_leaf >> 1);
Neale Ranns04a75e32017-03-23 06:46:01 -0700215 return (ply->leaves[dst_address->as_u8[dst_address_byte_index]]);
216 }
217
218 return current_leaf;
219}
220
Neale Rannsa3af3372017-03-28 03:49:52 -0700221/**
222 * @brief Lookup step number 1. Processes 2 bytes of 4 byte ip4 address.
223 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000224always_inline ip4_mtrie_leaf_t
225ip4_mtrie_16_lookup_step_one (const ip4_mtrie_16_t *m,
226 const ip4_address_t *dst_address)
Neale Ranns04a75e32017-03-23 06:46:01 -0700227{
Neale Ranns6bb2db02021-08-06 12:24:14 +0000228 ip4_mtrie_leaf_t next_leaf;
Neale Ranns04a75e32017-03-23 06:46:01 -0700229
Neale Rannsa3af3372017-03-28 03:49:52 -0700230 next_leaf = m->root_ply.leaves[dst_address->as_u16[0]];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700231
232 return next_leaf;
233}
234
Neale Ranns7244a702021-08-06 13:12:00 +0000235always_inline ip4_mtrie_leaf_t
236ip4_mtrie_8_lookup_step (ip4_mtrie_leaf_t current_leaf,
237 const ip4_address_t *dst_address,
238 u32 dst_address_byte_index)
239{
240 ip4_mtrie_8_ply_t *ply;
241
242 uword current_is_terminal = ip4_mtrie_leaf_is_terminal (current_leaf);
243
244 if (!current_is_terminal)
245 {
246 ply = ip4_ply_pool + (current_leaf >> 1);
247 return (ply->leaves[dst_address->as_u8[dst_address_byte_index]]);
248 }
249
250 return current_leaf;
251}
252
253always_inline ip4_mtrie_leaf_t
254ip4_mtrie_8_lookup_step_one (const ip4_mtrie_8_t *m,
255 const ip4_address_t *dst_address)
256{
257 ip4_mtrie_leaf_t next_leaf;
258 ip4_mtrie_8_ply_t *ply;
259
260 ply = pool_elt_at_index (ip4_ply_pool, m->root_ply);
261 next_leaf = ply->leaves[dst_address->as_u8[0]];
262
263 return next_leaf;
264}
265
Ed Warnickecb9cada2015-12-08 15:45:58 -0700266#endif /* included_ip_ip4_fib_h */
Dave Barachd7cb1b52016-12-09 09:52:16 -0500267
268/*
269 * fd.io coding-style-patch-verification: ON
270 *
271 * Local Variables:
272 * eval: (c-set-style "gnu")
273 * End:
274 */