]> git.puffer.fish Git - matthieu/frr.git/commitdiff
isisd: generate unique circuit ids
authorChristian Franke <chris@opensourcerouting.org>
Thu, 14 Sep 2017 13:26:33 +0000 (15:26 +0200)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 Sep 2017 11:59:09 +0000 (07:59 -0400)
Circuit IDs need to be unique, otherwise mayhem will ensue.

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
isisd/isis_circuit.c
isisd/isis_csm.c
isisd/isis_flags.h
isisd/isisd.h

index 192b225cae7830493cf98ee2eb07c4ce1fafd589..1a978ee0423a5553c68c87c2727827b321037075 100644 (file)
@@ -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;
index 10870d5c50210c222d8ea40b9107ab540b28ef9f..a283260d92aa590d93896f1d8e1d9fc423506afe 100644 (file)
@@ -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.",
index c57f7788076f5f0b976bff7821ae3d5ed67208ac..229b7ab3378e45ff47ff1e5bc8147edbb4e091f5 100644 (file)
@@ -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)                                              \
index 36fe0b5937dd4dab5161f1c30ace3d9f537d92fd..a10748fd45284cf6bfaba88245b530ad677827e6 100644 (file)
@@ -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];