From: Christian Franke Date: Thu, 14 Sep 2017 13:26:33 +0000 (+0200) Subject: isisd: generate unique circuit ids X-Git-Tag: frr-4.0-dev~296 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=068c82222961320a57ef56488de5eb3c49b159da;p=matthieu%2Ffrr.git isisd: generate unique circuit ids Circuit IDs need to be unique, otherwise mayhem will ensue. Signed-off-by: Christian Franke --- diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 192b225cae..1a978ee042 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -373,43 +373,31 @@ void isis_circuit_del_addr(struct isis_circuit *circuit, return; } -static u_char isis_circuit_id_gen(struct interface *ifp) +static uint8_t isis_circuit_id_gen(struct interface *ifp) { - u_char id = 0; - char ifname[16]; + /* Circuit ids MUST be unique for any broadcast circuits. Otherwise, + * Pseudo-Node LSPs cannot be generated correctly. + * + * Currently, allocate one circuit ID for any circuit, limiting the total + * numer of circuits IS-IS can run on to 255. + * + * We should revisit this when implementing 3-way adjacencies for p2p, since + * we then have extended interface IDs available. + */ + uint8_t id = ifp->ifindex; unsigned int i; - int start = -1, end = -1; - /* - * Get a stable circuit id from ifname. This makes - * the ifindex from flapping when netdevs are created - * and deleted on the fly. Note that this circuit id - * is used in pseudo lsps so it is better to be stable. - * The following code works on any reasonanle ifname - * like: eth1 or trk-1.1 etc. - */ - for (i = 0; i < strlen(ifp->name); i++) { - if (isdigit((unsigned char)ifp->name[i])) { - if (start < 0) { - start = i; - end = i + 1; - } else { - end = i + 1; - } - } else if (start >= 0) + for (i = 0; i < 256; i++) { + if (id && !_ISIS_CHECK_FLAG(isis->circuit_ids_used, id)) break; + id++; } - if ((start >= 0) && (end >= start) && (end - start) < 16) { - memset(ifname, 0, 16); - strncpy(ifname, &ifp->name[start], end - start); - id = (u_char)atoi(ifname); + if (i == 256) { + zlog_warn("Could not allocate a circuit id for '%s'", ifp->name); + return 0; } - /* Try to be unique. */ - if (!id) - id = (u_char)((ifp->ifindex & 0xff) | 0x80); - return id; } @@ -419,6 +407,7 @@ void isis_circuit_if_add(struct isis_circuit *circuit, struct interface *ifp) struct connected *conn; circuit->circuit_id = isis_circuit_id_gen(ifp); + _ISIS_SET_FLAG(isis->circuit_ids_used, circuit->circuit_id); isis_circuit_if_bind(circuit, ifp); /* isis_circuit_update_addrs (circuit, ifp); */ @@ -480,6 +469,7 @@ void isis_circuit_if_del(struct isis_circuit *circuit, struct interface *ifp) } circuit->circ_type = CIRCUIT_T_UNKNOWN; + _ISIS_CLEAR_FLAG(isis->circuit_ids_used, circuit->circuit_id); circuit->circuit_id = 0; return; diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c index 10870d5c50..a283260d92 100644 --- a/isisd/isis_csm.c +++ b/isisd/isis_csm.c @@ -86,6 +86,13 @@ isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg) case IF_UP_FROM_Z: circuit = isis_circuit_new(); isis_circuit_if_add(circuit, (struct interface *)arg); + if (!circuit->circuit_id) { + isis_circuit_if_del(circuit, + (struct interface *)arg); + isis_circuit_del(circuit); + circuit = NULL; + break; + } listnode_add(isis->init_circ_list, circuit); circuit->state = C_STATE_INIT; break; @@ -136,6 +143,8 @@ isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg) break; case IF_UP_FROM_Z: isis_circuit_if_add(circuit, (struct interface *)arg); + if (!circuit->circuit_id) + break; if (isis_circuit_up(circuit) != ISIS_OK) { zlog_err( "Could not bring up %s because of invalid config.", diff --git a/isisd/isis_flags.h b/isisd/isis_flags.h index c57f778807..229b7ab337 100644 --- a/isisd/isis_flags.h +++ b/isisd/isis_flags.h @@ -41,17 +41,22 @@ long int flags_get_index(struct flags *flags); void flags_free_index(struct flags *flags, long int index); int flags_any_set(u_int32_t *flags); -#define ISIS_SET_FLAG(F, C) \ - { \ - F[C->idx >> 5] |= (1 << (C->idx & 0x1F)); \ +#define _ISIS_SET_FLAG(F, C) \ + { \ + F[(C) >> 5] |= (1 << ((C) & 0x1F)); \ } +#define ISIS_SET_FLAG(F, C) _ISIS_SET_FLAG(F, C->idx) -#define ISIS_CLEAR_FLAG(F, C) \ - { \ - F[C->idx >> 5] &= ~(1 << (C->idx & 0x1F)); \ + +#define _ISIS_CLEAR_FLAG(F, C) \ + { \ + F[(C) >> 5] &= ~(1 << ((C) & 0x1F)); \ } +#define ISIS_CLEAR_FLAG(F, C) _ISIS_CLEAR_FLAG(F, C->idx) + -#define ISIS_CHECK_FLAG(F, C) (F[(C)->idx>>5] & (1<<(C->idx & 0x1F))) +#define _ISIS_CHECK_FLAG(F, C) (F[(C)>>5] & (1<<((C) & 0x1F))) +#define ISIS_CHECK_FLAG(F, C) _ISIS_CHECK_FLAG(F, C->idx) /* sets all u_32int_t flags to 1 */ #define ISIS_FLAGS_SET_ALL(FLAGS) \ diff --git a/isisd/isisd.h b/isisd/isisd.h index 36fe0b5937..a10748fd45 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -50,7 +50,8 @@ struct isis { struct area_addr *man_area_addrs; /* manualAreaAddresses */ u_int32_t debugs; /* bitmap for debug */ time_t uptime; /* when did we start */ - struct thread *t_dync_clean; /* dynamic hostname cache cleanup thread */ + struct thread *t_dync_clean; /* dynamic hostname cache cleanup thread */ + uint32_t circuit_ids_used[8]; /* 256 bits to track circuit ids 0 through 255 */ struct route_table *ext_info[REDIST_PROTOCOL_COUNT];