]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: dup addr detect operation commands
authorChirag Shah <chirag@cumulusnetworks.com>
Sun, 4 Nov 2018 18:17:29 +0000 (10:17 -0800)
committerChirag Shah <chirag@cumulusnetworks.com>
Sun, 18 Nov 2018 03:22:17 +0000 (19:22 -0800)
Display duplicate detected list of MACs and VNIs.
- Per VNI
- Across all VNIs

Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
zebra/zebra_vty.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h
zebra/zebra_vxlan_private.h

index 263cb3d22c7aeded7e541624909f28775896ab6c..1b8a12e319288f8a6943801913953ce6533e255c 100644 (file)
@@ -1970,7 +1970,7 @@ DEFUN (show_evpn_mac_vni_all,
        bool uj = use_json(argc, argv);
 
        zvrf = vrf_info_lookup(VRF_DEFAULT);
-       zebra_vxlan_print_macs_all_vni(vty, zvrf, uj);
+       zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj);
        return CMD_SUCCESS;
 }
 
@@ -2059,6 +2059,90 @@ DEFUN (show_evpn_mac_vni_vtep,
        return CMD_SUCCESS;
 }
 
+DEFPY (show_evpn_mac_vni_all_dad,
+       show_evpn_mac_vni_all_dad_cmd,
+       "show evpn mac vni all duplicate [json]",
+       SHOW_STR
+       "EVPN\n"
+       "MAC addresses\n"
+       "VxLAN Network Identifier\n"
+       "All VNIs\n"
+       "Duplicate address list\n"
+       JSON_STR)
+{
+       struct zebra_vrf *zvrf;
+       bool uj = use_json(argc, argv);
+
+       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj);
+       return CMD_SUCCESS;
+}
+
+
+DEFPY (show_evpn_mac_vni_dad,
+       show_evpn_mac_vni_dad_cmd,
+       "show evpn mac vni " CMD_VNI_RANGE " duplicate" "[json]",
+       SHOW_STR
+       "EVPN\n"
+       "MAC addresses\n"
+       "VxLAN Network Identifier\n"
+       "VNI number\n"
+       "Duplicate address list\n"
+       JSON_STR)
+{
+       struct zebra_vrf *zvrf;
+       vni_t vni;
+       bool uj = use_json(argc, argv);
+
+       vni = strtoul(argv[4]->arg, NULL, 10);
+       zvrf = vrf_info_lookup(VRF_DEFAULT);
+
+       zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj);
+
+       return CMD_SUCCESS;
+}
+
+DEFPY (show_evpn_neigh_vni_dad,
+       show_evpn_neigh_vni_dad_cmd,
+       "show evpn arp-cache vni " CMD_VNI_RANGE "duplicate" "[json]",
+       SHOW_STR
+       "EVPN\n"
+       "ARP and ND cache\n"
+       "VxLAN Network Identifier\n"
+       "VNI number\n"
+       "Duplicate address list\n"
+       JSON_STR)
+{
+       struct zebra_vrf *zvrf;
+       vni_t vni;
+       bool uj = use_json(argc, argv);
+
+       vni = strtoul(argv[4]->arg, NULL, 10);
+       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj);
+       return CMD_SUCCESS;
+}
+
+DEFPY (show_evpn_neigh_vni_all_dad,
+       show_evpn_neigh_vni_all_dad_cmd,
+       "show evpn arp-cache vni all duplicate [json]",
+       SHOW_STR
+       "EVPN\n"
+       "ARP and ND cache\n"
+       "VxLAN Network Identifier\n"
+       "All VNIs\n"
+       "Duplicate address list\n"
+       JSON_STR)
+{
+       struct zebra_vrf *zvrf;
+       bool uj = use_json(argc, argv);
+
+       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj);
+       return CMD_SUCCESS;
+}
+
+
 DEFUN (show_evpn_neigh_vni,
        show_evpn_neigh_vni_cmd,
        "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
@@ -2093,7 +2177,7 @@ DEFUN (show_evpn_neigh_vni_all,
        bool uj = use_json(argc, argv);
 
        zvrf = vrf_info_lookup(VRF_DEFAULT);
-       zebra_vxlan_print_neigh_all_vni(vty, zvrf, uj);
+       zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj);
        return CMD_SUCCESS;
 }
 
@@ -2755,10 +2839,14 @@ void zebra_vty_init(void)
        install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
        install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
        install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
+       install_element(VIEW_NODE, &show_evpn_mac_vni_dad_cmd);
+       install_element(VIEW_NODE, &show_evpn_mac_vni_all_dad_cmd);
        install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
        install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
        install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
        install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
+       install_element(VIEW_NODE, &show_evpn_neigh_vni_dad_cmd);
+       install_element(VIEW_NODE, &show_evpn_neigh_vni_all_dad_cmd);
 
        install_element(VIEW_NODE, &show_pbr_ipset_cmd);
        install_element(VIEW_NODE, &show_pbr_iptable_cmd);
index 4866e584a8b95a26b5fb588f7938c28fdb49a6fb..00ba39d92fd67f51f129ec8039f62a6ba1c48f5a 100644 (file)
@@ -66,6 +66,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
                                    uint16_t cmd);
 static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json);
 static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt);
+static void zvni_print_dad_neigh_hash(struct hash_backet *backet, void *ctxt);
 static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
                                          void **args);
 static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
@@ -261,6 +262,50 @@ static uint32_t num_valid_macs(zebra_vni_t *zvni)
        return num_macs;
 }
 
+static uint32_t num_dup_detected_macs(zebra_vni_t *zvni)
+{
+       unsigned int i;
+       uint32_t num_macs = 0;
+       struct hash *hash;
+       struct hash_backet *hb;
+       zebra_mac_t *mac;
+
+       hash = zvni->mac_table;
+       if (!hash)
+               return num_macs;
+       for (i = 0; i < hash->size; i++) {
+               for (hb = hash->index[i]; hb; hb = hb->next) {
+                       mac = (zebra_mac_t *)hb->data;
+                       if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
+                               num_macs++;
+               }
+       }
+
+       return num_macs;
+}
+
+static uint32_t num_dup_detected_neighs(zebra_vni_t *zvni)
+{
+       unsigned int i;
+       uint32_t num_neighs = 0;
+       struct hash *hash;
+       struct hash_backet *hb;
+       zebra_neigh_t *nbr;
+
+       hash = zvni->neigh_table;
+       if (!hash)
+               return num_neighs;
+       for (i = 0; i < hash->size; i++) {
+               for (hb = hash->index[i]; hb; hb = hb->next) {
+                       nbr = (zebra_neigh_t *)hb->data;
+                       if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
+                               num_neighs++;
+               }
+       }
+
+       return num_neighs;
+}
+
 static int advertise_gw_macip_enabled(zebra_vni_t *zvni)
 {
        struct zebra_vrf *zvrf;
@@ -541,13 +586,19 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
        uint32_t num_neigh;
        struct neigh_walk_ctx wctx;
        char vni_str[VNI_STR_LEN];
+       uint32_t print_dup;
 
        vty = (struct vty *)args[0];
        json = (json_object *)args[1];
+       print_dup = (uint32_t)(uintptr_t)args[2];
 
        zvni = (zebra_vni_t *)backet->data;
 
        num_neigh = hashcount(zvni->neigh_table);
+
+       if (print_dup)
+               num_neigh = num_dup_detected_neighs(zvni);
+
        if (json == NULL) {
                vty_out(vty,
                        "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
@@ -557,6 +608,7 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
                json_object_int_add(json_vni, "numArpNd", num_neigh);
                snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
        }
+
        if (!num_neigh) {
                if (json)
                        json_object_object_add(json, vni_str, json_vni);
@@ -579,12 +631,28 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
                        -wctx.addr_width, "IP", "Type",
                        "State", "MAC", "Remote VTEP");
        }
-       hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
+       if (print_dup)
+               hash_iterate(zvni->neigh_table, zvni_print_dad_neigh_hash,
+                            &wctx);
+       else
+               hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
 
        if (json)
                json_object_object_add(json, vni_str, json_vni);
 }
 
+static void zvni_print_dad_neigh_hash(struct hash_backet *backet, void *ctxt)
+{
+       zebra_neigh_t *nbr;
+
+       nbr = (zebra_neigh_t *)backet->data;
+       if (!nbr)
+               return;
+
+       if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
+               zvni_print_neigh_hash(backet, ctxt);
+}
+
 /* print a specific next hop for an l3vni */
 static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
                            json_object *json)
@@ -948,6 +1016,19 @@ static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt)
        }
 }
 
+/* Print Duplicate MAC */
+static void zvni_print_dad_mac_hash(struct hash_backet *backet, void *ctxt)
+{
+       zebra_mac_t *mac;
+
+       mac = (zebra_mac_t *)backet->data;
+       if (!mac)
+               return;
+
+       if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
+               zvni_print_mac_hash(backet, ctxt);
+}
+
 /*
  * Print MACs for all VNI.
  */
@@ -974,6 +1055,9 @@ static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt)
        if (!num_macs)
                return;
 
+       if (wctx->print_dup)
+               num_macs = num_dup_detected_macs(zvni);
+
        if (json) {
                json_vni = json_object_new_object();
                json_mac = json_object_new_object();
@@ -989,12 +1073,24 @@ static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt)
                } else
                        json_object_int_add(json_vni, "numMacs", num_macs);
        }
+
+       if (!num_macs) {
+               if (json) {
+                       json_object_int_add(json_vni, "numMacs", num_macs);
+                       json_object_object_add(json, vni_str, json_vni);
+               }
+               return;
+       }
+
        /* assign per-vni to wctx->json object to fill macs
         * under the vni. Re-assign primary json object to fill
         * next vni information.
         */
        wctx->json = json_mac;
-       hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx);
+       if (wctx->print_dup)
+               hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash, wctx);
+       else
+               hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx);
        wctx->json = json;
        if (json) {
                if (wctx->count)
@@ -5528,10 +5624,10 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
  * Display neighbors across all VNIs (VTY command handler).
  */
 void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
-                                    bool use_json)
+                                    bool print_dup, bool use_json)
 {
        json_object *json = NULL;
-       void *args[2];
+       void *args[3];
 
        if (!is_evpn_enabled())
                return;
@@ -5541,6 +5637,8 @@ void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
 
        args[0] = vty;
        args[1] = json;
+       args[2] = (void *)(ptrdiff_t)print_dup;
+
        hash_iterate(zvrf->vni_table,
                     (void (*)(struct hash_backet *,
                               void *))zvni_print_neigh_hash_all_vni,
@@ -5637,6 +5735,70 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
        }
 }
 
+/*
+ * Display Duplicate detected Neighbors for a VNI
+ * (VTY command handler).
+ */
+void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
+                                    struct zebra_vrf *zvrf,
+                                    vni_t vni,
+                                    bool use_json)
+{
+       zebra_vni_t *zvni;
+       uint32_t num_neigh;
+       struct neigh_walk_ctx wctx;
+       json_object *json = NULL;
+
+       if (!is_evpn_enabled())
+               return;
+
+       zvni = zvni_lookup(vni);
+       if (!zvni) {
+               vty_out(vty, "%% VNI %u does not exist\n", vni);
+               return;
+       }
+
+       num_neigh = hashcount(zvni->neigh_table);
+       if (!num_neigh)
+               return;
+
+       num_neigh = num_dup_detected_neighs(zvni);
+       if (!num_neigh)
+               return;
+
+       if (use_json)
+               json = json_object_new_object();
+
+       /* Since we have IPv6 addresses to deal with which can vary widely in
+        * size, we try to be a bit more elegant in display by first computing
+        * the maximum width.
+        */
+       memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
+       wctx.zvni = zvni;
+       wctx.vty = vty;
+       wctx.addr_width = 15;
+       wctx.json = json;
+       hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
+
+       if (!use_json) {
+               vty_out(vty,
+                       "Number of ARPs (local and remote) known for this VNI: %u\n",
+                       num_neigh);
+               vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
+                       -wctx.addr_width, "IP", "Type",
+                       "State", "MAC", "Remote VTEP");
+       } else
+               json_object_int_add(json, "numArpNd", num_neigh);
+
+       hash_iterate(zvni->neigh_table, zvni_print_dad_neigh_hash, &wctx);
+
+       if (use_json) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
 /*
  * Display MACs for a VNI (VTY command handler).
  */
@@ -5696,7 +5858,7 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
  * Display MACs for all VNIs (VTY command handler).
  */
 void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
-                                   bool use_json)
+                                   bool print_dup, bool use_json)
 {
        struct mac_walk_ctx wctx;
        json_object *json = NULL;
@@ -5712,6 +5874,7 @@ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
        memset(&wctx, 0, sizeof(struct mac_walk_ctx));
        wctx.vty = vty;
        wctx.json = json;
+       wctx.print_dup = print_dup;
        hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
 
        if (use_json) {
@@ -5790,6 +5953,64 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
        zvni_print_mac(mac, vty, json);
 }
 
+/* Print Duplicate MACs per VNI */
+void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
+                                   struct zebra_vrf *zvrf,
+                                   vni_t vni, bool use_json)
+{
+       zebra_vni_t *zvni;
+       struct mac_walk_ctx wctx;
+       uint32_t num_macs;
+       json_object *json = NULL;
+       json_object *json_mac = NULL;
+
+       if (!is_evpn_enabled())
+               return;
+
+       zvni = zvni_lookup(vni);
+       if (!zvni) {
+               vty_out(vty, "%% VNI %u does not exist\n", vni);
+               return;
+       }
+
+       num_macs = num_valid_macs(zvni);
+       if (!num_macs)
+               return;
+
+       num_macs = num_dup_detected_macs(zvni);
+       if (!num_macs)
+               return;
+
+       if (use_json) {
+               json = json_object_new_object();
+               json_mac = json_object_new_object();
+       }
+
+       memset(&wctx, 0, sizeof(struct mac_walk_ctx));
+       wctx.zvni = zvni;
+       wctx.vty = vty;
+       wctx.json = json_mac;
+
+       if (!use_json) {
+               vty_out(vty,
+               "Number of MACs (local and remote) known for this VNI: %u\n",
+                       num_macs);
+               vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
+                       "Intf/Remote VTEP", "VLAN");
+       } else
+               json_object_int_add(json, "numMacs", num_macs);
+
+       hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash, &wctx);
+
+       if (use_json) {
+               json_object_object_add(json, "macs", json_mac);
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
+}
+
 /*
  * Display MACs for a VNI from specific VTEP (VTY command handler).
  */
index 806af9100f400526b71e8702b529ebc82245cd55..b33219d5e9dca9da82376509828c8d8078e8f31c 100644 (file)
@@ -88,6 +88,7 @@ extern void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
                                       vni_t vni, bool use_json);
 extern void zebra_vxlan_print_macs_all_vni(struct vty *vty,
                                           struct zebra_vrf *zvrf,
+                                          bool print_dup,
                                           bool use_json);
 extern void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
                                                struct zebra_vrf *zvrf,
@@ -101,10 +102,14 @@ extern void zebra_vxlan_print_macs_vni_vtep(struct vty *vty,
                                            struct zebra_vrf *zvrf, vni_t vni,
                                            struct in_addr vtep_ip,
                                            bool use_json);
+extern void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
+                                          struct zebra_vrf *zvrf, vni_t vni,
+                                          bool use_json);
 extern void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
                                        vni_t vni, bool use_json);
 extern void zebra_vxlan_print_neigh_all_vni(struct vty *vty,
                                            struct zebra_vrf *zvrf,
+                                           bool print_dup,
                                            bool use_json);
 extern void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
                                                 struct zebra_vrf *zvrf,
@@ -114,6 +119,9 @@ extern void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty,
                                             struct zebra_vrf *zvrf, vni_t vni,
                                             struct in_addr vtep_ip,
                                             bool use_json);
+extern void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
+                                       struct zebra_vrf *zvrf, vni_t vni,
+                                       bool use_json);
 extern void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf,
                                  vni_t vni, bool use_json);
 extern void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
index ca1c25e2ac10f5c9c64f04896763466e839756d1..3be7dc012ac2839bb4939f258c25a84c4e0e2495 100644 (file)
@@ -305,6 +305,7 @@ struct mac_walk_ctx {
        struct vty *vty;          /* Used by VTY handlers */
        uint32_t count;           /* Used by VTY handlers */
        struct json_object *json; /* Used for JSON Output */
+       bool print_dup; /* Used to print dup addr list */
 };
 
 struct rmac_walk_ctx {