/* * Copyright (c) 2016 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * Enurmeration of path types */ typedef enum fib_path_type_t_ { /** * Marker. Add new types after this one. */ FIB_PATH_TYPE_FIRST = 0, /** * Attached-nexthop. An interface and a nexthop are known. */ FIB_PATH_TYPE_ATTACHED_NEXT_HOP = FIB_PATH_TYPE_FIRST, /** * attached. Only the interface is known. */ FIB_PATH_TYPE_ATTACHED, /** * recursive. Only the next-hop is known. */ FIB_PATH_TYPE_RECURSIVE, /** * special. nothing is known. so we drop. */ FIB_PATH_TYPE_SPECIAL, /** * exclusive. user provided adj. */ FIB_PATH_TYPE_EXCLUSIVE, /** * deag. Link to a lookup adj in the next table */ FIB_PATH_TYPE_DEAG, /** * interface receive. */ FIB_PATH_TYPE_INTF_RX, /** * Path resolves via a UDP encap object. */ FIB_PATH_TYPE_UDP_ENCAP, /** * receive. it's for-us. */ FIB_PATH_TYPE_RECEIVE, /** * bier-imp. it's via a BIER imposition. */ FIB_PATH_TYPE_BIER_IMP, /** * bier-fmask. it's via a BIER ECMP-table. */ FIB_PATH_TYPE_BIER_TABLE, /** * bier-fmask. it's via a BIER f-mask. */ FIB_PATH_TYPE_BIER_FMASK, /** * via a DVR. */ FIB_PATH_TYPE_DVR, } __attribute__ ((packed)) fib_path_type_t; #define FIB_PATH_TYPES { \ [FIB_PATH_TYPE_ATTACHED_NEXT_HOP] = "attached-nexthop", \ [FIB_PATH_TYPE_ATTACHED] = "attached", \ [FIB_PATH_TYPE_RECURSIVE] = "recursive", \ [FIB_PATH_TYPE_SPECIAL] = "special", \ [FIB_PATH_TYPE_EXCLUSIVE] = "exclusive", \ [FIB_PATH_TYPE_DEAG] = "deag", \ [FIB_PATH_TYPE_INTF_RX] = "intf-rx", \ [FIB_PATH_TYPE_UDP_ENCAP] = "udp-encap", \ [FIB_PATH_TYPE_RECEIVE] = "receive", \ [FIB_PATH_TYPE_BIER_IMP] = "bier-imp", \ [FIB_PATH_TYPE_BIER_TABLE] = "bier-table", \ [FIB_PATH_TYPE_BIER_FMASK] = "bier-fmask", \ [FIB_PATH_TYPE_DVR] = "dvr", \ } /** * Enurmeration of path operational (i.e. derived) attributes */ typedef enum fib_path_oper_attribute_t_ { /** * Marker. Add new types after this one. */ FIB_PATH_OPER_ATTRIBUTE_FIRST = 0, /** * The path forms part of a recursive loop. */ FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP = FIB_PATH_OPER_ATTRIBUTE_FIRST, /** * The path is resolved */ FIB_PATH_OPER_ATTRIBUTE_RESOLVED, /** * The path has become a permanent drop. */ FIB_PATH_OPER_ATTRIBUTE_DROP, /** * Marker. Add new types before this one, then update it. */ FIB_PATH_OPER_ATTRIBUTE_LAST = FIB_PATH_OPER_ATTRIBUTE_DROP, } __attribute__ ((packed)) fib_path_oper_attribute_t; /** * The maximum number of path operational attributes */ #define FIB_PATH_OPER_ATTRIBUTE_MAX (FIB_PATH_OPER_ATTRIBUTE_LAST + 1) #define FIB_PATH_OPER_ATTRIBUTES { \ [FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP] = "recursive-loop", \ [FIB_PATH_OPER_ATTRIBUTE_RESOLVED] = "resolved", \ [FIB_PATH_OPER_ATTRIBUTE_DROP] = "drop", \ } #define FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(_item) \ for (_item = FIB_PATH_OPER_ATTRIBUTE_FIRST; \ _item <= FIB_PATH_OPER_ATTRIBUTE_LAST; \ _item++) /** * Path flags from the attributes */ typedef enum fib_path_oper_flags_t_ { FIB_PATH_OPER_FLAG_NONE = 0, FIB_PATH_OPER_FLAG_RECURSIVE_LOOP = (1 << FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP), FIB_PATH_OPER_FLAG_DROP = (1 << FIB_PATH_OPER_ATTRIBUTE_DROP), FIB_PATH_OPER_FLAG_RESOLVED = (1 << FIB_PATH_OPER_ATTRIBUTE_RESOLVED), } __attribute__ ((packed)) fib_path_oper_flags_t; /** * A FIB path */ typedef struct fib_path_t_ { /** * A path is a node in the FIB graph. */ fib_node_t fp_node; /** * The index of the path-list to which this path belongs */ u32 fp_pl_index; /** * This marks the start of the memory area used to hash * the path */ STRUCT_MARK(path_hash_start); /** * Configuration Flags */ fib_path_cfg_flags_t fp_cfg_flags; /** * The type of the path. This is the selector for the union */ fib_path_type_t fp_type; /** * The protocol of the next-hop, i.e. the address family of the * next-hop's address. We can't derive this from the address itself * since the address can be all zeros */ dpo_proto_t fp_nh_proto; /** * UCMP [unnormalised] weigth */ u8 fp_weight; /** * A path preference. 0 is the best. * Only paths of the best preference, that are 'up', are considered * for forwarding. */ u8 fp_preference; /** * per-type union of the data required to resolve the path */ union { struct { /** * The next-hop */ ip46_address_t fp_nh; /** * The interface */ u32 fp_interface; } attached_next_hop; struct { /** * The Connected local address */ fib_prefix_t fp_connected; /** * The interface */ u32 fp_interface; } attached; struct { union { /** * The next-hop */ ip46_address_t fp_ip; struct { /** * The local label to resolve through. */ mpls_label_t fp_local_label; /** * The EOS bit of the resolving label */ mpls_eos_bit_t fp_eos; }; } fp_nh; /** * The FIB table index in which to find the next-hop. */ fib_node_index_t fp_tbl_id; } recursive; struct { /** * BIER FMask ID */ index_t fp_bier_fmask; } bier_fmask; struct { /** * The BIER table's ID */ bier_table_id_t fp_bier_tbl; } bier_table; struct { /** * The BIER imposition object * this is part of the path's key, since the index_t * of an imposition object is the object's key. */ index_t fp_bier_imp; } bier_imp; struct { /** * The FIB index in which to perfom the next lookup */ fib_node_index_t fp_tbl_id; /** * The RPF-ID to tag the packets with */ fib_rpf_id_t fp_rpf_id; } deag; struct { } special; struct { /** * The user provided 'exclusive' DPO */ dpo_id_t fp_ex_dpo; } exclusive; struct { /** * The interface on which the local address is configured */ u32 fp_interface; /** * The next-hop */ ip46_address_t fp_addr; } receive; struct { /** * The interface on which the packets will be input. */ u32 fp_interface; } intf_rx; struct { /** * The UDP Encap object this path resolves through */ u32 fp_udp_encap_id; } udp_encap; struct { /** * The UDP Encap object this path resolves through */ u32 fp_classify_table_id; } classify; struct { /** * The interface */ u32 fp_interface; } dvr; }; STRUCT_MARK(path_hash_end); /** * Members in this last section represent information that is * dervied during resolution. It should not be copied to new paths * nor compared. */ /** * Operational Flags */ fib_path_oper_flags_t fp_oper_flags; union { /** * the resolving via fib. not part of the union, since it it not part * of the path's hash. */ fib_node_index_t fp_via_fib; /** * the resolving bier-table */ index_t fp_via_bier_tbl; /** * the resolving bier-fmask */ index_t fp_via_bier_fmask; }; /** * The Data-path objects through which this path resolves for IP. */ dpo_id_t fp_dpo; /** * the index of this path in the parent's child list. */ u32 fp_sibling; } fib_path_t; /* * Array of strings/names for the path types and attributes */ static const char *fib_path_type_names[] = FIB_PATH_TYPES; static const char *fib_path_oper_attribute_names[] = FIB_PATH_OPER_ATTRIBUTES; static const char *fib_path_cfg_attribute_names[] = FIB_PATH_CFG_ATTRIBUTES; /* * The memory pool from which we allocate all the paths */ static fib_path_t *fib_path_pool; /** * the logger */ vlib_log_class_t fib_path_logger; /* * Debug macro */ #define FIB_PATH_DBG(_p, _fmt, _args...) \ { \ vlib_log_debug (fib_path_logger, \ "[%U]: " _fmt, \ format_fib_path, fib_path_get_index(_p), 0, \ FIB_PATH_FORMAT_FLAGS_ONE_LINE, \ ##_args); \ } static fib_path_t * fib_path_get (fib_node_index_t index) { return (pool_elt_at_index(fib_path_pool, index)); } static fib_node_index_t fib_path_get_index (fib_path_t *path) { return (path - fib_path_pool); } static fib_node_t * fib_path_get_node (fib_node_index_t index) { return ((fib_node_t*)fib_path_get(index)); } static fib_path_t* fib_path_from_fib_node (fib_node_t *node) { ASSERT(FIB_NODE_TYPE_PATH == node->fn_type); return ((fib_path_t*)node); } u8 * format_fib_path (u8 * s, va_list * args) { fib_node_index_t path_index = va_arg (*args, fib_node_index_t); u32 indent = va_arg (*args, u32); fib_format_path_flags_t flags = va_arg (*args, fib_format_path_flags_t); vnet_main_t * vnm = vnet_get_main(); fib_path_oper_attribute_t oattr; fib_path_cfg_attribute_t cattr; fib_path_t *path; const char *eol; if (flags & FIB_PATH_FORMAT_FLAGS_ONE_LINE) { eol = ""; } else { eol = "\n"; } path = fib_path_get(path_index); s = format (s, "%Upath:[%d] ", format_white_space, indent, fib_path_get_index(path)); s = format (s, "pl-index:%d ", path->fp_pl_index); s = format (s, "%U ", format_dpo_proto, path->fp_nh_proto); s = format (s, "weight=%d ", path->fp_weight); s = format (s, "pref=%d ", path->fp_preference); s = format (s, "%s: ", fib_path_type_names[path->fp_type]); if (FIB_PATH_OPER_FLAG_NONE != path->fp_oper_flags) { s = format(s, " oper-flags:"); FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(oattr) { if ((1<fp_oper_flags) { s = format (s, "%s,", fib_path_oper_attribute_names[oattr]); } } } if (FIB_PATH_CFG_FLAG_NONE != path->fp_cfg_flags) { s = format(s, " cfg-flags:"); FOR_EACH_FIB_PATH_CFG_ATTRIBUTE(cattr) { if ((1<fp_cfg_flags) { s = format (s, "%s,", fib_path_cfg_attribute_names[cattr]); } } } if (!(flags & FIB_PATH_FORMAT_FLAGS_ONE_LINE)) s = format(s, "\n%U", format_white_space, indent+2); switch (path->fp_type) { case FIB_PATH_TYPE_ATTACHED_NEXT_HOP: s = format (s, "%U", format_ip46_address, &path->attached_next_hop.fp_nh, IP46_TYPE_ANY); if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP) { s = format (s, " if_index:%d", path->attached_next_hop.fp_interface); } else { s = format (s, " %U", format_vnet_sw_interface_name, vnm, vnet_get_sw_interface( vnm, path->attached_next_hop.fp_interface)); if (vnet_sw_interface_is_p2p(vnet_get_main(), path->attached_next_hop.fp_interface)) { s = format (s, " (p2p)"); } } if (!dpo_id_is_valid(&path->fp_dpo)) { s = format(s, "%s%Uunresolved", eol, format_white_space, indent+2); } else { s = format(s, "%s%U%U", eol, format_white_space, indent, format_dpo_id, &path->fp_dpo, 13); } break; case FIB_PATH_TYPE_ATTACHED: if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP) { s = format (s, "if_index:%d", path->attached_next_hop.fp_interface); } else { s = format (s, " %U", format_vnet_sw_interface_name, vnm, vnet_get_sw_interface( vnm, path->attached.fp_interface)); } break; case FIB_PATH_TYPE_RECURSIVE: if (DPO_PROTO_MPLS == path->fp_nh_proto) { s = format (s, "via %U %U", format_mpls_unicast_label, path->recursive.fp_nh.fp_local_label, format_mpls_eos_bit, path->recursive.fp_nh.fp_eos); } else { s = format (s, "via %U", format_ip46_address, &path->recursive.fp_nh.fp_ip, IP46_TYPE_ANY); } s = format (s, " in fib:%d", path->recursive.fp_tbl_id, path->fp_via_fib); s = format (s, " via-fib:%d", path->fp_via_fib); s = format (s, " via-dpo:[%U:%d]", format_dpo_type, path->fp_dpo.dpoi_type, path->fp_dpo.dpoi_index); break; case FIB_PATH_TYPE_UDP_ENCAP: s = format (s, "UDP-encap ID:%d", path->udp_encap.fp_udp_encap_id); break; case FIB_PATH_TYPE_BIER_TABLE: s = format (s, "via bier-table:[%U}", format_bier_table_id, &path->bier_table.fp_bier_tbl); s = format (s, " via-dpo:[%U:%d]", format_dpo_type, path->fp_dpo.dpoi_type, path->fp_dpo.dpoi_index); break; case FIB_PATH_TYPE_BIER_FMASK: s = format (s, "via-fmask:%d", path->bier_fmask.fp_bier_fmask); s = format (s, " via-dpo:[%U:%d]", format_dpo_type, path->fp_dpo.dpoi_type, path->fp_dpo.dpoi_index); break; case FIB_PATH_TYPE_BIER_IMP: s = format (s, "via %U", format_bier_imp, path->bier_imp.fp_bier_imp, 0, BIER_SHOW_BRIEF); break; case FIB_PATH_TYPE_DVR: s = format (s, " %U", format_vnet_sw_interface_name, vnm, vnet_get_sw_interface( vnm, path->dvr.fp_interface)); break; case FIB_PATH_TYPE_DEAG: s = format (s, " %sfib-index:%d", (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID ? "m" : ""), path->deag.fp_tbl_id); break; case FIB_PATH_TYPE_RECEIVE: case FIB_PATH_TYPE_INTF_RX: case FIB_PATH_TYPE_SPECIAL: case FIB_PATH_TYPE_EXCLUSIVE: if (dpo_id_is_valid(&path->fp_dpo)) { s = format(s, "%U", format_dpo_id, &path->fp_dpo, indent+2); } break; } return (s); } /* * fib_path_last_lock_gone * * We don't share paths, we share path lists, so the [un]lock functions * are no-ops */ static void fib_path_last_lock_gone (fib_node_t *node) { ASSERT(0); } static fib_path_t* fib_path_attached_next_hop_get_adj (fib_path_t *path, vnet_link_t link, dpo_id_t *dpo) { fib_node_index_t fib_path_index; fib_protocol_t nh_proto; adj_index_t ai; fib_path_index = fib_path_get_index(path); nh_proto = dpo_proto_to_fib(path->fp_nh_proto); if (vnet_sw_interface_is_p2p(vnet_get_main(), path->attached_next_hop.fp_interface)) { /* * if the interface is p2p then the adj for the specific * neighbour on that link will never exist. on p2p links * the subnet address (the attached route) links to the * auto-adj (see below), we want that adj here too. */ ai = adj_nbr_add_or_lock(nh_proto, link, &zero_addr, path->attached_next_hop.fp_interface); } else { ai = adj_nbr_add_or_lock(nh_proto, link, &path->attached_next_hop.fp_nh, path->attached_next_hop.fp_interface); } dpo_set(dpo, DPO_ADJACENCY, vnet_link_to_dpo_proto(link), ai); adj_unlock(ai); return (fib_path_get(fib_path_index)); } static void fib_path_attached_next_hop_set (fib_path_t *path) { dpo_id_t tmp = DPO_INVALID; /* * resolve directly via the adjacency discribed by the * interface and next-hop */ dpo_copy (&tmp, &path->fp_dpo); path = fib_path_attached_next_hop_get_adj(path, dpo_proto_to_link(path->fp_nh_proto), &tmp); dpo_copy(&path->fp_dpo, &tmp); dpo_reset(&tmp); ASSERT(dpo_is_adj(&path->fp_dpo)); /* * become a child of the adjacency so we receive updates * when its rewrite changes */ path->fp_sibling = adj_child_add(path->fp_dpo.dpoi_index, FIB_NODE_TYPE_PATH, fib_path_get_index(path)); if (!vnet_sw_interface_is_up(vnet_get_main(), path->attached_next_hop.fp_interface) || !adj_is_up(path->fp_dpo.dpoi_index)) { path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; } } static void fib_path_attached_get_adj (fib_path_t *path, vnet_link_t link, dpo_id_t *dpo) { fib_protocol_t nh_proto; nh_proto = dpo_proto_to_fib(path->fp_nh_proto); if (vnet_sw_interface_is_p2p(vnet_get_main(), path->attached.fp_interface)) { /* * point-2-point interfaces do not require a glean, since * there is nothing to ARP. Install a rewrite/nbr adj instead */ adj_index_t ai; ai = adj_nbr_add_or_lock(nh_proto, link, &zero_addr, path->attached.fp_interface); dpo_set(dpo, DPO_ADJACENCY, vnet_link_to_dpo_proto(link), ai); adj_unlock(ai); } else if (vnet_sw_interface_is_nbma(vnet_get_main(), path->attached.fp_interface)) { dpo_copy(dpo, drop_dpo_get(path->fp_nh_proto)); } else { adj_index_t ai; ai = adj_glean_add_or_lock(nh_proto, link, path->attached.fp_interface, &path->attached.fp_connected); dpo_set(dpo, DPO_ADJACENCY_GLEAN, vnet_link_to_dpo_proto(link), ai); adj_unlock(ai); } } /* * create of update the paths recursive adj */ static void fib_path_recursive_adj_update (fib_path_t *path, fib_forward_chain_type_t fct, dpo_id_t *dpo) { dpo_id_t via_dpo = DPO_INVALID; /* * get the DPO to resolve through from the via-entry */ fib_entry_contribute_forwarding(path->fp_via_fib, fct, &via_dpo); /* * hope for the best - clear if restrictions apply. */ path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED; /* * Validate any recursion constraints and over-ride the via * adj if not met */ if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RECURSIVE_LOOP) { path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto)); } else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_HOST) { /* * the via FIB must be a host route. * note the via FIB just added will always be a host route * since it is an RR source added host route. So what we need to * check is whether the route has other sources. If it does then * some other source has added it as a host route. If it doesn't * then it was added only here and inherits forwarding from a cover. * the cover is not a host route. * The RR source is the lowest priority source, so we check if it * is the best. if it is there are no other sources. */ if (fib_entry_get_best_source(path->fp_via_fib) >= FIB_SOURCE_RR) { path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto)); /* * PIC edge trigger. let the load-balance maps know */ load_balance_map_path_state_change(fib_path_get_index(path)); } } else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED) { /* * RR source entries inherit the flags from the cover, so * we can check the via directly */ if (!(FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(path->fp_via_fib))) { path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto)); /* * PIC edge trigger. let the load-balance maps know */ load_balance_map_path_state_change(fib_path_get_index(path)); } } /* * check for over-riding factors on the FIB entry itself */ if (!fib_entry_is_resolved(path->fp_via_fib)) { path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto)); /* * PIC edge trigger. let the load-balance maps know */ load_balance_map_path_state_change(fib_path_get_index(path)); } /* * If this path is contributing a drop, then it's not resolved */ if (dpo_is_drop(&via_dpo) || load_balance_is_drop(&via_dpo)) { path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; } /* * update the path's contributed DPO */ dpo_copy(dpo, &via_dpo); FIB_PATH_DBG(path, "recursive update:"); dpo_reset(&via_dpo); } /* * re-evaulate the forwarding state for a via fmask path */ static void fib_path_bier_fmask_update (fib_path_t *path, dpo_id_t *dpo) { bier_fmask_contribute_forwarding(path->bier_fmask.fp_bier_fmask, dpo); /* * if we are stakcing on the drop, then the path is not resolved */ if (dpo_is_drop(dpo)) { path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; } else { path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED; } } /* * fib_path_is_permanent_drop * * Return !0 if the path is configured to permanently drop, * despite other attributes. */ static int fib_path_is_permanent_drop (fib_path_t *path) { return ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DROP) || (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP)); } /* * fib_path_unresolve * * Remove our dependency on the resolution target */ static void fib_path_unresolve (fib_path_t *path) { /* * the forced drop path does not need unresolving */ if (fib_path_is_permanent_drop(path)) { return; } switch (path->fp_type) { case FIB_PATH_TYPE_RECURSIVE: if (FIB_NODE_INDEX_INVALID != path->fp_via_fib) { fib_entry_child_remove(path->fp_via_fib, path->fp_sibling); fib_table_entry_special_remove(path->recursive.fp_tbl_id, fib_entry_get_prefix(path->fp_via_fib), FIB_SOURCE_RR); fib_table_unlock(path->recursive.fp_tbl_id, dpo_proto_to_fib(path->fp_nh_proto), FIB_SOURCE_RR); path->fp_via_fib = FIB_NODE_INDEX_INVALID; } break; case FIB_PATH_TYPE_BIER_FMASK: bier_fmask_child_remove(path->fp_via_bier_fmask, path->fp_sibling); break; case FIB_PATH_TYPE_BIER_IMP: bier_imp_unlock(path->fp_dpo.dpoi_index); break; case FIB_PATH_TYPE_BIER_TABLE: bier_table_ecmp_unlock(path->fp_via_bier_tbl); break; case FIB_PATH_TYPE_ATTACHED_NEXT_HOP: case FIB_PATH_TYPE_ATTACHED: if (dpo_is_adj(&path->fp_dpo)) adj_child_remove(path->fp_dpo.dpoi_index, path->fp_sibling); break; case FIB_PATH_TYPE_UDP_ENCAP: udp_encap_unlock(path->fp_dpo.dpoi_index); break; case FIB_PATH_TYPE_EXCLUSIVE: dpo_reset(&path->exclusive.fp_ex_dpo); break; case FIB_PATH_TYPE_SPECIAL: case FIB_PATH_TYPE_RECEIVE: case FIB_PATH_TYPE_INTF_RX: case FIB_PATH_TYPE_DEAG: case FIB_PATH_TYPE_DVR: /* * these hold only the path's DPO, which is reset below. */ break; } /* * release the adj we were holding and pick up the * drop just in case. */ dpo_reset(&path->fp_dpo); path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; return; } static fib_forward_chain_type_t fib_path_to_chain_type (const fib_path_t *path) { if (DPO_PROTO_MPLS == path->fp_nh_proto) { if (FIB_PATH_TYPE_RECURSIVE == path->fp_type && MPLS_EOS == path->recursive.fp_nh.fp_eos) { return (FIB_FORW_CHAIN_TYPE_MPLS_EOS); } else { return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS); } } else { return (fib_forw_chain_type_from_dpo_proto(path->fp_nh_proto)); } } /* * fib_path_back_walk_notify * * A back walk has reach this path. */ static fib_node_back_walk_rc_t fib_path_back_walk_notify (fib_node_t *node, fib_node_back_walk_ctx_t *ctx) { fib_path_t *path; path = fib_path_from_fib_node(node); FIB_PATH_DBG(path, "bw:%U", format_fib_node_bw_reason, ctx->fnbw_reason); switch (path->fp_type) { case FIB_PATH_TYPE_RECURSIVE: if (FIB_NODE_BW_REASON_FLAG_EVALUATE & ctx->fnbw_reason) { /* * modify the recursive adjacency to use the new forwarding * of the via-fib. * this update is visible to packets in flight in the DP. */ fib_path_recursive_adj_update( path, fib_path_to_chain_type(path), &path->fp_dpo); } if ((FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason) || (FIB_NODE_BW_REASON_FLAG_ADJ_MTU & ctx->fnbw_reason) || (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN & ctx->fnbw_reason)) { /* * ADJ updates (complete<->incomplete) do not need to propagate to * recursive entries. * The only reason its needed as far back as here, is that the adj * and the incomplete adj are a different DPO type, so the LBs need * to re-stack. * If this walk was quashed in the fib_entry, then any non-fib_path * children (like tunnels that collapse out the LB when they stack) * would not see the update. */ return (FIB_NODE_BACK_WALK_CONTINUE); } break; case FIB_PATH_TYPE_BIER_FMASK: if (FIB_NODE_BW_REASON_FLAG_EVALUATE & ctx->fnbw_reason) { /* * update to use the BIER fmask's new forwading */ fib_path_bier_fmask_update(path, &path->fp_dpo); } if ((FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason) || (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN & ctx->fnbw_reason)) { /* * ADJ updates (complete<->incomplete) do not need to propagate to * recursive entries. * The only reason its needed as far back as here, is that the adj * and the incomplete adj are a different DPO type, so the LBs need * to re-stack. * If this walk was quashed in the fib_entry, then any non-fib_path * children (like tunnels that collapse out the LB when they stack) * would not see the update. */ return (FIB_NODE_BACK_WALK_CONTINUE); } break; case FIB_PATH_TYPE_ATTACHED_NEXT_HOP: /* FIXME comment * ADJ_UPDATE backwalk pass silently through here and up to * the path-list when the multipath adj collapse occurs. * The reason we do this is that the assumtption is that VPP * runs in an environment where the Control-Plane is remote * and hence reacts slowly to link up down. In order to remove * this down link from the ECMP set quickly, we back-walk. * VPP also has dedicated CPUs, so we are not stealing resources * from the CP to do so. */ if (FIB_NODE_BW_REASON_FLAG_INTERFACE_UP & ctx->fnbw_reason) { if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED) { /* * alreday resolved. no need to walk back again */ return (FIB_NODE_BACK_WALK_CONTINUE); } path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED; } if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN & ctx->fnbw_reason) { if (!(path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED)) { /* * alreday unresolved. no need to walk back again */ return (FIB_NODE_BACK_WALK_CONTINUE); } path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; } if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE & ctx->fnbw_reason) { /* * The interface this path resolves through has been deleted. * This will leave the path in a permanent drop state. The route * needs to be removed and readded (and hence the path-list deleted) * before it can forward again. */ fib_path_unresolve(path); path->fp_oper_flags |= FIB_PATH_OPER_FLAG_DROP; } if (FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason) { /* * restack the DPO to pick up the correct DPO sub-type */ dpo_id_t tmp = DPO_INVALID; uword if_is_up; if_is_up = vnet_sw_interface_is_up( vnet_get_main(), path->attached_next_hop.fp_interface); dpo_copy (&tmp, &path->fp_dpo); path = fib_path_attached_next_hop_get_adj( path, dpo_proto_to_link(path->fp_nh_proto), &tmp); dpo_copy(&path->fp_dpo, &tmp); dpo_reset(&tmp); path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; if (if_is_up && adj_is_up(path->fp_dpo.dpoi_index)) { path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED; } if (!if_is_up) { /* * If the interface is not up there is no reason to walk * back to children. if we did they would only evalute * that this path is unresolved and hence it would * not contribute the adjacency - so it would be wasted * CPU time. */ return (FIB_NODE_BACK_WALK_CONTINUE); } } if (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN & ctx->fnbw_reason) { if (!(path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED)) { /* * alreday unresolved. no need to walk back again */ return (FIB_NODE_BACK_WALK_CONTINUE); } /* * the adj has gone down. the path is no longer resolved. */ path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; } break; case FIB_PATH_TYPE_ATTACHED: case FIB_PATH_TYPE_DVR: /* * FIXME; this could schedule a lower priority walk, since attached * routes are not usually in ECMP configurations so the backwalk to * the FIB entry does not need to be high priority */ if (FIB_NODE_BW_REASON_FLAG_INTERFACE_UP & ctx->fnbw_reason) { path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED; } if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN & ctx->fnbw_reason) { path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; } if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE & ctx->fnbw_reason) { fib_path_unresolve(path); path->fp_oper_flags |= FIB_PATH_OPER_FLAG_DROP; } break; case FIB_PATH_TYPE_UDP_ENCAP: { dpo_id_t via_dpo = DPO_INVALID; /* * hope for the best - clear if restrictions apply. */ path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED; udp_encap_contribute_forwarding(path->udp_encap.fp_udp_encap_id, path->fp_nh_proto, &via_dpo); /* * If this path is contributing a drop, then it's not resolved */ if (dpo_is_drop(&via_dpo) || load_balance_is_drop(&via_dpo)) { path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED; } /* * update the path's contributed DPO */ dpo_copy(&path->fp_dpo, &via_dpo); dpo_reset(&via_dpo); break; } case FIB_PATH_TYPE_INTF_RX: ASSERT(0); case FIB_PATH_TYPE_DEAG: /* * FIXME When VRF delete is allowed this will need a poke. */ case FIB_PATH_TYPE_SPECIAL: case FIB_PATH_TYPE_RECEIVE: case FIB_PATH_TYPE_EXCLUSIVE: case FIB_PATH_TYPE_BIER_TABLE: case FIB_PATH_TYPE_BIER_IMP: /* * these path types have no parents. so to be * walked from one is unexpected. */ ASSERT(0); break; } /* * propagate the backwalk further to the path-list */ fib_path_list_back_walk(path->fp_pl_index, ctx); return (FIB_NODE_BACK_WALK_CONTINUE); } static void fib_path_memory_show (void) { fib_show_memory_usage("Path", pool_elts(fib_path_pool), pool_len(fib_path_pool), sizeof(fib_path_t)); } /* * The FIB path's graph node virtual function table */ static const fib_node_vft_t fib_path_vft = { .fnv_get = fib_path_get_node, .fnv_last_lock = fib_path_last_lock_gone, .fnv_back_walk = fib_path_back_walk_notify, .fnv_mem_show = fib_path_memory_show, }; static fib_path_cfg_flags_t fib_path_route_flags_to_cfg_flags (const fib_route_path_t *rpath) { fib_path_cfg_flags_t cfg_flags = FIB_PATH_CFG_FLAG_NONE; if (rpath->frp_flags & FIB_ROUTE_PATH_POP_PW_CW) cfg_flags |= FIB_PATH_CFG_FLAG_POP_PW_CW; if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST) cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_HOST; if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED) cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED; if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL) cfg_flags |= FIB_PATH_CFG_FLAG_LOCAL; if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED) cfg_flags |= FIB_PATH_CFG_FLAG_ATTACHED; if (rpath->frp_flags & FIB_ROUTE_PATH_INTF_RX) cfg_flags |= FIB_PATH_CFG_FLAG_INTF_RX; if (rpath->frp_flags & FIB_ROUTE_PATH_RPF_ID) cfg_flags |= FIB_PATH_CFG_FLAG_RPF_ID; if (rpath->frp_flags & FIB_ROUTE_PATH_EXCLUSIVE) cfg_flags |= FIB_PATH_CFG_FLAG_EXCLUSIVE; if (rpath->frp_flags & FIB_ROUTE_PATH_DROP) cfg_flags |= FIB_PATH_CFG_FLAG_DROP; if (rpath->frp_flags & FIB_ROUTE_PATH_SOURCE_LOOKUP) cfg_flags |= FIB_PATH_CFG_FLAG_DEAG_SRC; if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_UNREACH) cfg_flags |= FIB_PATH_CFG_FLAG_ICMP_UNREACH; if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_PROHIBIT) cfg_flags |= FIB_PATH_CFG_FLAG_ICMP_PROHIBIT; if (rpath->frp_flags & FIB_ROUTE_PATH_GLEAN) cfg_flags |= FIB_PATH_CFG_FLAG_GLEAN; return (cfg_flags); } /* * fib_path_create * * Create and initialise a new path object. * return the index of the path. */ fib_node_index_t fib_path_create (fib_node_index_t pl_index, const fib_route_path_t *rpath) { fib_path_t *path; pool_get(fib_path_pool, path); clib_memset(path, 0, sizeof(*path)); fib_node_init(&path->fp_node, FIB_NODE_TYPE_PATH); dpo_reset(&path->fp_dpo); path->fp_pl_index = pl_index; path->fp_nh_proto = rpath->frp_proto; path->fp_via_fib = FIB_NODE_INDEX_INVALID; path->fp_weight = rpath->frp_weight; if (0 == path->fp_weight) { /* * a weight of 0 is a meaningless value. We could either reject it, and thus force * clients to always use 1, or we can accept it and fixup approrpiately. */ path->fp_weight = 1; } path->fp_preference = rpath->frp_preference; path->fp_cfg_flags = fib_path_route_flags_to_cfg_flags(rpath); /* * deduce the path's tpye from the parementers and save what is needed. */ if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_LOCAL) { path->fp_type = FIB_PATH_TYPE_RECEIVE; path->receive.fp_interface = rpath->frp_sw_if_index; path->receive.fp_addr = rpath->frp_addr; } else if (rpath->frp_flags & FIB_ROUTE_PATH_UDP_ENCAP) { path->fp_type = FIB_PATH_TYPE_UDP_ENCAP; path->udp_encap.fp_udp_encap_id = rpath->frp_udp_encap_id; } else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_INTF_RX) { path->fp_type = FIB_PATH_TYPE_INTF_RX; path->intf_rx.fp_interface = rpath->frp_sw_if_index; } else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID) { path->fp_type = FIB_PATH_TYPE_DEAG; path->deag.fp_tbl_id = rpath->frp_fib_index; path->deag.fp_rpf_id = rpath->frp_rpf_id; } else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_FMASK) { path->fp_type = FIB_PATH_TYPE_BIER_FMASK; path->bier_fmask.fp_bier_fmask = rpath->frp_bier_fmask; } else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_IMP) { path->fp_type = FIB_PATH_TYPE_BIER_IMP; path->bier_imp.fp_bier_imp = rpath->frp_bier_imp; } else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_TABLE) { path->fp_type = FIB_PATH_TYPE_BIER_TABLE; path->bier_table.fp_bier_tbl = rpath->frp_bier_tbl; } else if (rpath->frp_flags & FIB_ROUTE_PATH_DEAG) { path->fp_type = FIB_PATH_TYPE_DEAG; path->deag.fp_tbl_id = rpath->frp_fib_index; } else if (rpath->frp_flags & FIB_ROUTE_PATH_DVR) { path->fp_type = FIB_PATH_TYPE_DVR; path->dvr.fp_interface = rpath->frp_sw_if_index; } else if (rpath->frp_flags & FIB_ROUTE_PATH_EXCLUSIVE) { path->fp_type = FIB_PATH_TYPE_EXCLUSIVE; dpo_copy(&path->exclusive.fp_ex_dpo, &rpath->dpo); } else if ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_PROHIBIT) || (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_UNREACH)) { path->fp_type = FIB_PATH_TYPE_SPECIAL; } else if ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_CLASSIFY)) { path->fp_type = FIB_PATH_TYPE_SPECIAL; path->classify.fp_classify_table_id = rpath->frp_classify_table_id; } else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_GLEAN) { path->fp_type = FIB_PATH_TYPE_ATTACHED; path->attached.fp_interface = rpath->frp_sw_if_index; path->attached.fp_connected = rpath->frp_connected; } else if (~0 != rpath->frp_sw_if_index) { if (ip46_address_is_zero(&rpath->frp_addr)) { path->fp_type = FIB_PATH_TYPE_ATTACHED; path->attached.fp_interface = rpath->frp_sw_if_index; } else { path->fp_type = FIB_PATH_TYPE_ATTACHED_NEXT_HOP; path->attached_next_hop.fp_interface = rpath->frp_sw_if_index; path->attached_next_hop.fp_nh = rpath->frp_addr; } } else { if (ip46_address_is_zero(&rpath->frp_addr)) { if (~0 == rpath->frp_fib_index) { path->fp_type = FIB_PATH_TYPE_SPECIAL; } else { path->fp_type = FIB_PATH_TYPE_DEAG; path->deag.fp_tbl_id = rpath->frp_fib_index; path->deag.fp_rpf_id = ~0; } } else { path->fp_type = FIB_PATH_TYPE_RECURSIVE; if (DPO_PROTO_MPLS == path->fp_nh_proto) { path->recursive.fp_nh.fp_local_label = rpath->frp_local_label; path->recursive.fp_nh.fp_eos = rpath->frp_eos; } else { path->recursive.fp_nh.fp_ip = rpath->frp_addr; } path->recursive.fp_tbl_id = rpath->frp_fib_index; } } FIB_PATH_DBG(path, "create"); return (fib_path_get_index(path)); } /* * fib_path_create_special * * Create and initialise a new path object. * return the index of the path. */ fib_node_index_t fib_path_create_special (fib_node_index_t pl_index, dpo_proto_t nh_proto, fib_path_cfg_flags_t flags, const dpo_id_t *dpo) { fib_path_t *path; pool_get(fib_path_pool, path); clib_memset(path, 0, sizeof(*path)); fib_node_init(&path->fp_node, FIB_NODE_TYPE_PATH); dpo_reset(&path->fp_dpo); path->fp_pl_index = pl_index; path->fp_weight = 1; path->fp_preference = 0; path->fp_nh_proto = nh_proto; path->fp_via_fib = FIB_NODE_INDEX_INVALID; path->fp_cfg_flags = flags; if (FIB_PATH_CFG_FLAG_DROP & flags) { path->fp_type = FIB_PATH_TYPE_SPECIAL; } else if (FIB_PATH_CFG_FLAG_LOCAL & flags) { path->fp_type = FIB_PATH_TYPE_RECEIVE; path->attached.fp_interface = FIB_NODE_INDEX_INVALID; } else { path->fp_type = FIB_PATH_TYPE_EXCLUSIVE; ASSERT(NULL != dpo); dpo_copy(&path->exclusive.fp_ex_dpo, dpo); } return (fib_path_get_index(path)); } /* * fib_path_copy * * Copy a path. return index of new path. */ fib_node_index_t fib_path_copy (fib_node_index_t path_index, fib_node_index_t path_list_index) { fib_path_t *path, *orig_path; pool_get(fib_path_pool, path); orig_path = fib_path_get(path_index); ASSERT(NULL != orig_path); clib_memcpy(path, orig_path, sizeof(*path)); FIB_PATH_DBG(path, "create-copy:%d", path_index); /* * reset the dynamic section */ fib_node_init(&path->fp_node, FIB_NODE_TYPE_PATH); path->fp_oper_flags = FIB_PATH_OPER_FLAG_NONE; path->fp_pl_index = path_list_index; path->fp_via_fib = FIB_NODE_INDEX_INVALID; clib_memset(&path->fp_dpo, 0, sizeof(path->fp_dpo)); dpo_reset(&path->fp_dpo); return (fib_path_get_index(path)); } /* * fib_path_destroy * * destroy a path that is no longer required */ void fib_path_destroy (fib_node_index_t path_index) { fib_path_t *path; path = fib_path_get(path_index); ASSERT(NULL != path); FIB_PATH_DBG(path, "destroy"); fib_path_unresolve(path); fib_node_deinit(&path->fp_node); pool_put(fib_path_pool, path); } /* * fib_path_destroy * * destroy a path that is no longer required */ uword fib_path_hash (fib_node_index_t path_index) { fib_path_t *path; path = fib_path_get(path_index); return (hash_memory(STRUCT_MARK_PTR(path, path_hash_start), (STRUCT_OFFSET_OF(fib_path_t, path_hash_end) - STRUCT_OFFSET_OF(fib_path_t, path_hash_start)), 0)); } /* * fib_path_cmp_i * * Compare two paths for equivalence. */ static int fib_path_cmp_i (const fib_path_t *path1, const fib_path_t *path2) { int res; res = 1; /* * paths of different types and protocol are not equal. * different weights and/or preference only are the same path. */ if (path1->fp_type != path2->fp_type) { res = (path1->fp_type - path2->fp_type); } else if (path1->fp_nh_proto != path2->fp_nh_proto) { res = (path1->fp_nh_proto - path2->fp_nh_proto); } else { /* * both paths are of the same type. * consider each type and its attributes in turn. */ switch (path1->fp_type) { case FIB_PATH_TYPE_ATTACHED_NEXT_HOP: res = ip46_address_cmp(&path1->attached_next_hop.fp_nh, &path2->attached_next_hop.fp_nh); if (0 == res) { res = (path1->attached_next_hop.fp_interface - path2->attached_next_hop.fp_interface); } break; case FIB_PATH_TYPE_ATTACHED: res = (path1->attached.fp_interface - path2->attached.fp_interface); break; case FIB_PATH_TYPE_RECURSIVE: res = ip46_address_cmp(&path1->recursive.fp_nh.fp_ip, &path2->recursive.fp_nh.fp_ip); if (0 == res) { res = (path1->recursive.fp_tbl_id - path2->recursive.fp_tbl_id); } break; case FIB_PATH_TYPE_BIER_FMASK: res = (path1->bier_fmask.fp_bier_fmask - path2->bier_fmask.fp_bier_fmask); break; case FIB_PATH_TYPE_BIER_IMP: res = (path1->bier_imp.fp_bier_imp - path2->bier_imp.fp_bier_imp); break; case FIB_PATH_TYPE_BIER_TABLE: res = bier_table_id_cmp(&path1->bier_table.fp_bier_tbl, &path2->bier_table.fp_bier_tbl); break; case FIB_PATH_TYPE_DEAG: res = (path1->deag.fp_tbl_id - path2->deag.fp_tbl_id); if (0 == res) { res = (path1->deag.fp_rpf_id - path2->deag.fp_rpf_id); } break; case FIB_PATH_TYPE_INTF_RX: res = (path1->intf_rx.fp_interface - path2->intf_rx.fp_interface); break; case FIB_PATH_TYPE_UDP_ENCAP: res = (path1->udp_encap.fp_udp_encap_id - path2->udp_encap.fp_udp_encap_id); break; case FIB_PATH_TYPE_DVR: res = (path1->dvr.fp_interface - path2->dvr.fp_interface); break; case FIB_PATH_TYPE_EXCLUSIVE: res = dpo_cmp(&path1->exclusive.fp_ex_dpo, &path2->exclusive.fp_ex_dpo); break; case FIB_PATH_TYPE_SPECIAL: case FIB_PATH_TYPE_RECEIVE: res = 0; break; } } return (res); } /* * fib_path_cmp_for_sort * * Compare two paths for equivalence. Used during path sorting. * As usual 0 means equal. */ int fib_path_cmp_for_sort (void * v1, void * v2) { fib_node_index_t *pi1 = v1, *pi2 = v2; fib_path_t *path1, *path2; path1 = fib_path_get(*pi1); path2 = fib_path_get(*pi2); /* * when sorting paths we want the highest preference paths * first, so that the choices set built is in prefernce order */ if (path1->fp_preference != path2->fp_preference) { return (path1->fp_preference - path2->fp_preference); } return (fib_path_cmp_i(path1, path2)); } /* * fib_path_cmp * * Compare two paths for equivalence. */ int fib_path_cmp (fib_node_index_t pi1, fib_node_index_t pi2) { fib_path_t *path1, *path2; path1 = fib_path_get(pi1); path2 = fib_path_get(pi2); return (fib_path_cmp_i(path1, path2)); } int fib_path_cmp_w_route_path (fib_node_index_t path_index, const fib_route_path_t *rpath) { fib_path_t *path; int res; path = fib_path_get(path_index); res = 1; if (path->fp_weight != rpath->frp_weight) { res = (path->fp_weight - rpath->frp_weight); } else { /* * both paths are of the same type. * consider each type and its attributes in turn. */ switch (path->fp_type) { case FIB_PATH_TYPE_ATTACHED_NEXT_HOP: res = ip46_address_cmp(&path->attached_next_hop.fp_nh, &rpath->frp_addr); if (0 == res) { res = (path->attached_next_hop.fp_interface - rpath->frp_sw_if_index); } break; case FIB_PATH_TYPE_ATTACHED: res = (path->attached.fp_interface - rpath->frp_sw_if_index); break; case FIB_PATH_TYPE_RECURSIVE: if (DPO_PROTO_MPLS == path->fp_nh_proto) { res = path->recursive.fp_nh.fp_local_label - rpath->frp_local_label; if (res == 0) { res = path->recursive.fp_nh.fp_eos - rpath->frp_eos; } } else { res = ip46_address_cmp(&path->recursive.fp_nh.fp_ip, &rpath->frp_addr); } if (0 == res) { res = (path->recursive.fp_tbl_id - rpath->frp_fib_index); } break; case FIB_PATH_TYPE_BIER_FMASK: res = (path->bier_fmask.fp_bier_fmask - rpath->frp_bier_fmask); break; case FIB_PATH_TYPE_BIER_IMP: res = (path->bier_imp.fp_bier_imp - rpath->frp_bier_imp); break; case FIB_PATH_TYPE_BIER_TABLE: res = bier_table_id_cmp(&path->bier_table.fp_bier_tbl, &rpath->frp_bier_tbl); break; case FIB_PATH_TYPE_INTF_RX: res = (path->intf_rx.fp_interface - rpath->frp_sw_if_index); break; case FIB_PATH_TYPE_UDP_ENCAP: res = (path->udp_encap.fp_udp_encap_id - rpath->frp_udp_encap_id); break; case FIB_PATH_TYPE_DEAG: res = (path->deag.fp_tbl_id - rpath->frp_fib_index); if (0 == res) { res = (path->deag.fp_rpf_id - rpath->frp_rpf_id); } break; case FIB_PATH_TYPE_DVR: res = (path->dvr.fp_interface - rpath->frp_sw_if_index); break; case FIB_PATH_TYPE_EXCLUSIVE: res = dpo_cmp(&path->exclusive.fp_ex_dpo, &rpath->dpo); break; case FIB_PATH_TYPE_RECEIVE: if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL) { res = 0; } else { res = 1; } break; case FIB_PATH_TYPE_SPECIAL: res = 0; break; } } return (res); } /* * fib_path_recursive_loop_detect * * A forward walk of the FIB object graph to detect for a cycle/loop. This * walk is initiated when an entry is linking to a new path list or from an old. * The entry vector passed contains all the FIB entrys that are children of this * path (it is all the entries encountered on the walk so far). If this vector * contains the entry this path resolve via, then a loop is about to form. * The loop must be allowed to form, since we need the dependencies in place * so that we can track when the loop breaks. * However, we MUST not produce a loop in the forwarding graph (else packets * would loop around the switch path until the loop breaks), so we mark recursive * paths as looped so that they do not contribute forwarding information. * By marking the path as looped, an etry such as; * X/Y * via a.a.a.a (looped) * via b.b.b.b (not looped) * can still forward using the info provided by b.b.b.b only */ int fib_path_recursive_loop_detect (fib_node_index_t path_index, fib_node_index_t **entry_indicies) { fib_path_t *path; path = fib_path_get(path_index); /* * the forced drop path is never looped, cos it is never resolved. */ if (fib_path_is_permanent_drop(path)) { return (0
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.2" width="136.48mm" height="110.15mm" viewBox="1086 1124 13648 11015" preserveAspectRatio="xMidYMid" fill-rule="evenodd" stroke-width="28.222" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" xmlns:ooo="http://xml.openoffice.org/svg/export" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:presentation="http://sun.com/xmlns/staroffice/presentation" xmlns:smil="http://www.w3.org/2001/SMIL20/" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xml:space="preserve">
 <defs class="ClipPathGroup">
  <clipPath id="presentation_clip_path" clipPathUnits="userSpaceOnUse">
   <rect x="1086" y="1124" width="13648" height="11015"/>
  </clipPath>
  <clipPath id="presentation_clip_path_shrink" clipPathUnits="userSpaceOnUse">
   <rect x="1099" y="1135" width="13621" height="10993"/>
  </clipPath>
 </defs>
 <defs>
  <font id="EmbeddedFont_1" horiz-adv-x="2048">
   <font-face font-family="Calibri embedded" units-per-em="2048" font-weight="normal" font-style="normal" ascent="1953" descent="553"/>
   <missing-glyph horiz-adv-x="2048" d="M 0,0 L 2047,0 2047,2047 0,2047 0,0 Z"/>
   <glyph unicode="…" horiz-adv-x="1142" d="M 361,108 C 361,61 353,30 338,15 322,-1 294,-9 254,-9 215,-9 188,-1 173,14 158,29 150,60 150,105 150,152 158,183 174,199 189,214 217,222 257,222 296,222 323,214 338,199 353,184 361,153 361,108 Z M 812,108 C 812,61 804,30 789,15 774,-1 746,-9 706,-9 667,-9 640,-1 625,14 610,29 602,60 602,105 602,152 610,183 626,199 641,214 669,222 708,222 747,222 775,214 790,199 805,184 812,153 812,108 Z M 1264,108 C 1264,61 1256,30 1241,15 1225,-1 1197,-9 1157,-9 1118,-9 1091,-1 1076,14 1061,29 1053,60 1053,105 1053,152 1061,183 1077,199 1092,214 1120,222 1160,222 1199,222 1226,214 1241,199 1256,184 1264,153 1264,108 Z"/>
   <glyph unicode="z" horiz-adv-x="658" d="M 727,70 C 727,57 726,47 724,38 722,29 720,21 717,16 714,10 711,6 706,4 701,1 696,0 691,0 L 137,0 C 123,0 112,5 103,14 94,23 89,39 89,61 L 89,95 C 89,104 90,113 91,120 92,127 94,135 97,142 100,149 103,157 108,166 113,174 118,183 125,194 L 522,812 137,812 C 126,812 118,818 112,829 105,840 102,857 102,882 102,894 103,905 104,914 105,923 108,930 111,936 114,941 117,945 122,948 126,950 131,951 137,951 L 653,951 C 660,951 667,950 673,948 678,946 683,943 687,938 691,933 694,927 697,920 699,913 700,903 700,892 L 700,860 C 700,851 699,842 698,834 697,826 695,818 692,811 689,803 686,795 681,786 676,777 671,768 664,757 L 269,139 691,139 C 696,139 701,138 706,136 710,133 714,129 717,124 720,119 722,112 724,103 726,94 727,83 727,70 Z"/>
   <glyph unicode="t" horiz-adv-x="606" d="M 621,91 C 621,72 620,56 617,45 614,34 610,25 605,20 600,15 592,10 581,5 570,0 558,-4 545,-7 531,-10 516,-12 501,-14 486,-16 470,-17 455,-17 408,-17 368,-11 335,2 302,14 274,33 253,58 232,83 216,114 207,153 197,191 192,236 192,288 L 192,814 66,814 C 56,814 48,819 42,830 36,841 33,858 33,882 33,895 34,905 36,914 37,923 39,930 42,936 45,941 48,945 53,948 57,950 62,951 67,951 L 192,951 192,1165 C 192,1170 193,1174 196,1178 198,1182 202,1186 209,1189 215,1192 223,1194 234,1195 245,1196 258,1197 274,1197 291,1197 304,1196 315,1195 326,1194 334,1192 340,1189 346,1186 350,1182 353,1178 356,1174 357,1170 357,1165 L 357,951 588,951 C 593,951 598,950 602,948 606,945 610,941 613,936 616,930 618,923 619,914 620,905 621,895 621,882 621,858 618,841 612,830 606,819 598,814 588,814 L 357,814 357,312 C 357,250 366,203 385,172 403,140 436,124 483,124 498,124 512,126 524,129 536,132 547,135 556,138 565,141 573,145 580,148 587,151 593,152 598,152 601,152 605,151 608,150 611,148 613,145 615,140 616,135 618,129 619,121 620,113 621,103 621,91 Z"/>
   <glyph unicode="s" horiz-adv-x="658" d="M 718,270 C 718,224 710,183 693,147 676,111 651,81 620,56 589,31 551,13 508,0 465,-13 417,-19 365,-19 333,-19 303,-17 274,-12 245,-7 219,0 196,8 173,15 153,23 137,32 121,40 109,47 102,54 95,61 89,70 86,82 83,94 81,110 81,131 81,144 82,154 83,163 84,172 86,179 88,184 90,189 93,193 97,196 100,198 104,199 109,199 116,199 127,195 142,186 156,177 174,167 195,156 216,145 240,136 269,127 298,118 331,113 368,113 396,113 421,116 444,122 467,128 486,137 503,149 520,160 533,175 542,193 551,211 555,232 555,257 555,282 549,304 536,321 523,338 505,354 484,367 463,380 439,392 412,403 385,413 358,424 330,435 301,446 274,459 247,474 220,488 195,505 174,526 153,547 136,571 123,600 110,629 103,663 103,703 103,738 110,772 124,805 137,837 158,865 185,890 212,914 247,933 288,948 329,963 376,970 431,970 455,970 479,968 503,964 527,960 549,955 568,949 587,943 604,937 618,930 631,923 642,916 649,911 656,906 660,901 663,897 665,893 667,889 668,884 669,879 670,872 671,865 672,858 672,849 672,838 672,827 672,817 671,809 670,800 668,793 666,788 663,783 660,779 657,777 654,774 650,773 646,773 640,773 631,777 620,784 609,791 594,799 576,808 558,816 537,824 513,831 488,838 460,842 429,842 401,842 376,839 355,833 334,826 316,817 303,806 289,794 279,780 272,764 265,748 261,731 261,712 261,686 268,664 281,647 294,629 312,613 333,600 354,587 379,575 406,564 433,553 461,542 490,531 518,520 546,507 574,493 601,479 626,462 647,442 668,422 686,398 699,370 712,342 718,309 718,270 Z"/>
   <glyph unicode="r" horiz-adv-x="554" d="M 679,866 C 679,851 679,839 678,829 677,819 676,811 674,806 672,800 670,796 667,793 664,790 659,788 654,788 649,788 642,790 635,793 627,796 618,799 609,802 599,805 588,807 576,810 564,813 551,814 537,814 520,814 504,811 488,804 472,797 455,786 438,771 420,756 401,735 382,710 363,685 341,654 318,617 L 318,25 C 318,20 317,15 314,12 311,8 307,5 301,2 295,-1 287,-3 276,-4 265,-5 252,-6 235,-6 219,-6 206,-5 195,-4 184,-3 176,-1 170,2 163,5 159,8 157,12 154,15 153,20 153,25 L 153,925 C 153,930 154,935 156,939 158,942 162,946 168,949 174,952 182,954 191,955 200,956 213,956 228,956 243,956 255,956 265,955 274,954 282,952 287,949 292,946 296,942 299,939 301,935 302,930 302,925 L 302,794 C 327,830 350,859 372,882 393,905 414,923 433,936 452,949 472,958 491,963 510,968 529,970 548,970 557,970 567,970 578,969 589,968 600,966 612,963 624,960 635,957 645,954 654,951 661,947 665,944 669,941 672,938 673,935 674,932 676,928 677,923 678,918 678,912 679,903 679,894 679,881 679,866 Z"/>
   <glyph unicode="p" horiz-adv-x="848" d="M 981,489 C 981,410 973,340 956,277 939,214 914,161 881,118 848,74 807,40 758,17 709,-7 654,-19 591,-19 564,-19 540,-16 517,-11 494,-6 472,3 451,14 429,25 407,40 386,57 365,74 342,95 318,118 L 318,-332 C 318,-337 317,-342 314,-346 311,-350 307,-353 301,-356 295,-359 287,-361 276,-362 265,-363 252,-364 235,-364 219,-364 206,-363 195,-362 184,-361 176,-359 170,-356 163,-353 159,-350 157,-346 154,-342 153,-337 153,-332 L 153,925 C 153,931 154,936 156,940 158,943 162,946 168,949 174,952 182,954 191,955 200,956 212,956 225,956 239,956 251,956 260,955 269,954 276,952 282,949 288,946 292,943 295,940 297,936 298,931 298,925 L 298,804 C 325,832 352,856 377,877 402,898 428,915 454,929 479,942 506,953 533,960 560,967 588,970 618,970 683,970 739,957 785,932 831,907 869,872 898,828 927,784 948,733 961,675 974,616 981,554 981,489 Z M 807,470 C 807,516 804,561 797,604 790,647 778,685 761,718 744,751 721,778 692,798 663,818 628,828 585,828 564,828 543,825 522,819 501,812 480,802 459,789 438,775 415,757 392,735 369,712 344,685 318,652 L 318,294 C 363,239 406,196 447,167 488,138 530,123 575,123 616,123 652,133 682,153 711,173 735,200 754,233 772,266 785,304 794,345 803,386 807,428 807,470 Z"/>
   <glyph unicode="o" horiz-adv-x="917" d="M 990,485 C 990,412 980,344 961,283 942,221 913,168 875,123 836,78 788,44 731,19 673,-7 606,-19 530,-19 456,-19 392,-8 337,14 282,36 236,68 199,110 162,152 135,203 117,263 99,323 90,391 90,467 90,540 100,608 119,670 138,731 166,784 205,829 243,874 291,908 348,933 405,958 472,970 549,970 623,970 688,959 743,937 798,915 843,883 880,841 917,799 944,748 963,688 981,628 990,560 990,485 Z M 816,474 C 816,523 812,569 803,612 794,655 779,693 758,726 737,759 709,785 674,804 639,823 595,832 542,832 493,832 452,823 417,806 382,789 353,764 330,733 307,701 291,663 280,620 269,577 263,529 263,478 263,429 268,382 277,339 286,296 301,258 322,226 343,193 371,168 406,149 441,130 485,120 538,120 586,120 628,129 663,146 698,163 727,188 750,219 773,250 789,288 800,331 811,374 816,422 816,474 Z"/>
   <glyph unicode="n" horiz-adv-x="796" d="M 928,25 C 928,20 927,15 924,12 921,8 917,5 911,2 905,-1 897,-3 886,-4 875,-5 862,-6 846,-6 829,-6 816,-5 805,-4 794,-3 786,-1 780,2 774,5 770,8 767,12 764,15 763,20 763,25 L 763,552 C 763,603 759,645 751,676 743,707 731,734 716,757 701,780 681,797 657,809 632,821 604,827 572,827 531,827 489,812 448,783 407,754 363,711 318,654 L 318,25 C 318,20 317,15 314,12 311,8 307,5 301,2 295,-1 287,-3 276,-4 265,-5 252,-6 235,-6 219,-6 206,-5 195,-4 184,-3 176,-1 170,2 163,5 159,8 157,12 154,15 153,20 153,25 L 153,925 C 153,930 154,935 156,939 158,942 162,946 168,949 174,952 182,954 191,955 200,956 213,956 228,956 243,956 255,956 265,955 274,954 282,952 287,949 292,946 296,942 299,939 301,935 302,930 302,925 L 302,806 C 353,863 403,904 454,931 504,957 555,970 606,970 666,970 717,960 758,940 799,919 832,892 857,858 882,824 901,784 912,739 923,693 928,638 928,574 Z"/>
   <glyph unicode="l" horiz-adv-x="191" d="M 318,25 C 318,20 317,15 314,12 311,8 307,5 301,2 295,-1 287,-3 276,-4 265,-5 252,-6 235,-6 219,-6 206,-5 195,-4 184,-3 176,-1 170,2 163,5 159,8 157,12 154,15 153,20 153,25 L 153,1361 C 153,1366 154,1371 157,1375 159,1379 163,1382 170,1385 176,1388 184,1390 195,1391 206,1392 219,1393 235,1393 252,1393 265,1392 276,1391 287,1390 295,1388 301,1385 307,1382 311,1379 314,1375 317,1371 318,1366 318,1361 Z"/>
   <glyph unicode="i" horiz-adv-x="226" d="M 318,25 C 318,20 317,15 314,12 311,8 307,5 301,2 295,-1 287,-3 276,-4 265,-5 252,-6 235,-6 219,-6 206,-5 195,-4 184,-3 176,-1 170,2 163,5 159,8 157,12 154,15 153,20 153,25 L 153,925 C 153,930 154,934 157,938 159,942 163,945 170,948 176,951 184,953 195,954 206,955 219,956 235,956 252,956 265,955 276,954 287,953 295,951 301,948 307,945 311,942 314,938 317,934 318,930 318,925 Z M 337,1229 C 337,1190 330,1164 315,1150 300,1136 273,1129 234,1129 195,1129 169,1136 155,1150 140,1163 133,1189 133,1227 133,1266 140,1292 155,1306 170,1320 197,1327 236,1327 275,1327 301,1320 316,1307 330,1293 337,1267 337,1229 Z"/>
   <glyph unicode="g" horiz-adv-x="865" d="M 905,884 C 905,861 902,844 896,834 889,823 881,818 871,818 L 742,818 C 765,794 782,768 791,739 800,710 805,679 805,648 805,596 797,550 780,510 763,470 740,436 709,409 678,381 641,360 598,345 555,330 508,323 456,323 419,323 385,328 352,338 319,347 293,359 275,374 263,362 253,348 246,333 238,318 234,300 234,280 234,257 245,237 267,222 288,207 317,198 353,197 L 588,187 C 633,186 674,180 711,169 748,158 781,142 808,122 835,101 857,76 872,47 887,17 895,-18 895,-57 895,-98 886,-138 869,-175 852,-212 825,-245 790,-274 754,-302 708,-324 653,-341 598,-357 532,-365 457,-365 384,-365 323,-359 272,-347 221,-334 179,-317 146,-296 113,-275 90,-249 75,-220 60,-190 53,-158 53,-123 53,-101 56,-80 61,-59 66,-38 75,-19 86,0 97,19 110,37 127,54 143,71 162,87 183,104 150,121 126,142 111,167 95,192 87,220 87,249 87,290 95,326 112,358 129,390 149,419 174,444 153,469 137,497 125,528 113,559 107,596 107,640 107,691 116,737 133,778 150,819 174,853 205,881 236,909 273,931 316,946 359,961 405,968 456,968 483,968 509,967 533,964 556,961 578,956 599,951 L 871,951 C 882,951 891,946 897,935 902,924 905,907 905,884 Z M 647,647 C 647,708 630,756 597,791 563,825 515,842 453,842 421,842 393,837 370,826 346,815 326,801 311,782 295,763 283,742 276,718 268,693 264,668 264,641 264,582 281,535 315,501 348,467 395,450 456,450 489,450 517,455 541,466 565,476 585,490 601,509 616,527 628,548 636,572 643,596 647,621 647,647 Z M 730,-66 C 730,-27 714,3 683,24 651,45 608,56 554,57 L 321,65 C 300,48 282,33 269,18 255,3 244,-12 236,-26 228,-39 223,-53 220,-66 217,-79 215,-93 215,-107 215,-150 237,-183 281,-206 325,-228 386,-239 465,-239 515,-239 557,-234 591,-225 624,-215 651,-202 672,-186 693,-170 708,-152 717,-131 726,-110 730,-89 730,-66 Z"/>
   <glyph unicode="e" horiz-adv-x="848" d="M 921,514 C 921,488 915,470 902,459 889,448 874,442 857,442 L 267,442 C 267,392 272,347 282,307 292,267 309,233 332,204 355,175 386,153 423,138 460,123 506,115 560,115 603,115 641,119 674,126 707,133 736,140 761,149 785,158 805,166 821,173 836,180 848,183 856,183 861,183 865,182 869,180 872,177 875,174 877,169 879,164 881,158 882,150 883,141 883,131 883,119 883,110 883,103 882,97 881,90 881,85 880,80 879,75 877,70 875,66 872,62 869,58 866,55 862,51 851,45 833,37 815,28 792,20 763,12 734,4 701,-3 664,-10 626,-16 586,-19 543,-19 469,-19 404,-9 349,12 293,33 246,63 208,104 170,145 141,196 122,257 103,318 93,390 93,471 93,548 103,618 123,680 143,741 172,794 210,837 247,880 293,913 346,936 399,959 459,970 525,970 596,970 656,959 706,936 755,913 796,883 828,845 860,806 884,761 899,710 914,658 921,603 921,544 Z M 755,563 C 757,650 738,718 698,767 657,816 597,841 518,841 477,841 442,833 411,818 380,803 355,782 334,757 313,732 297,702 286,669 275,635 268,600 267,563 Z"/>
   <glyph unicode="d" horiz-adv-x="848" d="M 924,25 C 924,20 923,15 921,11 918,7 914,4 909,2 903,-1 895,-3 886,-4 877,-5 865,-6 852,-6 838,-6 826,-5 817,-4 808,-3 800,-1 794,2 788,4 784,7 781,11 778,15 777,20 777,25 L 777,144 C 730,93 681,53 630,24 579,-5 523,-19 462,-19 396,-19 340,-6 293,20 246,45 209,80 180,124 151,167 129,219 116,278 103,337 96,399 96,464 96,541 104,611 121,674 138,736 162,789 195,833 228,877 268,911 317,935 365,958 421,970 484,970 537,970 585,959 629,936 672,913 715,879 758,834 L 758,1357 C 758,1362 759,1366 762,1371 764,1375 768,1378 775,1381 782,1383 790,1385 801,1387 811,1388 824,1389 840,1389 857,1389 870,1388 881,1387 892,1385 900,1383 906,1381 912,1378 917,1375 920,1371 923,1366 924,1362 924,1357 Z M 758,658 C 713,713 670,756 629,785 587,814 543,828 498,828 456,828 420,818 391,798 362,778 338,752 320,719 301,686 288,649 280,608 271,567 267,525 267,482 267,437 271,392 278,349 285,306 297,267 314,234 331,200 354,173 383,153 412,132 448,122 491,122 513,122 534,125 555,131 575,137 596,147 617,161 638,175 661,193 684,216 707,238 732,265 758,298 Z"/>
   <glyph unicode="a" horiz-adv-x="762" d="M 831,24 C 831,16 828,10 823,6 818,2 810,-1 801,-3 792,-5 778,-6 760,-6 743,-6 729,-5 719,-3 708,-1 701,2 696,6 691,10 689,16 689,24 L 689,114 C 650,72 606,39 558,16 509,-7 458,-19 404,-19 357,-19 314,-13 276,-1 237,12 205,30 178,53 151,76 130,105 115,139 100,173 92,212 92,255 92,306 102,350 123,387 144,424 173,455 212,480 251,505 298,523 354,536 410,548 473,554 543,554 L 667,554 667,624 C 667,659 663,689 656,716 649,743 637,765 621,783 604,800 583,814 557,823 531,832 499,836 461,836 420,836 384,831 352,822 319,812 291,801 267,790 242,778 222,767 206,758 189,748 177,743 169,743 164,743 159,744 155,747 151,750 148,754 145,759 142,764 139,771 138,780 137,788 136,797 136,807 136,824 137,837 140,847 142,856 148,865 157,874 166,883 181,893 203,905 225,916 250,927 279,937 308,946 339,954 373,961 407,967 441,970 476,970 541,970 596,963 641,948 686,933 723,912 751,884 779,855 799,820 812,778 825,736 831,687 831,631 Z M 667,435 L 526,435 C 481,435 441,431 408,424 375,416 347,405 325,390 303,375 287,357 277,336 266,315 261,290 261,263 261,216 276,179 306,152 335,124 377,110 430,110 473,110 514,121 551,143 588,165 626,199 667,244 Z"/>
   <glyph unicode="T" horiz-adv-x="986" d="M 983,1220 C 983,1207 982,1196 981,1187 980,1178 978,1170 975,1165 972,1159 968,1155 964,1152 959,1149 954,1148 949,1148 L 585,1148 585,26 C 585,21 584,16 581,12 578,8 574,5 567,3 560,0 552,-2 541,-4 530,-5 516,-6 499,-6 483,-6 469,-5 458,-4 447,-2 438,0 431,3 424,5 420,8 417,12 414,16 413,21 413,26 L 413,1148 49,1148 C 44,1148 39,1149 35,1152 30,1155 27,1159 24,1165 21,1170 19,1178 18,1187 16,1196 15,1207 15,1220 15,1233 16,1244 18,1254 19,1263 21,1271 24,1277 27,1283 30,1287 35,1290 39,1293 44,1294 49,1294 L 949,1294 C 954,1294 959,1293 964,1290 968,1287 972,1283 975,1277 978,1271 980,1263 981,1254 982,1244 983,1233 983,1220 Z"/>
   <glyph unicode="N" horiz-adv-x="1003" d="M 1150,71 C 1150,58 1148,46 1144,37 1139,28 1134,20 1127,14 1120,8 1112,4 1103,1 1094,-2 1086,-3 1077,-3 L 1022,-3 C 1005,-3 990,-1 977,3 964,6 951,13 940,23 928,32 916,45 905,62 893,79 880,100 866,126 L 458,862 C 437,900 415,940 394,982 372,1023 352,1064 333,1103 L 331,1103 C 332,1055 333,1006 334,956 335,906 335,856 335,807 L 335,26 C 335,21 334,17 331,13 328,8 324,5 318,3 311,0 303,-2 293,-4 282,-5 269,-6 253,-6 237,-6 224,-5 214,-4 203,-2 195,0 189,3 183,5 179,8 176,13 173,17 172,21 172,26 L 172,1220 C 172,1247 179,1266 194,1277 209,1288 225,1294 242,1294 L 324,1294 C 343,1294 360,1292 373,1289 386,1286 397,1280 408,1273 418,1265 428,1254 438,1241 447,1227 458,1210 469,1189 L 783,621 C 802,586 821,553 839,520 857,487 874,454 891,422 908,390 924,359 941,328 957,297 973,265 989,234 L 990,234 C 989,287 988,342 988,399 987,456 987,510 987,563 L 987,1265 C 987,1270 988,1274 991,1278 994,1282 998,1286 1005,1289 1011,1292 1019,1294 1030,1295 1040,1296 1053,1297 1070,1297 1085,1297 1097,1296 1108,1295 1119,1294 1127,1292 1133,1289 1139,1286 1143,1282 1146,1278 1149,1274 1150,1270 1150,1265 Z"/>
   <glyph unicode="C" horiz-adv-x="952" d="M 1036,183 C 1036,172 1036,163 1035,155 1034,147 1033,140 1032,134 1030,128 1028,123 1025,118 1022,113 1018,108 1011,101 1004,94 990,84 969,71 948,57 921,44 890,31 858,18 822,7 781,-3 740,-12 695,-16 646,-16 562,-16 486,-2 419,26 351,54 293,95 246,150 198,205 161,272 136,353 110,433 97,525 97,630 97,737 111,833 139,917 166,1001 205,1072 255,1131 305,1189 365,1233 435,1264 504,1295 581,1310 666,1310 703,1310 740,1307 775,1300 810,1293 843,1284 873,1273 903,1262 930,1250 953,1236 976,1222 993,1211 1002,1202 1011,1193 1016,1186 1019,1181 1022,1176 1024,1171 1026,1165 1027,1158 1029,1151 1030,1142 1031,1133 1031,1123 1031,1111 1031,1098 1030,1086 1029,1077 1028,1068 1026,1060 1023,1054 1020,1047 1017,1043 1014,1040 1010,1037 1005,1035 1000,1035 991,1035 978,1042 961,1055 944,1068 923,1082 897,1098 870,1113 838,1128 801,1141 763,1154 718,1160 665,1160 608,1160 556,1149 509,1126 462,1103 421,1069 388,1024 355,979 329,925 311,861 292,796 283,723 283,640 283,558 292,486 310,423 327,360 353,307 386,265 419,222 459,190 507,169 555,147 609,136 670,136 721,136 766,142 805,155 843,168 876,182 903,198 930,213 952,227 969,240 986,253 1000,259 1010,259 1015,259 1019,258 1022,256 1025,254 1028,250 1030,245 1032,239 1034,231 1035,221 1036,211 1036,198 1036,183 Z"/>
   <glyph unicode="2" horiz-adv-x="830" d="M 924,74 C 924,62 923,51 922,42 920,33 918,25 915,19 912,12 908,8 903,5 898,2 892,0 886,0 L 171,0 C 162,0 154,1 147,4 140,6 134,10 129,15 124,20 120,28 118,38 115,48 114,60 114,75 114,88 115,100 116,110 117,120 119,129 122,137 125,144 130,152 135,160 140,167 146,175 154,184 L 405,450 C 463,511 510,566 545,615 580,664 607,708 626,748 645,788 657,824 663,857 669,890 672,920 672,949 672,978 667,1005 658,1031 649,1056 635,1079 618,1098 600,1117 578,1133 551,1144 524,1155 494,1161 459,1161 418,1161 382,1155 350,1144 317,1133 289,1120 265,1107 240,1094 220,1081 204,1070 187,1059 175,1053 167,1053 162,1053 158,1054 155,1057 151,1060 148,1064 146,1070 143,1076 141,1084 140,1094 139,1104 138,1116 138,1130 138,1140 138,1149 139,1156 140,1163 141,1170 143,1175 144,1180 146,1185 149,1190 152,1195 157,1201 165,1208 173,1215 187,1224 207,1236 226,1248 251,1260 281,1272 310,1283 343,1293 379,1301 414,1309 452,1313 491,1313 554,1313 609,1304 656,1287 703,1269 742,1245 773,1214 804,1183 827,1148 842,1107 857,1066 865,1023 865,977 865,936 861,895 854,854 847,813 831,768 808,721 784,673 750,620 705,562 660,503 601,436 527,360 L 322,146 885,146 C 890,146 896,145 901,142 906,139 910,134 914,128 917,122 920,115 922,106 923,97 924,86 924,74 Z"/>
   <glyph unicode="-" horiz-adv-x="519" d="M 558,505 C 558,479 555,461 549,451 543,441 534,436 523,436 L 105,436 C 93,436 84,441 78,452 72,462 69,480 69,505 69,530 72,548 78,558 84,568 93,573 105,573 L 523,573 C 528,573 533,572 538,570 542,568 546,564 549,559 552,553 554,546 556,537 557,528 558,518 558,505 Z"/>
   <glyph unicode=" " horiz-adv-x="467"/>
  </font>
 </defs>
 <defs>
  <font id="EmbeddedFont_2" horiz-adv-x="2048">
   <font-face font-family="Calibri embedded" units-per-em="2048" font-weight="bold" font-style="normal" ascent="1953" descent="553"/>
   <missing-glyph horiz-adv-x="2048" d="M 0,0 L 2047,0 2047,2047 0,2047 0,0 Z"/>
   <glyph unicode="x" horiz-adv-x="900" d="M 901,52 C 906,41 909,31 909,24 908,17 903,11 894,6 885,1 870,-2 851,-4 832,-5 806,-6 774,-6 744,-6 720,-6 702,-5 683,-4 669,-2 659,2 648,5 641,8 636,13 631,17 627,22 624,29 L 459,346 294,29 C 291,22 288,17 283,13 278,8 271,5 262,2 252,-2 238,-4 221,-5 204,-6 181,-6 153,-6 124,-6 100,-5 83,-4 66,-2 53,1 45,6 37,11 33,17 33,24 32,31 35,41 41,52 L 288,491 60,903 C 54,915 51,925 51,934 50,942 54,948 63,953 72,958 86,961 105,963 124,965 149,966 182,966 211,966 235,966 253,965 270,964 284,962 294,960 304,958 311,955 316,951 321,946 325,941 328,934 L 487,636 645,934 C 647,939 650,944 654,948 658,952 664,955 673,958 682,961 694,963 709,964 724,965 744,966 770,966 799,966 823,965 841,964 858,963 871,960 879,955 886,950 890,944 890,936 889,927 885,916 878,903 L 656,498 Z"/>
   <glyph unicode="v" horiz-adv-x="934" d="M 947,927 C 947,924 947,920 947,915 946,910 946,905 945,900 944,894 942,887 941,880 939,873 937,864 934,855 L 666,48 C 663,37 658,28 653,21 647,14 638,8 625,4 612,0 594,-3 572,-4 549,-5 520,-6 484,-6 449,-6 420,-5 398,-4 375,-2 358,1 345,5 332,9 323,15 318,22 312,29 307,37 304,48 L 36,855 C 32,868 29,880 27,891 24,902 23,909 23,914 22,919 22,923 22,927 22,934 24,940 28,945 31,950 38,954 47,957 56,960 69,963 86,964 102,965 122,966 147,966 174,966 196,965 213,964 230,962 243,960 253,957 262,954 269,949 273,944 277,938 280,931 283,923 L 486,268 492,243 498,268 698,923 C 700,931 703,938 708,944 712,949 719,954 728,957 737,960 750,962 766,964 781,965 802,966 827,966 852,966 872,965 888,964 903,963 915,960 924,957 933,954 939,950 942,945 945,940 947,934 947,927 Z"/>
   <glyph unicode="u" horiz-adv-x="865" d="M 972,34 C 972,27 970,22 967,17 964,12 958,7 950,4 941,1 930,-2 917,-4 903,-5 886,-6 865,-6 843,-6 825,-5 812,-4 798,-2 787,1 779,4 771,7 765,12 762,17 759,22 757,27 757,34 L 757,137 C 708,84 658,44 607,17 556,-10 503,-23 448,-23 387,-23 335,-13 294,7 252,27 218,54 193,89 167,124 149,164 138,210 127,255 121,312 121,380 L 121,926 C 121,933 123,939 127,944 130,949 137,953 147,956 156,959 169,962 186,964 202,965 222,966 246,966 271,966 291,965 307,964 323,962 336,959 346,956 355,953 362,949 366,944 370,939 372,933 372,926 L 372,422 C 372,375 375,340 381,315 387,290 396,269 409,252 421,234 437,220 456,211 475,201 497,196 522,196 554,196 586,208 619,231 651,254 685,288 722,333 L 722,926 C 722,933 724,939 728,944 731,949 738,953 748,956 757,959 770,962 786,964 802,965 822,966 847,966 872,966 892,965 908,964 924,962 937,959 946,956 955,953 962,949 966,944 970,939 972,933 972,926 Z"/>
   <glyph unicode="t" horiz-adv-x="641" d="M 654,122 C 654,93 652,70 649,55 645,39 640,28 634,22