Circuit IDs need to be unique, otherwise mayhem will ensue.
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
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;
}
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); */
}
circuit->circ_type = CIRCUIT_T_UNKNOWN;
+ _ISIS_CLEAR_FLAG(isis->circuit_ids_used, circuit->circuit_id);
circuit->circuit_id = 0;
return;
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;
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.",
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) \
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];