Neale Ranns | d792d9c | 2017-10-21 10:53:20 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2017 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 | * bier_imposition : The BIER imposition object |
| 17 | * |
| 18 | * A BIER imposition object is present in the IP mcast output list |
| 19 | * and represents the imposition of a BIER bitmask. After BIER header |
Paul Vinciguerra | 8feeaff | 2019-03-27 11:25:48 -0700 | [diff] [blame] | 20 | * imposition the packet is forward within the appropriate/specified |
Neale Ranns | d792d9c | 2017-10-21 10:53:20 -0700 | [diff] [blame] | 21 | * BIER table |
| 22 | */ |
| 23 | |
| 24 | #include <vnet/bier/bier_imp.h> |
| 25 | #include <vnet/bier/bier_table.h> |
| 26 | #include <vnet/bier/bier_hdr_inlines.h> |
| 27 | #include <vnet/fib/fib_node.h> |
| 28 | #include <vnet/mpls/mpls_types.h> |
| 29 | |
| 30 | /** |
| 31 | * The memory pool of all imp objects |
| 32 | */ |
| 33 | bier_imp_t *bier_imp_pool; |
| 34 | |
| 35 | /** |
| 36 | * When constructing the BIER imp ID from an index and BSL, shift |
| 37 | * the BSL this far |
| 38 | */ |
| 39 | #define BIER_IMP_ID_HLEN_SHIFT 24 |
| 40 | |
| 41 | static void |
| 42 | bier_imp_lock_i (bier_imp_t *bi) |
| 43 | { |
| 44 | bi->bi_locks++; |
| 45 | } |
| 46 | |
| 47 | void |
| 48 | bier_imp_lock (index_t bii) |
| 49 | { |
| 50 | bier_imp_lock_i(bier_imp_get(bii)); |
| 51 | } |
| 52 | |
| 53 | static index_t |
| 54 | bier_imp_get_index(bier_imp_t *bi) |
| 55 | { |
| 56 | return (bi - bier_imp_pool); |
| 57 | } |
| 58 | |
| 59 | index_t |
| 60 | bier_imp_add_or_lock (const bier_table_id_t *bti, |
| 61 | bier_bp_t sender, |
| 62 | const bier_bit_string_t *bs) |
| 63 | { |
| 64 | bier_imp_t *bi = NULL; |
| 65 | fib_protocol_t fproto; |
| 66 | index_t btii; |
| 67 | |
| 68 | pool_get_aligned(bier_imp_pool, bi, CLIB_CACHE_LINE_BYTES); |
| 69 | |
| 70 | bi->bi_tbl = *bti; |
Neale Ranns | fe4e48f | 2018-09-24 23:38:37 -0700 | [diff] [blame] | 71 | btii = bier_table_lock(bti); |
Neale Ranns | d792d9c | 2017-10-21 10:53:20 -0700 | [diff] [blame] | 72 | |
| 73 | /* |
| 74 | * init the BIER header we will paint on in the data plane |
| 75 | */ |
| 76 | bier_hdr_init(&bi->bi_hdr, |
| 77 | BIER_HDR_VERSION_1, |
| 78 | BIER_HDR_PROTO_INVALID, // filled in later |
| 79 | bti->bti_hdr_len, |
| 80 | 0, // entropy |
| 81 | sender); |
| 82 | bier_hdr_hton(&bi->bi_hdr); |
Dave Barach | 178cf49 | 2018-11-13 16:34:13 -0500 | [diff] [blame] | 83 | clib_memcpy_fast(&bi->bi_bits, bs->bbs_buckets, bs->bbs_len); |
Neale Ranns | d792d9c | 2017-10-21 10:53:20 -0700 | [diff] [blame] | 84 | |
| 85 | bier_imp_lock_i(bi); |
| 86 | |
| 87 | /* |
| 88 | * get and stack on the forwarding info from the table |
| 89 | */ |
| 90 | FOR_EACH_FIB_IP_PROTOCOL(fproto) |
| 91 | { |
| 92 | /* |
| 93 | * initialise to invalid first, lest we pick up garbage |
| 94 | * from the pool alloc |
| 95 | */ |
| 96 | dpo_id_t dpo = DPO_INVALID; |
| 97 | bi->bi_dpo[fproto] = dpo; |
| 98 | |
| 99 | bier_table_contribute_forwarding(btii, &dpo); |
| 100 | dpo_stack(DPO_BIER_IMP, fib_proto_to_dpo(fproto), |
| 101 | &bi->bi_dpo[fproto], |
| 102 | &dpo); |
| 103 | dpo_reset(&dpo); |
| 104 | } |
| 105 | |
| 106 | return (bier_imp_get_index(bi)); |
| 107 | } |
| 108 | |
| 109 | void |
| 110 | bier_imp_unlock (index_t bii) |
| 111 | { |
| 112 | fib_protocol_t fproto; |
| 113 | bier_imp_t *bi; |
| 114 | |
| 115 | if (INDEX_INVALID == bii) |
| 116 | { |
| 117 | return; |
| 118 | } |
| 119 | |
| 120 | bi = bier_imp_get(bii); |
| 121 | |
| 122 | bi->bi_locks--; |
| 123 | |
| 124 | if (0 == bi->bi_locks) |
| 125 | { |
| 126 | bier_table_unlock(&bi->bi_tbl); |
| 127 | |
| 128 | FOR_EACH_FIB_IP_PROTOCOL(fproto) |
| 129 | { |
| 130 | dpo_reset(&bi->bi_dpo[fproto]); |
| 131 | } |
| 132 | pool_put(bier_imp_pool, bi); |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | u8* |
| 137 | format_bier_imp (u8* s, va_list *args) |
| 138 | { |
| 139 | index_t bii = va_arg (*args, index_t); |
| 140 | u32 indent = va_arg(*args, u32); |
| 141 | bier_show_flags_t flags = va_arg(*args, bier_show_flags_t); |
| 142 | bier_imp_t *bi; |
| 143 | |
| 144 | bi = bier_imp_get(bii); |
| 145 | |
| 146 | s = format(s, "bier-imp:[%d]: tbl:[%U] hdr:[%U]", |
| 147 | bier_imp_get_index(bi), |
| 148 | format_bier_table_id, &bi->bi_tbl, |
| 149 | format_bier_hdr, &bi->bi_hdr); |
| 150 | |
| 151 | if (BIER_SHOW_DETAIL & flags) |
| 152 | { |
| 153 | bier_bit_string_t bbs; |
| 154 | bier_hdr_t copy; |
| 155 | |
| 156 | copy = bi->bi_hdr; |
| 157 | bier_hdr_ntoh(©); |
| 158 | bier_bit_string_init(&bbs, |
| 159 | bier_hdr_get_len_id(©), |
Neale Ranns | f051072 | 2018-01-31 11:35:41 -0800 | [diff] [blame] | 160 | bi->bi_bits); |
Neale Ranns | d792d9c | 2017-10-21 10:53:20 -0700 | [diff] [blame] | 161 | |
| 162 | s = format(s, "\n%U%U", |
| 163 | format_white_space, indent, |
| 164 | format_bier_bit_string, &bbs); |
| 165 | s = format(s, "\n%U%U", |
| 166 | format_white_space, indent, |
| 167 | format_dpo_id, &bi->bi_dpo, indent+2); |
| 168 | } |
| 169 | |
| 170 | return (s); |
| 171 | } |
| 172 | |
| 173 | void |
| 174 | bier_imp_contribute_forwarding (index_t bii, |
| 175 | dpo_proto_t proto, |
| 176 | dpo_id_t *dpo) |
| 177 | { |
| 178 | dpo_set(dpo, DPO_BIER_IMP, proto, bii); |
| 179 | } |
| 180 | |
| 181 | const static char* const bier_imp_ip4_nodes[] = |
| 182 | { |
| 183 | "bier-imp-ip4", |
| 184 | NULL, |
| 185 | }; |
| 186 | const static char* const bier_imp_ip6_nodes[] = |
| 187 | { |
| 188 | "bier-imp-ip6", |
| 189 | NULL, |
| 190 | }; |
| 191 | |
| 192 | const static char* const * const bier_imp_nodes[DPO_PROTO_NUM] = |
| 193 | { |
| 194 | [DPO_PROTO_IP4] = bier_imp_ip4_nodes, |
| 195 | [DPO_PROTO_IP6] = bier_imp_ip6_nodes, |
| 196 | }; |
| 197 | |
| 198 | static void |
| 199 | bier_imp_dpo_lock (dpo_id_t *dpo) |
| 200 | { |
| 201 | bier_imp_lock(dpo->dpoi_index); |
| 202 | } |
| 203 | |
| 204 | static void |
| 205 | bier_imp_dpo_unlock (dpo_id_t *dpo) |
| 206 | { |
| 207 | bier_imp_unlock(dpo->dpoi_index); |
| 208 | } |
| 209 | |
| 210 | static void |
| 211 | bier_imp_dpo_mem_show (void) |
| 212 | { |
| 213 | fib_show_memory_usage("BIER imposition", |
| 214 | pool_elts(bier_imp_pool), |
| 215 | pool_len(bier_imp_pool), |
| 216 | sizeof(bier_imp_t)); |
| 217 | } |
| 218 | |
| 219 | static u8* |
| 220 | format_bier_imp_dpo (u8* s, va_list *ap) |
| 221 | { |
| 222 | index_t index = va_arg(*ap, index_t); |
| 223 | u32 indent = va_arg(*ap, u32); |
| 224 | |
| 225 | s = format(s, "%U", format_bier_imp, index, indent, BIER_SHOW_DETAIL); |
| 226 | |
| 227 | return (s); |
| 228 | } |
| 229 | |
| 230 | const static dpo_vft_t bier_imp_vft = { |
| 231 | .dv_lock = bier_imp_dpo_lock, |
| 232 | .dv_unlock = bier_imp_dpo_unlock, |
| 233 | .dv_format = format_bier_imp_dpo, |
| 234 | .dv_mem_show = bier_imp_dpo_mem_show, |
| 235 | }; |
| 236 | |
| 237 | clib_error_t * |
| 238 | bier_imp_db_module_init (vlib_main_t *vm) |
| 239 | { |
| 240 | dpo_register(DPO_BIER_IMP, &bier_imp_vft, bier_imp_nodes); |
| 241 | |
| 242 | return (NULL); |
| 243 | } |
| 244 | |
| 245 | VLIB_INIT_FUNCTION (bier_imp_db_module_init); |
| 246 | |
| 247 | static clib_error_t * |
| 248 | show_bier_imp (vlib_main_t * vm, |
| 249 | unformat_input_t * input, |
| 250 | vlib_cli_command_t * cmd) |
| 251 | { |
| 252 | bier_imp_t *bi; |
| 253 | index_t bii; |
| 254 | |
| 255 | bii = INDEX_INVALID; |
| 256 | |
| 257 | while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { |
| 258 | if (unformat (input, "%d", &bii)) |
| 259 | ; |
| 260 | else |
| 261 | { |
| 262 | break; |
| 263 | } |
| 264 | } |
| 265 | |
| 266 | if (INDEX_INVALID == bii) |
| 267 | { |
| 268 | pool_foreach(bi, bier_imp_pool, |
| 269 | ({ |
| 270 | vlib_cli_output(vm, "%U", format_bier_imp, |
| 271 | bier_imp_get_index(bi), |
| 272 | 1, |
| 273 | BIER_SHOW_BRIEF); |
| 274 | })); |
| 275 | } |
| 276 | else |
| 277 | { |
Neale Ranns | 8f6e321 | 2018-06-04 17:10:18 -0700 | [diff] [blame] | 278 | if (pool_is_free_index(bier_imp_pool, bii)) |
| 279 | { |
| 280 | vlib_cli_output(vm, "No such BIER imposition: %d", bii); |
| 281 | } |
| 282 | else |
| 283 | { |
| 284 | vlib_cli_output(vm, "%U", format_bier_imp, bii, 1, |
| 285 | BIER_SHOW_DETAIL); |
| 286 | } |
Neale Ranns | d792d9c | 2017-10-21 10:53:20 -0700 | [diff] [blame] | 287 | } |
| 288 | return (NULL); |
| 289 | } |
| 290 | |
| 291 | VLIB_CLI_COMMAND (show_bier_imp_node, static) = { |
| 292 | .path = "show bier imp", |
| 293 | .short_help = "show bier imp [index]", |
| 294 | .function = show_bier_imp, |
| 295 | }; |