diff options
Diffstat (limited to 'isisd/isis_circuit.c')
| -rw-r--r-- | isisd/isis_circuit.c | 223 |
1 files changed, 79 insertions, 144 deletions
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index a637429e84..7fd9c07ed2 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -73,61 +73,42 @@ DEFINE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp)); int isis_if_new_hook(struct interface *); int isis_if_delete_hook(struct interface *); -static int isis_circuit_smmp_id_gen(struct isis_circuit *circuit) -{ - struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); - struct isis *isis = NULL; - uint32_t id; - uint32_t i; - - isis = isis_lookup_by_vrfid(vrf->vrf_id); - if (isis == NULL) - return 0; - - id = isis->snmp_circuit_id_last; - id++; +DEFINE_HOOK(isis_circuit_new_hook, (struct isis_circuit *circuit), (circuit)); +DEFINE_HOOK(isis_circuit_del_hook, (struct isis_circuit *circuit), (circuit)); - /* find next unused entry */ - for (i = 0; i < SNMP_CIRCUITS_MAX; i++) { - if (id >= SNMP_CIRCUITS_MAX) { - id = 0; - continue; - } - - if (id == 0) - continue; +static void isis_circuit_enable(struct isis_circuit *circuit) +{ + struct isis_area *area; + struct interface *ifp = circuit->interface; - if (isis->snmp_circuits[id] == NULL) - break; + area = isis_area_lookup(circuit->tag, ifp->vrf_id); + if (area) + isis_area_add_circuit(area, circuit); - id++; - } + if (if_is_operative(ifp)) + isis_csm_state_change(IF_UP_FROM_Z, circuit, ifp); +} - if (i == SNMP_CIRCUITS_MAX) { - zlog_warn("Could not allocate a smmp-circuit-id"); - return 0; - } +static void isis_circuit_disable(struct isis_circuit *circuit) +{ + struct isis_area *area = circuit->area; + struct interface *ifp = circuit->interface; - isis->snmp_circuits[id] = circuit; - isis->snmp_circuit_id_last = id; - circuit->snmp_id = id; + if (if_is_operative(ifp)) + isis_csm_state_change(IF_DOWN_FROM_Z, circuit, ifp); - return 1; + if (area) + isis_area_del_circuit(area, circuit); } -struct isis_circuit *isis_circuit_new(struct isis *isis) +struct isis_circuit *isis_circuit_new(struct interface *ifp, const char *tag) { struct isis_circuit *circuit; int i; circuit = XCALLOC(MTYPE_ISIS_CIRCUIT, sizeof(struct isis_circuit)); - circuit->isis = isis; - /* - * Note: if snmp-id generation failed circuit will fail - * up operation - */ - isis_circuit_smmp_id_gen(circuit); + circuit->tag = XSTRDUP(MTYPE_ISIS_CIRCUIT, tag); /* * Default values @@ -193,31 +174,39 @@ struct isis_circuit *isis_circuit_new(struct isis *isis) isis_lfa_excluded_ifaces_init(circuit, ISIS_LEVEL1); isis_lfa_excluded_ifaces_init(circuit, ISIS_LEVEL2); + circuit->ldp_sync_info = ldp_sync_info_create(); + circuit->ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED; + QOBJ_REG(circuit, isis_circuit); + isis_circuit_if_bind(circuit, ifp); + + if (ifp->ifindex != IFINDEX_INTERNAL) + isis_circuit_enable(circuit); + return circuit; } void isis_circuit_del(struct isis_circuit *circuit) { - struct isis *isis = NULL; - if (!circuit) return; - QOBJ_UNREG(circuit); - - if (circuit->interface) { - isis = isis_lookup_by_vrfid(circuit->interface->vrf_id); - isis->snmp_circuits[circuit->snmp_id] = NULL; - } + if (circuit->interface->ifindex != IFINDEX_INTERNAL) + isis_circuit_disable(circuit); isis_circuit_if_unbind(circuit, circuit->interface); + QOBJ_UNREG(circuit); + + ldp_sync_info_free(&circuit->ldp_sync_info); + circuit_mt_finish(circuit); isis_lfa_excluded_ifaces_clear(circuit, ISIS_LEVEL1); isis_lfa_excluded_ifaces_clear(circuit, ISIS_LEVEL2); + XFREE(MTYPE_ISIS_CIRCUIT, circuit->tag); + /* and lastly the circuit itself */ XFREE(MTYPE_ISIS_CIRCUIT, circuit); @@ -228,6 +217,7 @@ void isis_circuit_configure(struct isis_circuit *circuit, struct isis_area *area) { assert(area); + circuit->isis = area->isis; circuit->area = area; /* @@ -247,12 +237,16 @@ void isis_circuit_configure(struct isis_circuit *circuit, circuit->idx = flags_get_index(&area->flags); + hook_call(isis_circuit_new_hook, circuit); + return; } void isis_circuit_deconfigure(struct isis_circuit *circuit, struct isis_area *area) { + hook_call(isis_circuit_del_hook, circuit); + /* Free the index of SRM and SSN flags */ flags_free_index(&area->flags, circuit->idx); circuit->idx = 0; @@ -260,6 +254,7 @@ void isis_circuit_deconfigure(struct isis_circuit *circuit, assert(circuit->area == area); listnode_delete(area->circuit_list, circuit); circuit->area = NULL; + circuit->isis = NULL; return; } @@ -284,29 +279,7 @@ struct isis_circuit *circuit_lookup_by_ifp(struct interface *ifp, struct isis_circuit *circuit_scan_by_ifp(struct interface *ifp) { - struct isis_area *area; - struct listnode *node; - struct isis_circuit *circuit; - struct isis *isis = NULL; - - if (ifp->info) - return (struct isis_circuit *)ifp->info; - - isis = isis_lookup_by_vrfid(ifp->vrf_id); - if (isis == NULL) { - zlog_warn(" %s : ISIS routing instance not found", __func__); - return NULL; - } - - if (isis->area_list) { - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { - circuit = - circuit_lookup_by_ifp(ifp, area->circuit_list); - if (circuit) - return circuit; - } - } - return circuit_lookup_by_ifp(ifp, isis->init_circ_list); + return (struct isis_circuit *)ifp->info; } DEFINE_HOOK(isis_circuit_add_addr_hook, (struct isis_circuit *circuit), @@ -516,8 +489,6 @@ void isis_circuit_if_add(struct isis_circuit *circuit, struct interface *ifp) struct listnode *node, *nnode; struct connected *conn; - isis_circuit_if_bind(circuit, ifp); - if (if_is_broadcast(ifp)) { if (fabricd || circuit->circ_type_config == CIRCUIT_T_P2P) circuit->circ_type = CIRCUIT_T_P2P; @@ -681,13 +652,6 @@ int isis_circuit_up(struct isis_circuit *circuit) return ISIS_OK; } - if (circuit->snmp_id == 0) { - /* We cannot bring circuit up if does not have snmp-id */ - flog_err(EC_ISIS_CONFIG, - "No snnmp-id: there are too many circuits:"); - return ISIS_ERROR; - } - if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit)) { flog_err( EC_ISIS_CONFIG, @@ -789,6 +753,11 @@ int isis_circuit_up(struct isis_circuit *circuit) circuit->last_uptime = time(NULL); + if (circuit->area->mta && circuit->area->mta->status) + isis_link_params_update(circuit, circuit->interface); + + isis_if_ldp_sync_enable(circuit); + #ifndef FABRICD /* send northbound notification */ isis_notif_if_state_change(circuit, false); @@ -804,6 +773,8 @@ void isis_circuit_down(struct isis_circuit *circuit) isis_notif_if_state_change(circuit, true); #endif /* ifndef FABRICD */ + isis_if_ldp_sync_disable(circuit); + /* log adjacency changes if configured to do so */ if (circuit->area->log_adj_changes) { struct isis_adjacency *adj = NULL; @@ -1345,23 +1316,6 @@ static int isis_interface_config_write(struct vty *vty) } #endif /* ifdef FABRICD */ -struct isis_circuit *isis_circuit_create(struct isis_area *area, - struct interface *ifp) -{ - struct isis_circuit *circuit = circuit_scan_by_ifp(ifp); - - if (circuit && circuit->area) - return NULL; - circuit = isis_csm_state_change(ISIS_ENABLE, circuit, area); - if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) - return circuit; - isis_circuit_if_bind(circuit, ifp); - if (circuit->area->mta && circuit->area->mta->status) - isis_link_params_update(circuit, ifp); - - return circuit; -} - void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router, bool ipv6_router) { @@ -1377,24 +1331,13 @@ void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router, circuit->ipv6_router = ipv6_router; circuit_update_nlpids(circuit); - /* the area should always be there if we get here, but in the past - * there were corner cases where the area was NULL (e.g. because the - * circuit was deconfigured following a validation error). Do not - * segfault if this happens again. - */ - if (!area) { - zlog_err("%s: NULL area for circuit %u", __func__, - circuit->circuit_id); - return; - } - - area->ip_circuits += ip_router - old_ipr; - area->ipv6_circuits += ipv6_router - old_ipv6r; + if (area) { + area->ip_circuits += ip_router - old_ipr; + area->ipv6_circuits += ipv6_router - old_ipv6r; - if (!ip_router && !ipv6_router) - isis_csm_state_change(ISIS_DISABLE, circuit, area); - else - lsp_regenerate_schedule(area, circuit->is_type, 0); + if (ip_router || ipv6_router) + lsp_regenerate_schedule(area, circuit->is_type, 0); + } } ferr_r isis_circuit_passive_set(struct isis_circuit *circuit, bool passive) @@ -1516,8 +1459,9 @@ int isis_circuit_mt_enabled_set(struct isis_circuit *circuit, uint16_t mtid, setting = circuit_get_mt_setting(circuit, mtid); if (setting->enabled != enabled) { setting->enabled = enabled; - lsp_regenerate_schedule(circuit->area, IS_LEVEL_1 | IS_LEVEL_2, - 0); + if (circuit->area) + lsp_regenerate_schedule(circuit->area, + IS_LEVEL_1 | IS_LEVEL_2, 0); } return CMD_SUCCESS; @@ -1530,27 +1474,19 @@ int isis_if_new_hook(struct interface *ifp) int isis_if_delete_hook(struct interface *ifp) { - struct isis_circuit *circuit; - /* Clean up the circuit data */ - if (ifp && ifp->info) { - circuit = ifp->info; - isis_csm_state_change(IF_DOWN_FROM_Z, circuit, ifp); - } + if (ifp->info) + isis_circuit_del(ifp->info); return 0; } static int isis_ifp_create(struct interface *ifp) { - struct vrf *vrf = NULL; + struct isis_circuit *circuit = ifp->info; + + if (circuit) + isis_circuit_enable(circuit); - if (if_is_operative(ifp)) { - vrf = vrf_lookup_by_id(ifp->vrf_id); - if (vrf) - isis_global_instance_create(vrf->name); - isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), - ifp); - } hook_call(isis_if_new_hook, ifp); return 0; @@ -1558,34 +1494,33 @@ static int isis_ifp_create(struct interface *ifp) static int isis_ifp_up(struct interface *ifp) { - isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp); + struct isis_circuit *circuit = ifp->info; + + if (circuit) + isis_csm_state_change(IF_UP_FROM_Z, circuit, ifp); return 0; } static int isis_ifp_down(struct interface *ifp) { - struct isis_circuit *circuit; + struct isis_circuit *circuit = ifp->info; + + if (circuit) { + isis_csm_state_change(IF_DOWN_FROM_Z, circuit, ifp); - circuit = isis_csm_state_change(IF_DOWN_FROM_Z, - circuit_scan_by_ifp(ifp), ifp); - if (circuit) SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF); + } return 0; } static int isis_ifp_destroy(struct interface *ifp) { - if (if_is_operative(ifp)) - zlog_warn("Zebra: got delete of %s, but interface is still up", - ifp->name); - - isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp); + struct isis_circuit *circuit = ifp->info; - /* Cannot call if_delete because we should retain the pseudo interface - in case there is configuration info attached to it. */ - if_delete_retain(ifp); + if (circuit) + isis_circuit_disable(circuit); return 0; } |
