blob: ec417c9a9f7249adacee35b0dfee951a8ee1211f [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 */
68 union
69 {
Neale Ranns6bb2db02021-08-06 12:24:14 +000070 ip4_mtrie_leaf_t leaves[PLY_16_SIZE];
Neale Rannsa3af3372017-03-28 03:49:52 -070071
72#ifdef CLIB_HAVE_VEC128
73 u32x4 leaves_as_u32x4[PLY_16_SIZE / 4];
74#endif
75 };
76
77 /**
78 * Prefix length for terminal leaves.
79 */
80 u8 dst_address_bits_of_leaves[PLY_16_SIZE];
Neale Ranns6bb2db02021-08-06 12:24:14 +000081} ip4_mtrie_16_ply_t;
Neale Rannsa3af3372017-03-28 03:49:52 -070082
83/**
Neale Ranns04a75e32017-03-23 06:46:01 -070084 * @brief One ply of the 4 ply mtrie fib.
85 */
Neale Ranns6bb2db02021-08-06 12:24:14 +000086typedef struct ip4_mtrie_8_ply_t_
Dave Barachd7cb1b52016-12-09 09:52:16 -050087{
Neale Ranns04a75e32017-03-23 06:46:01 -070088 /**
89 * The leaves/slots/buckets to be filed with leafs
90 */
91 union
92 {
Neale Ranns6bb2db02021-08-06 12:24:14 +000093 ip4_mtrie_leaf_t leaves[256];
Ed Warnickecb9cada2015-12-08 15:45:58 -070094
Neale Ranns04a75e32017-03-23 06:46:01 -070095#ifdef CLIB_HAVE_VEC128
96 u32x4 leaves_as_u32x4[256 / 4];
97#endif
98 };
99
100 /**
101 * Prefix length for leaves/ply.
102 */
103 u8 dst_address_bits_of_leaves[256];
104
105 /**
106 * Number of non-empty leafs (whether terminal or not).
107 */
108 i32 n_non_empty_leafs;
109
110 /**
Lijian.Zhang33af8c12019-09-16 16:22:36 +0800111 * The length of the ply's covering prefix. Also a measure of its depth
Neale Ranns04a75e32017-03-23 06:46:01 -0700112 * If a leaf in a slot has a mask length longer than this then it is
113 * 'non-empty'. Otherwise it is the value of the cover.
114 */
115 i32 dst_address_bits_base;
116
117 /* Pad to cache line boundary. */
118 u8 pad[CLIB_CACHE_LINE_BYTES - 2 * sizeof (i32)];
Neale Ranns6bb2db02021-08-06 12:24:14 +0000119} ip4_mtrie_8_ply_t;
Neale Ranns04a75e32017-03-23 06:46:01 -0700120
Neale Ranns6bb2db02021-08-06 12:24:14 +0000121STATIC_ASSERT (0 == sizeof (ip4_mtrie_8_ply_t) % CLIB_CACHE_LINE_BYTES,
Neale Ranns04a75e32017-03-23 06:46:01 -0700122 "IP4 Mtrie ply cache line");
123
Neale Rannsa3af3372017-03-28 03:49:52 -0700124/**
Neale Ranns7244a702021-08-06 13:12:00 +0000125 * @brief The mutiway-TRIE with a 16-8-8 stride.
Neale Rannsa3af3372017-03-28 03:49:52 -0700126 * There is no data associated with the mtrie apart from the top PLY
127 */
Neale Ranns04a75e32017-03-23 06:46:01 -0700128typedef struct
129{
Neale Rannsa3af3372017-03-28 03:49:52 -0700130 /**
131 * Embed the PLY with the mtrie struct. This means that the Data-plane
132 * 'get me the mtrie' returns the first ply, and not an indirect 'pointer'
Lijian.Zhang33af8c12019-09-16 16:22:36 +0800133 * to it. therefore no cacheline misses in the data-path.
Neale Rannsa3af3372017-03-28 03:49:52 -0700134 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000135 ip4_mtrie_16_ply_t root_ply;
136} ip4_mtrie_16_t;
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 The mutiway-TRIE with a 8-8-8-8 stride.
140 * There is no data associated with the mtrie apart from the top PLY
141 */
142typedef struct
143{
144 /* pool index of the root ply */
145 u32 root_ply;
146} ip4_mtrie_8_t;
147
148/**
Neale Rannsa3af3372017-03-28 03:49:52 -0700149 * @brief Initialise an mtrie
150 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000151void ip4_mtrie_16_init (ip4_mtrie_16_t *m);
Neale Ranns7244a702021-08-06 13:12:00 +0000152void ip4_mtrie_8_init (ip4_mtrie_8_t *m);
Neale Ranns04a75e32017-03-23 06:46:01 -0700153
Neale Rannsa3af3372017-03-28 03:49:52 -0700154/**
Neale Ranns7244a702021-08-06 13:12:00 +0000155 * @brief Free an mtrie, It must be empty when free'd
Neale Rannsa3af3372017-03-28 03:49:52 -0700156 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000157void ip4_mtrie_16_free (ip4_mtrie_16_t *m);
Neale Ranns7244a702021-08-06 13:12:00 +0000158void ip4_mtrie_8_free (ip4_mtrie_8_t *m);
Neale Ranns04a75e32017-03-23 06:46:01 -0700159
Neale Rannsa3af3372017-03-28 03:49:52 -0700160/**
Lijian.Zhang33af8c12019-09-16 16:22:36 +0800161 * @brief Add a route/entry to the mtrie
Neale Rannsa3af3372017-03-28 03:49:52 -0700162 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000163void ip4_mtrie_16_route_add (ip4_mtrie_16_t *m,
164 const ip4_address_t *dst_address,
165 u32 dst_address_length, u32 adj_index);
Neale Ranns7244a702021-08-06 13:12:00 +0000166void ip4_mtrie_8_route_add (ip4_mtrie_8_t *m, const ip4_address_t *dst_address,
167 u32 dst_address_length, u32 adj_index);
168
Neale Rannsa3af3372017-03-28 03:49:52 -0700169/**
Lijian.Zhang33af8c12019-09-16 16:22:36 +0800170 * @brief remove a route/entry to the mtrie
Neale Rannsa3af3372017-03-28 03:49:52 -0700171 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000172void ip4_mtrie_16_route_del (ip4_mtrie_16_t *m,
173 const ip4_address_t *dst_address,
174 u32 dst_address_length, u32 adj_index,
175 u32 cover_address_length, u32 cover_adj_index);
Neale Ranns7244a702021-08-06 13:12:00 +0000176void ip4_mtrie_8_route_del (ip4_mtrie_8_t *m, const ip4_address_t *dst_address,
177 u32 dst_address_length, u32 adj_index,
178 u32 cover_address_length, u32 cover_adj_index);
Neale Ranns04a75e32017-03-23 06:46:01 -0700179
Neale Rannsa3af3372017-03-28 03:49:52 -0700180/**
Neale Rannsc87aafa2017-11-29 00:59:31 -0800181 * @brief return the memory used by the table
182 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000183uword ip4_mtrie_16_memory_usage (ip4_mtrie_16_t *m);
Neale Ranns7244a702021-08-06 13:12:00 +0000184uword ip4_mtrie_8_memory_usage (ip4_mtrie_8_t *m);
Neale Rannsc87aafa2017-11-29 00:59:31 -0800185
186/**
Neale Rannsa3af3372017-03-28 03:49:52 -0700187 * @brief Format/display the contents of the mtrie
188 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000189format_function_t format_ip4_mtrie_16;
Neale Ranns7244a702021-08-06 13:12:00 +0000190format_function_t format_ip4_mtrie_8;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700191
Neale Rannsa3af3372017-03-28 03:49:52 -0700192/**
193 * @brief A global pool of 8bit stride plys
194 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000195extern ip4_mtrie_8_ply_t *ip4_ply_pool;
Neale Rannsa3af3372017-03-28 03:49:52 -0700196
197/**
Lijian.Zhang33af8c12019-09-16 16:22:36 +0800198 * Is the leaf terminal (i.e. an LB index) or non-terminal (i.e. a PLY index)
Neale Rannsa3af3372017-03-28 03:49:52 -0700199 */
Dave Barachd7cb1b52016-12-09 09:52:16 -0500200always_inline u32
Neale Ranns6bb2db02021-08-06 12:24:14 +0000201ip4_mtrie_leaf_is_terminal (ip4_mtrie_leaf_t n)
Dave Barachd7cb1b52016-12-09 09:52:16 -0500202{
203 return n & 1;
204}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700205
Neale Rannsa3af3372017-03-28 03:49:52 -0700206/**
207 * From the stored slot value extract the LB index value
208 */
Dave Barachd7cb1b52016-12-09 09:52:16 -0500209always_inline u32
Neale Ranns6bb2db02021-08-06 12:24:14 +0000210ip4_mtrie_leaf_get_adj_index (ip4_mtrie_leaf_t n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700211{
Neale Ranns6bb2db02021-08-06 12:24:14 +0000212 ASSERT (ip4_mtrie_leaf_is_terminal (n));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700213 return n >> 1;
214}
215
Neale Rannsa3af3372017-03-28 03:49:52 -0700216/**
217 * @brief Lookup step. Processes 1 byte of 4 byte ip4 address.
218 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000219always_inline ip4_mtrie_leaf_t
Neale Ranns7244a702021-08-06 13:12:00 +0000220ip4_mtrie_16_lookup_step (ip4_mtrie_leaf_t current_leaf,
Neale Ranns6bb2db02021-08-06 12:24:14 +0000221 const ip4_address_t *dst_address,
222 u32 dst_address_byte_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223{
Neale Ranns6bb2db02021-08-06 12:24:14 +0000224 ip4_mtrie_8_ply_t *ply;
Neale Rannsa3af3372017-03-28 03:49:52 -0700225
Neale Ranns6bb2db02021-08-06 12:24:14 +0000226 uword current_is_terminal = ip4_mtrie_leaf_is_terminal (current_leaf);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700227
Neale Ranns04a75e32017-03-23 06:46:01 -0700228 if (!current_is_terminal)
229 {
Neale Rannsa3af3372017-03-28 03:49:52 -0700230 ply = ip4_ply_pool + (current_leaf >> 1);
Neale Ranns04a75e32017-03-23 06:46:01 -0700231 return (ply->leaves[dst_address->as_u8[dst_address_byte_index]]);
232 }
233
234 return current_leaf;
235}
236
Neale Rannsa3af3372017-03-28 03:49:52 -0700237/**
238 * @brief Lookup step number 1. Processes 2 bytes of 4 byte ip4 address.
239 */
Neale Ranns6bb2db02021-08-06 12:24:14 +0000240always_inline ip4_mtrie_leaf_t
241ip4_mtrie_16_lookup_step_one (const ip4_mtrie_16_t *m,
242 const ip4_address_t *dst_address)
Neale Ranns04a75e32017-03-23 06:46:01 -0700243{
Neale Ranns6bb2db02021-08-06 12:24:14 +0000244 ip4_mtrie_leaf_t next_leaf;
Neale Ranns04a75e32017-03-23 06:46:01 -0700245
Neale Rannsa3af3372017-03-28 03:49:52 -0700246 next_leaf = m->root_ply.leaves[dst_address->as_u16[0]];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700247
248 return next_leaf;
249}
250
Neale Ranns7244a702021-08-06 13:12:00 +0000251always_inline ip4_mtrie_leaf_t
252ip4_mtrie_8_lookup_step (ip4_mtrie_leaf_t current_leaf,
253 const ip4_address_t *dst_address,
254 u32 dst_address_byte_index)
255{
256 ip4_mtrie_8_ply_t *ply;
257
258 uword current_is_terminal = ip4_mtrie_leaf_is_terminal (current_leaf);
259
260 if (!current_is_terminal)
261 {
262 ply = ip4_ply_pool + (current_leaf >> 1);
263 return (ply->leaves[dst_address->as_u8[dst_address_byte_index]]);
264 }
265
266 return current_leaf;
267}
268
269always_inline ip4_mtrie_leaf_t
270ip4_mtrie_8_lookup_step_one (const ip4_mtrie_8_t *m,
271 const ip4_address_t *dst_address)
272{
273 ip4_mtrie_leaf_t next_leaf;
274 ip4_mtrie_8_ply_t *ply;
275
276 ply = pool_elt_at_index (ip4_ply_pool, m->root_ply);
277 next_leaf = ply->leaves[dst_address->as_u8[0]];
278
279 return next_leaf;
280}
281
Ed Warnickecb9cada2015-12-08 15:45:58 -0700282#endif /* included_ip_ip4_fib_h */
Dave Barachd7cb1b52016-12-09 09:52:16 -0500283
284/*
285 * fd.io coding-style-patch-verification: ON
286 *
287 * Local Variables:
288 * eval: (c-set-style "gnu")
289 * End:
290 */