summaryrefslogtreecommitdiff
path: root/isisd/isis_circuit.c
diff options
context:
space:
mode:
Diffstat (limited to 'isisd/isis_circuit.c')
-rw-r--r--isisd/isis_circuit.c223
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;
}