| /* |
| * Copyright (c) 2015 Cisco and/or its affiliates. |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /* |
| * ip/ip4_fib.h: ip4 mtrie fib |
| * |
| * Copyright (c) 2012 Eliot Dresselhaus |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining |
| * a copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sublicense, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #ifndef included_ip_ip4_fib_h |
| #define included_ip_ip4_fib_h |
| |
| #include <vppinfra/cache.h> |
| #include <vppinfra/vector.h> |
| #include <vnet/ip/lookup.h> |
| #include <vnet/ip/ip4_packet.h> /* for ip4_address_t */ |
| |
| /* ip4 fib leafs: 4 ply 8-8-8-8 mtrie. |
| 1 + 2*adj_index for terminal leaves. |
| 0 + 2*next_ply_index for non-terminals. |
| 1 => empty (adjacency index of zero is special miss adjacency). */ |
| typedef u32 ip4_fib_mtrie_leaf_t; |
| |
| #define IP4_FIB_MTRIE_LEAF_EMPTY (1 + 2*0) |
| #define IP4_FIB_MTRIE_LEAF_ROOT (0 + 2*0) |
| |
| always_inline u32 |
| ip4_fib_mtrie_leaf_is_empty (ip4_fib_mtrie_leaf_t n) |
| { |
| return n == IP4_FIB_MTRIE_LEAF_EMPTY; |
| } |
| |
| always_inline u32 |
| ip4_fib_mtrie_leaf_is_non_empty (ip4_fib_mtrie_leaf_t n) |
| { |
| return n != IP4_FIB_MTRIE_LEAF_EMPTY; |
| } |
| |
| always_inline u32 |
| ip4_fib_mtrie_leaf_is_terminal (ip4_fib_mtrie_leaf_t n) |
| { |
| return n & 1; |
| } |
| |
| always_inline u32 |
| ip4_fib_mtrie_leaf_get_adj_index (ip4_fib_mtrie_leaf_t n) |
| { |
| ASSERT (ip4_fib_mtrie_leaf_is_terminal (n)); |
| return n >> 1; |
| } |
| |
| always_inline ip4_fib_mtrie_leaf_t |
| ip4_fib_mtrie_leaf_set_adj_index (u32 adj_index) |
| { |
| ip4_fib_mtrie_leaf_t l; |
| l = 1 + 2 * adj_index; |
| ASSERT (ip4_fib_mtrie_leaf_get_adj_index (l) == adj_index); |
| return l; |
| } |
| |
| always_inline u32 |
| ip4_fib_mtrie_leaf_is_next_ply (ip4_fib_mtrie_leaf_t n) |
| { |
| return (n & 1) == 0; |
| } |
| |
| always_inline u32 |
| ip4_fib_mtrie_leaf_get_next_ply_index (ip4_fib_mtrie_leaf_t n) |
| { |
| ASSERT (ip4_fib_mtrie_leaf_is_next_ply (n)); |
| return n >> 1; |
| } |
| |
| always_inline ip4_fib_mtrie_leaf_t |
| ip4_fib_mtrie_leaf_set_next_ply_index (u32 i) |
| { |
| ip4_fib_mtrie_leaf_t l; |
| l = 0 + 2 * i; |
| ASSERT (ip4_fib_mtrie_leaf_get_next_ply_index (l) == i); |
| return l; |
| } |
| |
| /* One ply of the 4 ply mtrie fib. */ |
| typedef struct |
| { |
| union |
| { |
| ip4_fib_mtrie_leaf_t leaves[256]; |
| |
| #ifdef CLIB_HAVE_VEC128 |
| u32x4 leaves_as_u32x4[256 / 4]; |
| #endif |
| }; |
| |
| /* Prefix length for terminal leaves. */ |
| u8 dst_address_bits_of_leaves[256]; |
| |
| /* Number of non-empty leafs (whether terminal or not). */ |
| i32 n_non_empty_leafs; |
| |
| /* Pad to cache line boundary. */ |
| u8 pad[CLIB_CACHE_LINE_BYTES - 1 * sizeof (i32)]; |
| } |
| ip4_fib_mtrie_ply_t; |
| |
| STATIC_ASSERT (0 == sizeof (ip4_fib_mtrie_ply_t) % CLIB_CACHE_LINE_BYTES, |
| "IP4 Mtrie ply cache line"); |
| |
| typedef struct |
| { |
| /* Pool of plies. Index zero is root ply. */ |
| ip4_fib_mtrie_ply_t *ply_pool; |
| |
| /* Special case leaf for default route 0.0.0.0/0. */ |
| ip4_fib_mtrie_leaf_t default_leaf; |
| } ip4_fib_mtrie_t; |
| |
| void ip4_fib_mtrie_init (ip4_fib_mtrie_t * m); |
| |
| struct ip4_fib_t; |
| |
| void ip4_fib_mtrie_add_del_route (struct ip4_fib_t *f, |
| ip4_address_t dst_address, |
| u32 dst_address_length, |
| u32 adj_index, u32 is_del); |
| |
| /* Returns adjacency index. */ |
| u32 ip4_mtrie_lookup_address (ip4_fib_mtrie_t * m, ip4_address_t dst); |
| |
| format_function_t format_ip4_fib_mtrie; |
| |
| /* Lookup step. Processes 1 byte of 4 byte ip4 address. */ |
| always_inline ip4_fib_mtrie_leaf_t |
| ip4_fib_mtrie_lookup_step (ip4_fib_mtrie_t * m, |
| ip4_fib_mtrie_leaf_t current_leaf, |
| const ip4_address_t * dst_address, |
| u32 dst_address_byte_index) |
| { |
| ip4_fib_mtrie_leaf_t next_leaf; |
| ip4_fib_mtrie_ply_t *ply; |
| uword current_is_terminal = ip4_fib_mtrie_leaf_is_terminal (current_leaf); |
| |
| ply = m->ply_pool + (current_is_terminal ? 0 : (current_leaf >> 1)); |
| next_leaf = ply->leaves[dst_address->as_u8[dst_address_byte_index]]; |
| next_leaf = current_is_terminal ? current_leaf : next_leaf; |
| |
| return next_leaf; |
| } |
| |
| #endif /* included_ip_ip4_fib_h */ |
| |
| /* |
| * fd.io coding-style-patch-verification: ON |
| * |
| * Local Variables: |
| * eval: (c-set-style "gnu") |
| * End: |
| */ |