]> git.puffer.fish Git - mirror/frr.git/commitdiff
fabricd: Add `show openfabric flooding` command
authorChristian Franke <chris@opensourcerouting.org>
Fri, 23 Nov 2018 02:13:56 +0000 (03:13 +0100)
committerRodny Molina <rmolina@linkedin.com>
Fri, 7 Dec 2018 19:45:14 +0000 (19:45 +0000)
Add a command to show to what neighbors an LSP has been flooded.

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
isisd/fabricd.c
isisd/fabricd.h
isisd/isis_lsp.c
isisd/isis_lsp.h
isisd/isis_vty_fabricd.c

index 5a9c424d66a9c0e66d86106b63244d1e09dca3a6..3b6db67c2ba210fd7769e3921f9a30972682a4d1 100644 (file)
@@ -35,6 +35,7 @@
 
 DEFINE_MTYPE_STATIC(ISISD, FABRICD_STATE, "ISIS OpenFabric")
 DEFINE_MTYPE_STATIC(ISISD, FABRICD_NEIGHBOR, "ISIS OpenFabric Neighbor Entry")
+DEFINE_MTYPE_STATIC(ISISD, FABRICD_FLOODING_INFO, "ISIS OpenFabric Flooding Log")
 
 /* Tracks initial synchronization as per section 2.4
  *
@@ -509,10 +510,13 @@ int fabricd_write_settings(struct isis_area *area, struct vty *vty)
 }
 
 static void move_to_queue(struct isis_lsp *lsp, struct neighbor_entry *n,
-                         enum isis_tx_type type)
+                         enum isis_tx_type type, struct isis_circuit *circuit)
 {
        n->present = false;
 
+       if (n->adj && n->adj->circuit == circuit)
+               return;
+
        if (isis->debugs & DEBUG_FLOODING) {
                zlog_debug("OpenFabric: Adding %s to %s",
                           print_sys_hostname(n->id),
@@ -521,6 +525,11 @@ static void move_to_queue(struct isis_lsp *lsp, struct neighbor_entry *n,
 
        if (n->adj)
                isis_tx_queue_add(n->adj->circuit->tx_queue, lsp, type);
+
+       uint8_t *neighbor_id = XMALLOC(MTYPE_FABRICD_FLOODING_INFO, sizeof(n->id));
+
+       memcpy(neighbor_id, n->id, sizeof(n->id));
+       listnode_add(lsp->flooding_neighbors[type], neighbor_id);
 }
 
 static void mark_neighbor_as_present(struct hash_backet *backet, void *arg)
@@ -571,11 +580,39 @@ static struct isis_lsp *lsp_for_neighbor(struct fabricd *f,
        return lsp_for_vertex(f->spftree, &vertex);
 }
 
-void fabricd_lsp_flood(struct isis_lsp *lsp)
+static void fabricd_free_lsp_flooding_info(void *val)
+{
+       XFREE(MTYPE_FABRICD_FLOODING_INFO, val);
+}
+
+static void fabricd_lsp_reset_flooding_info(struct isis_lsp *lsp,
+                                           struct isis_circuit *circuit)
+{
+       XFREE(MTYPE_FABRICD_FLOODING_INFO, lsp->flooding_interface);
+       for (enum isis_tx_type type = TX_LSP_NORMAL;
+            type <= TX_LSP_CIRCUIT_SCOPED; type++) {
+               if (lsp->flooding_neighbors[type]) {
+                       list_delete_all_node(lsp->flooding_neighbors[type]);
+                       continue;
+               }
+
+               lsp->flooding_neighbors[type] = list_new();
+               lsp->flooding_neighbors[type]->del = fabricd_free_lsp_flooding_info;
+       }
+
+       if (circuit) {
+               lsp->flooding_interface = XSTRDUP(MTYPE_FABRICD_FLOODING_INFO,
+                                                 circuit->interface->name);
+       }
+}
+
+void fabricd_lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit)
 {
        struct fabricd *f = lsp->area->fabricd;
        assert(f);
 
+       fabricd_lsp_reset_flooding_info(lsp, circuit);
+
        void *cursor = NULL;
        struct neighbor_entry *n;
 
@@ -597,7 +634,7 @@ void fabricd_lsp_flood(struct isis_lsp *lsp)
                                   rawlspid_print(node_lsp->hdr.lsp_id));
                }
 
-               move_to_queue(lsp, n, TX_LSP_CIRCUIT_SCOPED);
+               move_to_queue(lsp, n, TX_LSP_CIRCUIT_SCOPED, circuit);
        }
 
        /* Mark all elements in NN as present */
@@ -625,7 +662,7 @@ void fabricd_lsp_flood(struct isis_lsp *lsp)
                                           print_sys_hostname(n->id));
                        }
 
-                       move_to_queue(lsp, n, TX_LSP_CIRCUIT_SCOPED);
+                       move_to_queue(lsp, n, TX_LSP_CIRCUIT_SCOPED, circuit);
                        continue;
                }
 
@@ -657,7 +694,8 @@ void fabricd_lsp_flood(struct isis_lsp *lsp)
                }
 
                move_to_queue(lsp, n, need_reflood ?
-                             TX_LSP_NORMAL : TX_LSP_CIRCUIT_SCOPED);
+                             TX_LSP_NORMAL : TX_LSP_CIRCUIT_SCOPED,
+                             circuit);
        }
 
        if (isis->debugs & DEBUG_FLOODING) {
@@ -709,3 +747,15 @@ struct list *fabricd_ip_addrs(struct isis_circuit *circuit)
 
        return NULL;
 }
+
+void fabricd_lsp_free(struct isis_lsp *lsp)
+{
+       XFREE(MTYPE_FABRICD_FLOODING_INFO, lsp->flooding_interface);
+       for (enum isis_tx_type type = TX_LSP_NORMAL;
+            type <= TX_LSP_CIRCUIT_SCOPED; type++) {
+               if (!lsp->flooding_neighbors[type])
+                       continue;
+
+               list_delete(&lsp->flooding_neighbors[type]);
+       }
+}
index 76c182f2d27816e1b1fc5cb71ccc8584fbb80ba6..886fd3c628885df3bd52021637511fc8a8fb3b4a 100644 (file)
@@ -42,8 +42,9 @@ struct isis_spftree *fabricd_spftree(struct isis_area *area);
 void fabricd_configure_tier(struct isis_area *area, uint8_t tier);
 uint8_t fabricd_tier(struct isis_area *area);
 int fabricd_write_settings(struct isis_area *area, struct vty *vty);
-void fabricd_lsp_flood(struct isis_lsp *lsp);
+void fabricd_lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit);
 void fabricd_trigger_csnp(struct isis_area *area);
 struct list *fabricd_ip_addrs(struct isis_circuit *circuit);
+void fabricd_lsp_free(struct isis_lsp *lsp);
 
 #endif
index b8640f34bf0d36ed484bd7de0157fc7c3ea15c61..86d433cff7f81db7e9338f9306437fc80dce0430 100644 (file)
@@ -143,6 +143,8 @@ static void lsp_destroy(struct isis_lsp *lsp)
 
        if (lsp->pdu)
                stream_free(lsp->pdu);
+
+       fabricd_lsp_free(lsp);
        XFREE(MTYPE_ISIS_LSP, lsp);
 }
 
@@ -2011,7 +2013,7 @@ void _lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit,
        if (!fabricd)
                lsp_set_all_srmflags(lsp, true);
        else
-               fabricd_lsp_flood(lsp);
+               fabricd_lsp_flood(lsp, circuit);
 
        if (circuit)
                isis_tx_queue_del(circuit->tx_queue, lsp);
index 3013b8c214ba88bfbebb079c0f39dcc5aa4057aa..7f088987bee5b783af31f43fc1dfbaa5739a3d39 100644 (file)
@@ -47,6 +47,9 @@ struct isis_lsp {
        int age_out;
        struct isis_area *area;
        struct isis_tlvs *tlvs;
+
+       struct list *flooding_neighbors[TX_LSP_CIRCUIT_SCOPED + 1];
+       char *flooding_interface;
 };
 
 dict_t *lsp_db_init(void);
index 5ef3af0f19d204d33f2147ba42034fa17178351c..72ee2ac921145fe146cca734f13ceb62dd0e3219 100644 (file)
 
 #include "command.h"
 
-#include "isisd.h"
-#include "isis_vty_common.h"
-#include "fabricd.h"
-#include "isis_tlvs.h"
+#include "isisd/isisd.h"
+#include "isisd/isis_vty_common.h"
+#include "isisd/fabricd.h"
+#include "isisd/isis_tlvs.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_lsp.h"
 
 DEFUN (fabric_tier,
        fabric_tier_cmd,
@@ -55,8 +57,83 @@ DEFUN (no_fabric_tier,
        return CMD_SUCCESS;
 }
 
+static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp)
+{
+       char lspid[255];
+
+       lspid_print(lsp->hdr.lsp_id, lspid, true, true);
+       vty_out(vty, "Flooding information for %s\n", lspid);
+
+       if (!lsp->flooding_neighbors[TX_LSP_NORMAL]) {
+               vty_out(vty, "    Never flooded.\n");
+               return;
+       }
+
+       vty_out(vty, "    Last received on: %s\n",
+               lsp->flooding_interface ?
+               lsp->flooding_interface : "(null)");
+
+       for (enum isis_tx_type type = TX_LSP_NORMAL;
+            type <= TX_LSP_CIRCUIT_SCOPED; type++) {
+               struct listnode *node;
+               uint8_t *neighbor_id;
+
+               vty_out(vty, "    %s:\n",
+                       (type == TX_LSP_NORMAL) ? "RF" : "DNR");
+               for (ALL_LIST_ELEMENTS_RO(lsp->flooding_neighbors[type],
+                                         node, neighbor_id)) {
+                       vty_out(vty, "        %s\n",
+                               print_sys_hostname(neighbor_id));
+               }
+       }
+}
+
+DEFUN (show_lsp_flooding,
+       show_lsp_flooding_cmd,
+       "show openfabric flooding [WORD]",
+       SHOW_STR
+       PROTO_HELP
+       "Flooding information\n"
+       "LSP ID\n")
+{
+       const char *lspid = NULL;
+
+       if (argc == 4) {
+               lspid = argv[3]->arg;
+       }
+
+       struct listnode *node;
+       struct isis_area *area;
+
+       for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
+               dict_t *lspdb = area->lspdb[ISIS_LEVEL2 - 1];
+
+               vty_out(vty, "Area %s:\n", area->area_tag ?
+                       area->area_tag : "null");
+
+               if (lspid) {
+                       struct isis_lsp *lsp = lsp_for_arg(lspid, lspdb);
+
+                       if (lsp)
+                               lsp_print_flooding(vty, lsp);
+
+                       continue;
+               }
+
+               for (dnode_t *dnode = dict_first(lspdb); dnode;
+                    dnode = dict_next(lspdb, dnode)) {
+                       lsp_print_flooding(vty, dnode_get(dnode));
+                       vty_out(vty, "\n");
+               }
+       }
+
+       return CMD_SUCCESS;
+}
+
 void isis_vty_daemon_init(void)
 {
        install_element(ROUTER_NODE, &fabric_tier_cmd);
        install_element(ROUTER_NODE, &no_fabric_tier_cmd);
+
+       install_element(ENABLE_NODE, &show_lsp_flooding_cmd);
 }