]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #3719 from liam-mcb/master
authorMartin Winter <mwinter@opensourcerouting.org>
Tue, 12 Feb 2019 01:54:53 +0000 (08:54 +0700)
committerGitHub <noreply@github.com>
Tue, 12 Feb 2019 01:54:53 +0000 (08:54 +0700)
Revert "redhat: don't Requires initscript on systemd based distros"

118 files changed:
bgpd/bgp_aspath.c
bgpd/bgp_debug.c
bgpd/bgp_debug.h
bgpd/bgp_evpn_private.h
bgpd/bgp_evpn_vty.c
bgpd/bgp_route.c
bgpd/bgp_routemap.c
bgpd/bgp_rpki.c
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.c
bgpd/rfapi/bgp_rfapi_cfg.c
doc/developer/conf.py
doc/developer/index.rst
doc/developer/subdir.am
doc/developer/testing.rst [new file with mode: 0644]
doc/developer/topotests-snippets.rst [new file with mode: 0644]
doc/developer/topotests.rst [new file with mode: 0644]
doc/user/routemap.rst
doc/user/sharp.rst
eigrpd/eigrp_dump.c
eigrpd/eigrp_dump.h
eigrpd/eigrp_interface.c
eigrpd/eigrp_topology.c
eigrpd/eigrp_vty.c
eigrpd/eigrp_zebra.c
eigrpd/eigrp_zebra.h
isisd/isis_redist.c
lib/log.c
lib/log.h
lib/memory.c
lib/memory.h
lib/prefix.c
lib/route_types.pl
lib/routemap.c
lib/routemap.h
lib/workqueue.c
lib/workqueue.h
lib/zclient.c
lib/zclient.h
ospf6d/ospf6_asbr.c
ospfd/ospf_packet.c
ospfd/ospf_routemap.c
ospfd/ospf_zebra.c
pimd/pim_cmd.c
pimd/pim_iface.c
pimd/pim_iface.h
pimd/pim_oil.c
pimd/pim_rp.c
pimd/pim_vty.c
pimd/pim_zebra.c
pimd/pimd.h
pimd/subdir.am
redhat/frr.service
ripd/ripd.c
ripngd/ripngd.c
sharpd/sharp_globals.h [new file with mode: 0644]
sharpd/sharp_main.c
sharpd/sharp_nht.c [new file with mode: 0644]
sharpd/sharp_nht.h [new file with mode: 0644]
sharpd/sharp_vty.c
sharpd/sharp_zebra.c
sharpd/sharp_zebra.h
sharpd/subdir.am
tests/Makefile.in [new file with mode: 0644]
tests/topotests/GUIDELINES.md [deleted file]
tests/topotests/README.md
tests/topotests/SNIPPETS.md [deleted file]
tests/topotests/eigrp-topo1/r1/show_ip_route.json_ref
tests/topotests/eigrp-topo1/r2/show_ip_route.json_ref
tests/topotests/eigrp-topo1/r3/show_ip_route.json_ref
tests/topotests/eigrp-topo1/test_eigrp_topo1.py
tests/topotests/ospf-topo1-vrf/r1/zebra.conf
tools/frr.service
vtysh/vtysh.c
zebra/debug.c
zebra/debug.h
zebra/interface.c
zebra/irdp_interface.c
zebra/irdp_main.c
zebra/irdp_packet.c
zebra/kernel_netlink.c
zebra/kernel_socket.c
zebra/label_manager.c
zebra/main.c
zebra/redistribute.c
zebra/router-id.c
zebra/rt.h
zebra/rt_netlink.c
zebra/rtadv.c
zebra/subdir.am
zebra/zapi_msg.c
zebra/zapi_msg.h
zebra/zebra_dplane.c
zebra/zebra_dplane.h
zebra/zebra_mlag.c
zebra/zebra_mpls.c
zebra/zebra_mpls_netlink.c
zebra/zebra_mpls_null.c
zebra/zebra_mpls_openbsd.c
zebra/zebra_netns_notify.c
zebra/zebra_ptm.c
zebra/zebra_ptm_redistribute.c
zebra/zebra_pw.c
zebra/zebra_pw.h
zebra/zebra_rib.c
zebra/zebra_routemap.c
zebra/zebra_router.c
zebra/zebra_router.h
zebra/zebra_vrf.c
zebra/zebra_vrf.h
zebra/zebra_vty.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h
zebra/zebra_vxlan_private.h
zebra/zserv.c
zebra/zserv.h

index 4f756519cafc3fbff1117e72cb8eef171910c5bf..9521a9e912eafcc86aaf2f7c50d847d5c9d42249 100644 (file)
@@ -1381,39 +1381,45 @@ static struct aspath *aspath_merge(struct aspath *as1, struct aspath *as2)
 /* Prepend as1 to as2.  as2 should be uninterned aspath. */
 struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
 {
-       struct assegment *seg1;
-       struct assegment *seg2;
+       struct assegment *as1segtail;
+       struct assegment *as2segtail;
+       struct assegment *as2seghead;
 
        if (!as1 || !as2)
                return NULL;
 
-       seg1 = as1->segments;
-       seg2 = as2->segments;
-
        /* If as2 is empty, only need to dupe as1's chain onto as2 */
-       if (seg2 == NULL) {
+       if (as2->segments == NULL) {
                as2->segments = assegment_dup_all(as1->segments);
                aspath_str_update(as2, false);
                return as2;
        }
 
        /* If as1 is empty AS, no prepending to do. */
-       if (seg1 == NULL)
+       if (as1->segments == NULL)
                return as2;
 
        /* find the tail as1's segment chain. */
-       while (seg1 && seg1->next)
-               seg1 = seg1->next;
+       as1segtail = as1->segments;
+       while (as1segtail && as1segtail->next)
+               as1segtail = as1segtail->next;
 
        /* Delete any AS_CONFED_SEQUENCE segment from as2. */
-       if (seg1->type == AS_SEQUENCE && seg2->type == AS_CONFED_SEQUENCE)
+       if (as1segtail->type == AS_SEQUENCE
+           && as2->segments->type == AS_CONFED_SEQUENCE)
                as2 = aspath_delete_confed_seq(as2);
 
+       if (!as2->segments) {
+               as2->segments = assegment_dup_all(as1->segments);
+               aspath_str_update(as2, false);
+               return as2;
+       }
+
        /* Compare last segment type of as1 and first segment type of as2. */
-       if (seg1->type != seg2->type)
+       if (as1segtail->type != as2->segments->type)
                return aspath_merge(as1, as2);
 
-       if (seg1->type == AS_SEQUENCE) {
+       if (as1segtail->type == AS_SEQUENCE) {
                /* We have two chains of segments, as1->segments and seg2,
                 * and we have to attach them together, merging the attaching
                 * segments together into one.
@@ -1423,23 +1429,28 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
                 * 3. attach chain after seg2
                 */
 
+               /* save as2 head */
+               as2seghead = as2->segments;
+
                /* dupe as1 onto as2's head */
-               seg1 = as2->segments = assegment_dup_all(as1->segments);
+               as2segtail = as2->segments = assegment_dup_all(as1->segments);
 
-               /* refind the tail of as2, reusing seg1 */
-               while (seg1 && seg1->next)
-                       seg1 = seg1->next;
+               /* refind the tail of as2 */
+               while (as2segtail && as2segtail->next)
+                       as2segtail = as2segtail->next;
 
                /* merge the old head, seg2, into tail, seg1 */
-               seg1 = assegment_append_asns(seg1, seg2->as, seg2->length);
+               assegment_append_asns(as2segtail, as2seghead->as,
+                                     as2seghead->length);
 
-               /* bypass the merged seg2, and attach any chain after it to
-                * chain descending from as2's head
+               /*
+                * bypass the merged seg2, and attach any chain after it
+                * to chain descending from as2's head
                 */
-               seg1->next = seg2->next;
+               as2segtail->next = as2seghead->next;
 
-               /* seg2 is now referenceless and useless*/
-               assegment_free(seg2);
+               /* as2->segments is now referenceless and useless */
+               assegment_free(as2seghead);
 
                /* we've now prepended as1's segment chain to as2, merging
                 * the inbetween AS_SEQUENCE of seg2 in the process
index 39ba404f384eebe2c70c81d29de33546161e303d..f476b161884ad8eaf6afa02c9523cda7d1fce692 100644 (file)
@@ -2123,67 +2123,6 @@ DEFUN_NOSH (show_debugging_bgp,
        return CMD_SUCCESS;
 }
 
-/* return count of number of debug flags set */
-int bgp_debug_count(void)
-{
-       int ret = 0;
-       if (BGP_DEBUG(as4, AS4))
-               ret++;
-
-       if (BGP_DEBUG(as4, AS4_SEGMENT))
-               ret++;
-
-       if (BGP_DEBUG(bestpath, BESTPATH))
-               ret++;
-
-       if (BGP_DEBUG(keepalive, KEEPALIVE))
-               ret++;
-
-       if (BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS))
-               ret++;
-
-       if (BGP_DEBUG(nht, NHT))
-               ret++;
-
-       if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
-               ret++;
-
-       if (BGP_DEBUG(update, UPDATE_PREFIX))
-               ret++;
-
-       if (BGP_DEBUG(update, UPDATE_IN))
-               ret++;
-
-       if (BGP_DEBUG(update, UPDATE_OUT))
-               ret++;
-
-       if (BGP_DEBUG(zebra, ZEBRA))
-               ret++;
-
-       if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS))
-               ret++;
-
-       if (BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF))
-               ret++;
-       if (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF))
-               ret++;
-       if (BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT))
-               ret++;
-       if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
-               ret++;
-       if (BGP_DEBUG(flowspec, FLOWSPEC))
-               ret++;
-       if (BGP_DEBUG(labelpool, LABELPOOL))
-               ret++;
-
-       if (BGP_DEBUG(pbr, PBR))
-               ret++;
-       if (BGP_DEBUG(pbr, PBR_ERROR))
-               ret++;
-
-       return ret;
-}
-
 static int bgp_config_write_debug(struct vty *vty)
 {
        int write = 0;
index d5d8fbb505e444e5e74b70e4a2d5ef0b47b60c67..e05da37647a45af926aa077b3c6b79ae93d49abf 100644 (file)
@@ -168,7 +168,6 @@ extern int bgp_debug_update(struct peer *peer, struct prefix *p,
 extern int bgp_debug_bestpath(struct prefix *p);
 extern int bgp_debug_zebra(struct prefix *p);
 
-extern int bgp_debug_count(void);
 extern const char *bgp_debug_rdpfxpath2str(afi_t, safi_t, struct prefix_rd *,
                                           union prefixconstptr, mpls_label_t *,
                                           uint32_t, int, uint32_t, char *,
index 43b1f05b3db49fa94b3ea141a0be580850729e96..c7f2671b78377ca2e9c4446044f4a9976f52cbd0 100644 (file)
@@ -73,6 +73,9 @@ struct bgpevpn {
         * advertising subnet for this VNI */
        uint8_t advertise_subnet;
 
+       /* Flag to indicate if we are advertising the svi mac ip for this VNI*/
+       uint8_t advertise_svi_macip;
+
        /* Id for deriving the RD
         * automatically for this VNI */
        uint16_t rd_id;
@@ -177,6 +180,10 @@ struct bgp_evpn_info {
        bool dad_freeze;
        /* Recovery time */
        uint32_t dad_freeze_time;
+
+       /* EVPN enable - advertise svi macip routes */
+       int advertise_svi_macip;
+
 };
 
 static inline int is_vrf_rd_configured(struct bgp *bgp_vrf)
index 776f8f8ef730d0df2fdca1353499700e4ba628e4..a3d8b8a6474313e5ed1dc190f0a2bb433060c959 100644 (file)
@@ -489,6 +489,8 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
                        inet_ntoa(vpn->originator_ip));
                vty_out(vty, "  Advertise-gw-macip : %s\n",
                        vpn->advertise_gw_macip ? "Yes" : "No");
+               vty_out(vty, "  Advertise-svi-macip : %s\n",
+                       vpn->advertise_svi_macip ? "Yes" : "No");
        }
 
        if (!json)
@@ -2618,6 +2620,33 @@ static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
                show_l3vni_entry(vty, bgp_temp, json);
 }
 
+/*
+ * evpn - enable advertisement of svi MAC-IP
+ */
+static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
+                                        uint32_t set)
+{
+       if (!vpn) {
+               if (set && bgp->evpn_info->advertise_svi_macip)
+                       return;
+               else if (!set && !bgp->evpn_info->advertise_svi_macip)
+                       return;
+
+               bgp->evpn_info->advertise_svi_macip = set;
+               bgp_zebra_advertise_svi_macip(bgp,
+                                       bgp->evpn_info->advertise_svi_macip, 0);
+       } else {
+               if (set && vpn->advertise_svi_macip)
+                       return;
+               else if (!set && !vpn->advertise_svi_macip)
+                       return;
+
+               vpn->advertise_svi_macip = set;
+               bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
+                                             vpn->vni);
+       }
+}
+
 /*
  * evpn - enable advertisement of default g/w
  */
@@ -2798,6 +2827,9 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
                if (vpn->advertise_gw_macip)
                        vty_out(vty, "   advertise-default-gw\n");
 
+               if (vpn->advertise_svi_macip)
+                       vty_out(vty, "   advertise-svi-ip\n");
+
                if (vpn->advertise_subnet)
                        vty_out(vty, "   advertise-subnet\n");
 
@@ -3151,6 +3183,54 @@ DEFPY (no_dup_addr_detection,
        return CMD_SUCCESS;
 }
 
+DEFPY(bgp_evpn_advertise_svi_ip,
+      bgp_evpn_advertise_svi_ip_cmd,
+      "[no$no] advertise-svi-ip",
+      NO_STR
+      "Advertise svi mac-ip routes in EVPN\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+
+       if (!bgp)
+               return CMD_WARNING;
+
+       if (bgp->vrf_id != VRF_DEFAULT) {
+               vty_out(vty,
+                       "This command is only supported under Default VRF\n");
+               return CMD_WARNING;
+       }
+
+       if (no)
+               evpn_set_advertise_svi_macip(bgp, NULL, 0);
+       else
+               evpn_set_advertise_svi_macip(bgp, NULL, 1);
+
+       return CMD_SUCCESS;
+}
+
+DEFPY(bgp_evpn_advertise_svi_ip_vni,
+      bgp_evpn_advertise_svi_ip_vni_cmd,
+      "[no$no] advertise-svi-ip",
+      NO_STR
+      "Advertise svi mac-ip routes in EVPN for a VNI\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
+
+       if (!bgp)
+               return CMD_WARNING;
+
+       if (!vpn)
+               return CMD_WARNING;
+
+       if (no)
+               evpn_set_advertise_svi_macip(bgp, vpn, 0);
+       else
+               evpn_set_advertise_svi_macip(bgp, vpn, 1);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
              bgp_evpn_advertise_vni_subnet_cmd,
              "advertise-subnet",
@@ -3260,6 +3340,8 @@ DEFUN (bgp_evpn_advertise_type5,
                if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
                        XFREE(MTYPE_ROUTE_MAP_NAME,
                              bgp_vrf->adv_cmd_rmap[afi][safi].name);
+                       route_map_counter_decrement(
+                                       bgp_vrf->adv_cmd_rmap[afi][safi].map);
                        bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
                        bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
                }
@@ -3271,6 +3353,8 @@ DEFUN (bgp_evpn_advertise_type5,
                        XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
                bgp_vrf->adv_cmd_rmap[afi][safi].map =
                        route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
+               route_map_counter_increment(
+                               bgp_vrf->adv_cmd_rmap[afi][safi].map);
        }
 
        /* advertise type-5 routes */
@@ -3409,6 +3493,9 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
                        vty_out(vty, "Advertise Gateway Macip: %s\n",
                                bgp_def->advertise_gw_macip ? "Enabled"
                                                            : "Disabled");
+                       vty_out(vty, "Advertise SVI Macip: %s\n",
+                               bgp_def->evpn_info->advertise_svi_macip ? "Enabled"
+                                                       : "Disabled");
                        vty_out(vty, "Advertise All VNI flag: %s\n",
                                is_evpn_enabled() ? "Enabled" : "Disabled");
                        vty_out(vty, "BUM flooding: %s\n",
@@ -5071,6 +5158,9 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
        if (bgp->advertise_gw_macip)
                vty_out(vty, "  advertise-default-gw\n");
 
+       if (bgp->evpn_info->advertise_svi_macip)
+               vty_out(vty, "  advertise-svi-ip\n");
+
        if (!bgp->evpn_info->dup_addr_detect)
                vty_out(vty, "  no dup-addr-detection\n");
 
@@ -5181,6 +5271,7 @@ void bgp_ethernetvpn_init(void)
        install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
        install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
        install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
+       install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
        install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
        install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
        install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
@@ -5237,6 +5328,7 @@ void bgp_ethernetvpn_init(void)
        install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
        install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
        install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
+       install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
        install_element(BGP_EVPN_VNI_NODE,
                        &bgp_evpn_advertise_default_gw_vni_cmd);
        install_element(BGP_EVPN_VNI_NODE,
index 99dc9d81249cab749d136a476cfd6cdcc7d66771..59ca223a2d8f3a997a3a60e77b43bd7838866fee 100644 (file)
@@ -4417,6 +4417,8 @@ static void bgp_static_free(struct bgp_static *bgp_static)
 {
        if (bgp_static->rmap.name)
                XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
+       route_map_counter_decrement(bgp_static->rmap.map);
+
        if (bgp_static->eth_s_id)
                XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
        XFREE(MTYPE_BGP_STATIC, bgp_static);
@@ -4981,14 +4983,20 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                                if (bgp_static->rmap.name)
                                        XFREE(MTYPE_ROUTE_MAP_NAME,
                                              bgp_static->rmap.name);
+                               route_map_counter_decrement(
+                                       bgp_static->rmap.map);
                                bgp_static->rmap.name =
                                        XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
                                bgp_static->rmap.map =
                                        route_map_lookup_by_name(rmap);
+                               route_map_counter_increment(
+                                       bgp_static->rmap.map);
                        } else {
                                if (bgp_static->rmap.name)
                                        XFREE(MTYPE_ROUTE_MAP_NAME,
                                              bgp_static->rmap.name);
+                               route_map_counter_decrement(
+                                       bgp_static->rmap.map);
                                bgp_static->rmap.name = NULL;
                                bgp_static->rmap.map = NULL;
                                bgp_static->valid = 0;
@@ -5007,10 +5015,14 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                                if (bgp_static->rmap.name)
                                        XFREE(MTYPE_ROUTE_MAP_NAME,
                                              bgp_static->rmap.name);
+                               route_map_counter_decrement(
+                                       bgp_static->rmap.map);
                                bgp_static->rmap.name =
                                        XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
                                bgp_static->rmap.map =
                                        route_map_lookup_by_name(rmap);
+                               route_map_counter_increment(
+                                       bgp_static->rmap.map);
                        }
                        bgp_node_set_bgp_static_info(rn, bgp_static);
                }
@@ -5289,10 +5301,12 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
                        if (bgp_static->rmap.name)
                                XFREE(MTYPE_ROUTE_MAP_NAME,
                                      bgp_static->rmap.name);
+                       route_map_counter_decrement(bgp_static->rmap.map);
                        bgp_static->rmap.name =
                                XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
                        bgp_static->rmap.map =
                                route_map_lookup_by_name(rmap_str);
+                       route_map_counter_increment(bgp_static->rmap.map);
                }
 
                if (safi == SAFI_EVPN) {
@@ -5395,11 +5409,14 @@ static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
        if (rmap_name) {
                if (rmap->name)
                        XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+               route_map_counter_decrement(rmap->map);
                rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
                rmap->map = route_map_lookup_by_name(rmap_name);
+               route_map_counter_increment(rmap->map);
        } else {
                if (rmap->name)
                        XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+               route_map_counter_decrement(rmap->map);
                rmap->name = NULL;
                rmap->map = NULL;
        }
@@ -5419,6 +5436,7 @@ static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
        rmap = &bgp->table_map[afi][safi];
        if (rmap->name)
                XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+       route_map_counter_decrement(rmap->map);
        rmap->name = NULL;
        rmap->map = NULL;
 
index 4953032f97bcd4dec6d0d04037907b2027e6a702..e28acdfbae6170ddb1c15772aaffcd61bb8d978e 100644 (file)
@@ -3250,6 +3250,15 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
                if (bgp->table_map[afi][safi].name
                    && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
                        == 0)) {
+
+                       /* bgp->table_map[afi][safi].map  is NULL.
+                        * i.e Route map creation event.
+                        * So update applied_counter.
+                        * If it is not NULL, i.e It may be routemap updation or
+                        * deletion. so no need to update the counter.
+                        */
+                       if (!bgp->table_map[afi][safi].map)
+                               route_map_counter_increment(map);
                        bgp->table_map[afi][safi].map = map;
 
                        if (BGP_DEBUG(zebra, ZEBRA))
@@ -3272,6 +3281,9 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
                            || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
                                continue;
 
+                       if (!bgp_static->rmap.map)
+                               route_map_counter_increment(map);
+
                        bgp_static->rmap.map = map;
 
                        if (route_update && !bgp_static->backdoor) {
@@ -3303,6 +3315,9 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
                                    || (strcmp(rmap_name, red->rmap.name) != 0))
                                        continue;
 
+                               if (!red->rmap.map)
+                                       route_map_counter_increment(map);
+
                                red->rmap.map = map;
 
                                if (!route_update)
index b614e87d23e3fb9111602389896a361c2cabf204..a38d78916c1837a7f69fbb40c73afdb670dc4336 100644 (file)
@@ -1134,7 +1134,7 @@ DEFPY (no_rpki_cache,
 {
        struct cache *cache_p = find_cache(preference);
 
-       if (!cache) {
+       if (!cache_p) {
                vty_out(vty, "Could not find cache %ld\n", preference);
                return CMD_WARNING;
        }
@@ -1190,9 +1190,23 @@ DEFUN (show_rpki_cache_server,
        struct cache *cache;
 
        for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
-               vty_out(vty, "host: %s port: %s\n",
-                       cache->tr_config.tcp_config->host,
-                       cache->tr_config.tcp_config->port);
+               if (cache->type == TCP) {
+                       vty_out(vty, "host: %s port: %s\n",
+                               cache->tr_config.tcp_config->host,
+                               cache->tr_config.tcp_config->port);
+
+               } else if (cache->type == SSH) {
+                       vty_out(vty,
+                               "host: %s port: %d username: %s "
+                               "server_hostkey_path: %s client_privkey_path: %s\n",
+                               cache->tr_config.ssh_config->host,
+                               cache->tr_config.ssh_config->port,
+                               cache->tr_config.ssh_config->username,
+                               cache->tr_config.ssh_config
+                                       ->server_hostkey_path,
+                               cache->tr_config.ssh_config
+                                       ->client_privkey_path);
+               }
        }
 
        return CMD_SUCCESS;
index 43adf342473c4b82ec84752d63d6c32e61b899ff..a6d985ab9f5e051c55780683d4cc408f75d5c89c 100644 (file)
@@ -11650,11 +11650,11 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group)
        conf = group->conf;
 
        if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) {
-               vty_out(vty, "\nBGP peer-group %s, remote AS %d\n", group->name,
-                       conf->as);
+               vty_out(vty, "\nBGP peer-group %s, remote AS %" PRIu32 "\n",
+                       group->name, conf->as);
        } else if (conf->as_type == AS_INTERNAL) {
-               vty_out(vty, "\nBGP peer-group %s, remote AS %d\n", group->name,
-                       group->bgp->as);
+               vty_out(vty, "\nBGP peer-group %s, remote AS %" PRIu32 "\n",
+                       group->name, group->bgp->as);
        } else {
                vty_out(vty, "\nBGP peer-group %s\n", group->name);
        }
index 75da0388296f2571205895b9cc1509c91a29926d..3f18d69a2d6a5333b71f74960148e3be0c45805d 100644 (file)
@@ -1683,8 +1683,13 @@ int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name,
 
        if (red->rmap.name)
                XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
+       /* Decrement the count for existing routemap and
+        * increment the count for new route map.
+        */
+       route_map_counter_decrement(red->rmap.map);
        red->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name);
        red->rmap.map = route_map;
+       route_map_counter_increment(red->rmap.map);
 
        return 1;
 }
@@ -1792,6 +1797,7 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
        /* Unset route-map. */
        if (red->rmap.name)
                XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
+       route_map_counter_decrement(red->rmap.map);
        red->rmap.name = NULL;
        red->rmap.map = NULL;
 
@@ -1930,6 +1936,29 @@ int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise, vni_t vni)
        return zclient_send_message(zclient);
 }
 
+int bgp_zebra_advertise_svi_macip(struct bgp *bgp, int advertise, vni_t vni)
+{
+       struct stream *s = NULL;
+
+       /* Check socket. */
+       if (!zclient || zclient->sock < 0)
+               return 0;
+
+       /* Don't try to register if Zebra doesn't know of this instance. */
+       if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
+               return 0;
+
+       s = zclient->obuf;
+       stream_reset(s);
+
+       zclient_create_header(s, ZEBRA_ADVERTISE_SVI_MACIP, bgp->vrf_id);
+       stream_putc(s, advertise);
+       stream_putl(s, vni);
+       stream_putw_at(s, 0, stream_get_endp(s));
+
+       return zclient_send_message(zclient);
+}
+
 int bgp_zebra_advertise_gw_macip(struct bgp *bgp, int advertise, vni_t vni)
 {
        struct stream *s = NULL;
index c6520c43e4e16583f38d3f498e4cfaa4ffde1f0a..fc19c5e17f5c6bd3ab1ecd79418b051cc42b18f6 100644 (file)
@@ -72,6 +72,8 @@ extern struct interface *if_lookup_by_ipv6_exact(struct in6_addr *, ifindex_t,
 extern int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise,
                                      vni_t vni);
 extern int bgp_zebra_advertise_gw_macip(struct bgp *, int, vni_t);
+extern int bgp_zebra_advertise_svi_macip(struct bgp *bgp, int advertise,
+                                        vni_t vni);
 extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
 extern int bgp_zebra_dup_addr_detection(struct bgp *bgp);
 extern int bgp_zebra_vxlan_flood_control(struct bgp *bgp,
index 0ab9a0b9212a71602e2e13d8cb3a7470167b4bfa..aceb990534c1de4f50c15b240a47b1066d73f364 100644 (file)
@@ -4594,15 +4594,18 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
                                XFREE(MTYPE_ROUTE_MAP_NAME,
                                      peer->default_rmap[afi][safi].name);
 
+                       route_map_counter_decrement(peer->default_rmap[afi][safi].map);
                        peer->default_rmap[afi][safi].name =
                                XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
                        peer->default_rmap[afi][safi].map = route_map;
+                       route_map_counter_increment(route_map);
                }
        } else if (!rmap) {
                if (peer->default_rmap[afi][safi].name)
                        XFREE(MTYPE_ROUTE_MAP_NAME,
                              peer->default_rmap[afi][safi].name);
 
+               route_map_counter_decrement(peer->default_rmap[afi][safi].map);
                peer->default_rmap[afi][safi].name = NULL;
                peer->default_rmap[afi][safi].map = NULL;
        }
@@ -4637,10 +4640,12 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
                        if (member->default_rmap[afi][safi].name)
                                XFREE(MTYPE_ROUTE_MAP_NAME,
                                      member->default_rmap[afi][safi].name);
-
+                       route_map_counter_decrement(
+                                       member->default_rmap[afi][safi].map);
                        member->default_rmap[afi][safi].name =
                                XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
                        member->default_rmap[afi][safi].map = route_map;
+                       route_map_counter_increment(route_map);
                }
 
                /* Update peer route announcements. */
@@ -4677,6 +4682,7 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
                if (peer->default_rmap[afi][safi].name)
                        XFREE(MTYPE_ROUTE_MAP_NAME,
                              peer->default_rmap[afi][safi].name);
+               route_map_counter_decrement(peer->default_rmap[afi][safi].map);
                peer->default_rmap[afi][safi].name = NULL;
                peer->default_rmap[afi][safi].map = NULL;
        }
@@ -4710,6 +4716,7 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
                if (peer->default_rmap[afi][safi].name)
                        XFREE(MTYPE_ROUTE_MAP_NAME,
                              peer->default_rmap[afi][safi].name);
+               route_map_counter_decrement(peer->default_rmap[afi][safi].map);
                peer->default_rmap[afi][safi].name = NULL;
                peer->default_rmap[afi][safi].map = NULL;
 
@@ -6118,8 +6125,10 @@ int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
        filter = &peer->filter[afi][safi];
        if (filter->map[direct].name)
                XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
+       route_map_counter_decrement(filter->map[direct].map);
        filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
        filter->map[direct].map = route_map;
+       route_map_counter_increment(route_map);
 
        /* Check if handling a regular peer. */
        if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@@ -6147,8 +6156,10 @@ int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
                filter = &member->filter[afi][safi];
                if (filter->map[direct].name)
                        XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
+               route_map_counter_decrement(filter->map[direct].map);
                filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
                filter->map[direct].map = route_map;
+               route_map_counter_increment(route_map);
 
                /* Process peer route updates. */
                peer_on_policy_change(member, afi, safi,
@@ -6182,6 +6193,7 @@ int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
                filter = &peer->filter[afi][safi];
                if (filter->map[direct].name)
                        XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
+               route_map_counter_decrement(filter->map[direct].map);
                filter->map[direct].name = NULL;
                filter->map[direct].map = NULL;
        }
@@ -6210,6 +6222,7 @@ int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
                filter = &member->filter[afi][safi];
                if (filter->map[direct].name)
                        XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
+               route_map_counter_decrement(filter->map[direct].map);
                filter->map[direct].name = NULL;
                filter->map[direct].map = NULL;
 
@@ -6233,8 +6246,10 @@ int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
        filter = &peer->filter[afi][safi];
        if (filter->usmap.name)
                XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
+       route_map_counter_decrement(filter->usmap.map);
        filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
        filter->usmap.map = route_map;
+       route_map_counter_increment(route_map);
 
        /* Check if handling a regular peer. */
        if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@@ -6261,8 +6276,10 @@ int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
                filter = &member->filter[afi][safi];
                if (filter->usmap.name)
                        XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
+               route_map_counter_decrement(filter->usmap.map);
                filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
                filter->usmap.map = route_map;
+               route_map_counter_increment(route_map);
 
                /* Process peer route updates. */
                peer_on_policy_change(member, afi, safi, 1);
@@ -6293,6 +6310,7 @@ int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
                filter = &peer->filter[afi][safi];
                if (filter->usmap.name)
                        XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
+               route_map_counter_decrement(filter->usmap.map);
                filter->usmap.name = NULL;
                filter->usmap.map = NULL;
        }
@@ -6320,6 +6338,7 @@ int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
                filter = &member->filter[afi][safi];
                if (filter->usmap.name)
                        XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
+               route_map_counter_decrement(filter->usmap.map);
                filter->usmap.name = NULL;
                filter->usmap.map = NULL;
 
index 05e057f07fe358b54d1fcd1374d698cc00447d19..13713c11f2285e4dcdd0aedef22177e2e2d5bb74 100644 (file)
@@ -1164,9 +1164,16 @@ DEFUN (vnc_redist_bgpdirect_routemap,
 
        if (hc->routemap_redist_name[route_type])
                free(hc->routemap_redist_name[route_type]);
+
+       /* If the old route map config overwrite with new
+        * route map config , old routemap counter have to be
+        * reduced.
+        */
+       route_map_counter_decrement(hc->routemap_redist[route_type]);
        hc->routemap_redist_name[route_type] = strdup(argv[4]->arg);
        hc->routemap_redist[route_type] =
                route_map_lookup_by_name(argv[4]->arg);
+       route_map_counter_increment(hc->routemap_redist[route_type]);
 
        vnc_redistribute_postchange(bgp);
 
@@ -1210,6 +1217,8 @@ DEFUN (vnc_nve_group_redist_bgpdirect_no_prefixlist,
 
        if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi])
                free(rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]);
+       route_map_counter_decrement(
+               rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]);
        rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi] = NULL;
        rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi] = NULL;
 
@@ -1285,6 +1294,8 @@ DEFUN (vnc_nve_group_redist_bgpdirect_no_routemap,
 
        if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT])
                free(rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]);
+       route_map_counter_decrement(
+               rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]);
        rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT] = NULL;
        rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT] = NULL;
 
@@ -1316,10 +1327,14 @@ DEFUN (vnc_nve_group_redist_bgpdirect_routemap,
 
        if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT])
                free(rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]);
+       route_map_counter_decrement(
+               rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]);
        rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT] =
                strdup(argv[3]->arg);
        rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT] =
                route_map_lookup_by_name(argv[3]->arg);
+       route_map_counter_increment(
+               rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]);
 
        vnc_redistribute_postchange(bgp);
 
@@ -1741,6 +1756,7 @@ DEFUN (vnc_nve_group_export_no_routemap,
                                    rfg->routemap_export_bgp_name))) {
                        if (rfg->routemap_export_bgp_name)
                                free(rfg->routemap_export_bgp_name);
+                       route_map_counter_decrement(rfg->routemap_export_bgp);
                        rfg->routemap_export_bgp_name = NULL;
                        rfg->routemap_export_bgp = NULL;
 
@@ -1754,6 +1770,7 @@ DEFUN (vnc_nve_group_export_no_routemap,
                                    rfg->routemap_export_zebra_name))) {
                        if (rfg->routemap_export_zebra_name)
                                free(rfg->routemap_export_zebra_name);
+                       route_map_counter_decrement(rfg->routemap_export_zebra);
                        rfg->routemap_export_zebra_name = NULL;
                        rfg->routemap_export_zebra = NULL;
 
@@ -1800,17 +1817,21 @@ DEFUN (vnc_nve_group_export_routemap,
        if (is_bgp) {
                if (rfg->routemap_export_bgp_name)
                        free(rfg->routemap_export_bgp_name);
+               route_map_counter_decrement(rfg->routemap_export_bgp);
                rfg->routemap_export_bgp_name = strdup(argv[idx]->arg);
                rfg->routemap_export_bgp =
                        route_map_lookup_by_name(argv[idx]->arg);
+               route_map_counter_increment(rfg->routemap_export_bgp);
                vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP);
                vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP6);
        } else {
                if (rfg->routemap_export_zebra_name)
                        free(rfg->routemap_export_zebra_name);
+               route_map_counter_decrement(rfg->routemap_export_zebra);
                rfg->routemap_export_zebra_name = strdup(argv[idx]->arg);
                rfg->routemap_export_zebra =
                        route_map_lookup_by_name(argv[idx]->arg);
+               route_map_counter_increment(rfg->routemap_export_zebra);
                vnc_zebra_reexport_group_afi(bgp, rfg, AFI_IP);
                vnc_zebra_reexport_group_afi(bgp, rfg, AFI_IP6);
        }
@@ -1937,6 +1958,7 @@ DEFUN (vnc_nve_export_no_routemap,
                    || (argc <= 5)) {
 
                        free(hc->routemap_export_bgp_name);
+                       route_map_counter_decrement(hc->routemap_export_bgp);
                        hc->routemap_export_bgp_name = NULL;
                        hc->routemap_export_bgp = NULL;
                        vnc_direct_bgp_reexport(bgp, AFI_IP);
@@ -1948,6 +1970,7 @@ DEFUN (vnc_nve_export_no_routemap,
                    || (argc <= 5)) {
 
                        free(hc->routemap_export_zebra_name);
+                       route_map_counter_decrement(hc->routemap_export_zebra);
                        hc->routemap_export_zebra_name = NULL;
                        hc->routemap_export_zebra = NULL;
                        /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */
@@ -1975,17 +1998,21 @@ DEFUN (vnc_nve_export_routemap,
        if (argv[2]->arg[0] == 'b') {
                if (hc->routemap_export_bgp_name)
                        free(hc->routemap_export_bgp_name);
+               route_map_counter_decrement(hc->routemap_export_bgp);
                hc->routemap_export_bgp_name = strdup(argv[4]->arg);
                hc->routemap_export_bgp =
                        route_map_lookup_by_name(argv[4]->arg);
+               route_map_counter_increment(hc->routemap_export_bgp);
                vnc_direct_bgp_reexport(bgp, AFI_IP);
                vnc_direct_bgp_reexport(bgp, AFI_IP6);
        } else {
                if (hc->routemap_export_zebra_name)
                        free(hc->routemap_export_zebra_name);
+               route_map_counter_decrement(hc->routemap_export_zebra);
                hc->routemap_export_zebra_name = strdup(argv[4]->arg);
                hc->routemap_export_zebra =
                        route_map_lookup_by_name(argv[4]->arg);
+               route_map_counter_increment(hc->routemap_export_zebra);
                /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */
                /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP6); */
        }
@@ -2083,6 +2110,7 @@ void vnc_routemap_update(struct bgp *bgp, const char *unused)
        struct rfapi_nve_group_cfg *rfg;
        struct rfapi_cfg *hc;
        int i;
+       struct route_map *old = NULL;
 
        vnc_zlog_debug_verbose("%s(arg=%s)", __func__, unused);
 
@@ -2104,18 +2132,36 @@ void vnc_routemap_update(struct bgp *bgp, const char *unused)
                                  rfg)) {
 
                if (rfg->routemap_export_bgp_name) {
+                       old = rfg->routemap_export_bgp;
                        rfg->routemap_export_bgp = route_map_lookup_by_name(
                                rfg->routemap_export_bgp_name);
+                       /* old is NULL. i.e Route map creation event.
+                        * So update applied_counter.
+                        * If Old is not NULL, i.e It may be routemap
+                        * updation or deletion.
+                        * So no need to update the counter.
+                        */
+                       if (!old)
+                               route_map_counter_increment(
+                                       rfg->routemap_export_bgp);
                }
                if (rfg->routemap_export_zebra_name) {
+                       old = rfg->routemap_export_bgp;
                        rfg->routemap_export_bgp = route_map_lookup_by_name(
                                rfg->routemap_export_zebra_name);
+                       if (!old)
+                               route_map_counter_increment(
+                                       rfg->routemap_export_bgp);
                }
                for (i = 0; i < ZEBRA_ROUTE_MAX; ++i) {
                        if (rfg->routemap_redist_name[i]) {
+                               old = rfg->routemap_redist[i];
                                rfg->routemap_redist[i] =
                                        route_map_lookup_by_name(
                                                rfg->routemap_redist_name[i]);
+                               if (!old)
+                                       route_map_counter_increment(
+                                               rfg->routemap_redist[i]);
                        }
                }
 
@@ -2128,17 +2174,27 @@ void vnc_routemap_update(struct bgp *bgp, const char *unused)
         * RH config, too
         */
        if (hc->routemap_export_bgp_name) {
+               old = hc->routemap_export_bgp;
                hc->routemap_export_bgp =
                        route_map_lookup_by_name(hc->routemap_export_bgp_name);
+               if (!old)
+                       route_map_counter_increment(hc->routemap_export_bgp);
        }
        if (hc->routemap_export_zebra_name) {
+               old  = hc->routemap_export_bgp;
                hc->routemap_export_bgp = route_map_lookup_by_name(
                        hc->routemap_export_zebra_name);
+               if (!old)
+                       route_map_counter_increment(hc->routemap_export_bgp);
        }
        for (i = 0; i < ZEBRA_ROUTE_MAX; ++i) {
                if (hc->routemap_redist_name[i]) {
+                       old = hc->routemap_redist[i];
                        hc->routemap_redist[i] = route_map_lookup_by_name(
                                hc->routemap_redist_name[i]);
+                       if (!old)
+                               route_map_counter_increment(
+                                       hc->routemap_redist[i]);
                }
        }
 
index 254c9f6bfc19a1f0141bd7a05ba59f009d48805b..ad501ae39ddd7c292347c19cbef4d0b09a5823b9 100644 (file)
@@ -131,7 +131,7 @@ language = None
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-exclude_patterns = ['_build', 'building-libyang.rst']
+exclude_patterns = ['_build', 'building-libyang.rst', 'topotests-snippets.rst']
 
 # The reST default role (used for this markup: `text`) to use for all
 # documents.
index 9838e1098caf5ebc05a87baf702376d4c0c0888d..3a33d9a5ec7bdc8f784ae1243598af1c8fd1cafe 100644 (file)
@@ -9,6 +9,7 @@ FRRouting Developer's Guide
    packaging
    process-architecture
    library
+   testing
    bgpd
    ospf
    zebra
index 575722a805c377719b7bd353246afc3d886a6dd4..19910e7627bb27c14e2c3a3809eeea43187ea797 100644 (file)
@@ -38,6 +38,9 @@ dev_RSTFILES = \
        doc/developer/ospf-api.rst \
        doc/developer/ospf-sr.rst \
        doc/developer/ospf.rst \
+       doc/developer/testing.rst \
+       doc/developer/topotests-snippets.rst \
+       doc/developer/topotests.rst \
        doc/developer/workflow.rst \
        doc/developer/zebra.rst \
        # end
diff --git a/doc/developer/testing.rst b/doc/developer/testing.rst
new file mode 100644 (file)
index 0000000..6396faf
--- /dev/null
@@ -0,0 +1,10 @@
+.. _testing:
+
+*******
+Testing
+*******
+
+.. toctree::
+   :maxdepth: 2
+
+   topotests
diff --git a/doc/developer/topotests-snippets.rst b/doc/developer/topotests-snippets.rst
new file mode 100644 (file)
index 0000000..649229b
--- /dev/null
@@ -0,0 +1,272 @@
+.. _topotests-snippets:
+
+Snippets
+--------
+
+This document will describe common snippets of code that are frequently needed
+to perform some test checks.
+
+Checking for router / test failures
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following check uses the topogen API to check for software failure (e.g.
+zebra died) and/or for errors manually set by ``Topogen.set_error()``.
+
+.. code:: py
+
+   # Get the topology reference
+   tgen = get_topogen()
+
+   # Check for errors in the topology
+   if tgen.routers_have_failure():
+       # Skip the test with the topology errors as reason
+       pytest.skip(tgen.errors)
+
+Checking FRR routers version
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This code snippet is usually run after the topology setup to make sure all
+routers instantiated in the topology have the correct software version.
+
+.. code:: py
+
+   # Get the topology reference
+   tgen = get_topogen()
+
+   # Get the router list
+   router_list = tgen.routers()
+
+   # Run the check for all routers
+   for router in router_list.values():
+       if router.has_version('<', '3'):
+           # Set topology error, so the next tests are skipped
+           tgen.set_error('unsupported version')
+
+A sample of this snippet in a test can be found `here
+<ldp-vpls-topo1/test_ldp_vpls_topo1.py>`__.
+
+Interacting with equipment
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You might want to interact with the topology equipments during the tests and
+there are different ways to do so.
+
+Notes:
+
+1. When using the Topogen API, all the equipments code derive from ``Topogear``
+   (`lib/topogen.py <lib/topogen.py>`__). If you feel brave you can look by
+   yourself how the abstractions that will be mentioned here works.
+
+2. When not using the ``Topogen`` API there is only one way to interact with
+   the equipments, which is by calling the ``mininet`` API functions directly
+   to spawn commands.
+
+Interacting with the Linux sandbox
+""""""""""""""""""""""""""""""""""
+
+Without ``Topogen``:
+
+.. code:: py
+
+   global net
+   output = net['r1'].cmd('echo "foobar"')
+   print 'output is: {}'.format(output)
+
+With ``Topogen``:
+
+.. code:: py
+
+   tgen = get_topogen()
+   output = tgen.gears['r1'].run('echo "foobar"')
+   print 'output is: {}'.format(output)
+
+Interacting with VTYSH
+""""""""""""""""""""""
+
+Without ``Topogen``:
+
+.. code:: py
+
+   global net
+   output = net['r1'].cmd('vtysh "show ip route" 2>/dev/null')
+   print 'output is: {}'.format(output)
+
+With ``Topogen``:
+
+.. code:: py
+
+   tgen = get_topogen()
+   output = tgen.gears['r1'].vtysh_cmd("show ip route")
+   print 'output is: {}'.format(output)
+
+``Topogen`` also supports sending multiple lines of command:
+
+.. code:: py
+
+   tgen = get_topogen()
+   output = tgen.gears['r1'].vtysh_cmd("""
+   configure terminal
+   router bgp 10
+     bgp router-id 10.0.255.1
+     neighbor 1.2.3.4 remote-as 10
+     !
+   router bgp 11
+     bgp router-id 10.0.255.2
+     !
+   """)
+   print 'output is: {}'.format(output)
+
+You might also want to run multiple commands and get only the commands that
+failed:
+
+.. code:: py
+
+   tgen = get_topogen()
+   output = tgen.gears['r1'].vtysh_multicmd("""
+   configure terminal
+   router bgp 10
+     bgp router-id 10.0.255.1
+     neighbor 1.2.3.4 remote-as 10
+     !
+   router bgp 11
+     bgp router-id 10.0.255.2
+     !
+   """, pretty_output=false)
+   print 'output is: {}'.format(output)
+
+Translating vtysh JSON output into Python structures:
+
+.. code:: py
+
+   tgen = get_topogen()
+   json_output = tgen.gears['r1'].vtysh_cmd("show ip route json", isjson=True)
+   output = json.dumps(json_output, indent=4)
+   print 'output is: {}'.format(output)
+
+   # You can also access the data structure as normal. For example:
+   # protocol = json_output['1.1.1.1/32']['protocol']
+   # assert protocol == "ospf", "wrong protocol"
+
+.. note::
+
+   ``vtysh_(multi)cmd`` is only available for router type of equipments.
+
+Invoking mininet CLI
+^^^^^^^^^^^^^^^^^^^^
+
+Without ``Topogen``:
+
+.. code:: py
+
+   CLI(net)
+
+With ``Topogen``:
+
+.. code:: py
+
+   tgen = get_topogen()
+   tgen.mininet_cli()
+
+Reading files
+^^^^^^^^^^^^^
+
+Loading a normal text file content in the current directory:
+
+.. code:: py
+
+   # If you are using Topogen
+   # CURDIR = CWD
+   #
+   # Otherwise find the directory manually:
+   CURDIR = os.path.dirname(os.path.realpath(__file__))
+
+   file_name = '{}/r1/show_ip_route.txt'.format(CURDIR)
+   file_content = open(file_name).read()
+
+Loading JSON from a file:
+
+.. code:: py
+
+   import json
+
+   file_name = '{}/r1/show_ip_route.json'.format(CURDIR)
+   file_content = json.loads(open(file_name).read())
+
+Comparing JSON output
+^^^^^^^^^^^^^^^^^^^^^
+
+After obtaining JSON output formated with Python data structures, you may use
+it to assert a minimalist schema:
+
+.. code:: py
+
+   tgen = get_topogen()
+   json_output = tgen.gears['r1'].vtysh_cmd("show ip route json", isjson=True)
+
+   expect = {
+     '1.1.1.1/32': {
+       'protocol': 'ospf'
+     }
+   }
+
+   assertmsg = "route 1.1.1.1/32 was not learned through OSPF"
+   assert json_cmp(json_output, expect) is None, assertmsg
+
+``json_cmp`` function description (it might be outdated, you can find the
+latest description in the source code at
+:file:`tests/topotests/lib/topotest.py`
+
+.. code:: text
+
+   JSON compare function. Receives two parameters:
+   * `d1`: json value
+   * `d2`: json subset which we expect
+
+   Returns `None` when all keys that `d1` has matches `d2`,
+   otherwise a string containing what failed.
+
+   Note: key absence can be tested by adding a key with value `None`.
+
+Pausing execution
+^^^^^^^^^^^^^^^^^
+
+Preferably, choose the ``sleep`` function that ``topotest`` provides, as it
+prints a notice during the test execution to help debug topology test execution
+time.
+
+.. code:: py
+
+    # Using the topotest sleep
+    from lib import topotest
+
+    topotest.sleep(10, 'waiting 10 seconds for bla')
+    # or just tell it the time:
+    # topotest.sleep(10)
+    # It will print 'Sleeping for 10 seconds'.
+
+    # Or you can also use the Python sleep, but it won't show anything
+    from time import sleep
+    sleep(5)
+
+iproute2 Linux commands as JSON
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``topotest`` has two helpers implemented that parses the output of ``ip route``
+commands to JSON. It might simplify your comparison needs by only needing to
+provide a Python dictionary.
+
+.. code:: py
+
+   from lib import topotest
+
+   tgen = get_topogen()
+   routes = topotest.ip4_route(tgen.gears['r1'])
+   expected = {
+     '10.0.1.0/24': {},
+     '10.0.2.0/24': {
+       'dev': 'r1-eth0'
+     }
+   }
+
+   assertmsg = "failed to find 10.0.1.0/24 and/or 10.0.2.0/24"
+   assert json_cmp(routes, expected) is None, assertmsg
diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst
new file mode 100644 (file)
index 0000000..aa06c8d
--- /dev/null
@@ -0,0 +1,927 @@
+.. _topotests:
+
+Topotests
+=========
+
+Topotests is a suite of topology tests for FRR built on top of Mininet.
+
+Installation and Setup
+----------------------
+
+Only tested with Ubuntu 16.04 and Ubuntu 18.04 (which uses Mininet 2.2.x).
+
+Instructions are the same for all setups (i.e. ExaBGP is only used for BGP
+tests).
+
+Installing Mininet Infrastructure
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: shell
+
+   apt-get install mininet
+   apt-get install python-pip
+   apt-get install iproute
+   pip install ipaddr
+   pip install pytest
+   pip install exabgp==3.4.17 (Newer 4.0 version of exabgp is not yet
+   supported)
+   useradd -d /var/run/exabgp/ -s /bin/false exabgp
+
+Enable Coredumps
+""""""""""""""""
+
+Optional, will give better output.
+
+.. code:: shell
+
+   apt-get install gdb
+   disable apport (which move core files)
+
+Set ``enabled=0`` in ``/etc/default/apport``.
+
+Next, update security limits by changing :file:`/etc/security/limits.conf` to::
+
+   #<domain>      <type>  <item>         <value>
+   *               soft    core          unlimited
+   root            soft    core          unlimited
+   *               hard    core          unlimited
+   root            hard    core          unlimited
+
+Reboot for options to take effect.
+
+FRR Installation
+^^^^^^^^^^^^^^^^
+
+FRR needs to be installed separately. It is assume to be configured like the
+standard Ubuntu Packages:
+
+-  Binaries in :file:`/usr/lib/frr`
+-  State Directory :file:`/var/run/frr`
+-  Running under user ``frr``, group ``frr``
+-  vtygroup: ``frrvty``
+-  config directory: :file:`/etc/frr`
+-  For FRR Packages, install the dbg package as well for coredump decoding
+
+No FRR config needs to be done and no FRR daemons should be run ahead of the
+test. They are all started as part of the test.
+
+Manual FRR build
+""""""""""""""""
+
+If you prefer to manually build FRR, then use the following suggested config:
+
+.. code:: shell
+
+   ./configure \
+       --prefix=/usr \
+       --localstatedir=/var/run/frr \
+       --sbindir=/usr/lib/frr \
+       --sysconfdir=/etc/frr \
+       --enable-vtysh \
+       --enable-pimd \
+       --enable-multipath=64 \
+       --enable-user=frr \
+       --enable-group=frr \
+       --enable-vty-group=frrvty \
+       --with-pkg-extra-version=-my-manual-build
+
+And create ``frr`` user and ``frrvty`` group as follows:
+
+.. code:: shell
+
+   addgroup --system --gid 92 frr
+   addgroup --system --gid 85 frrvty
+   adduser --system --ingroup frr --home /var/run/frr/ \
+      --gecos "FRRouting suite" --shell /bin/false frr
+   usermod -G frrvty frr
+
+Executing Tests
+---------------
+
+Execute all tests with output to console
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code:: shell
+
+   py.test -s -v --tb=no
+
+All test\_\* scripts in subdirectories are detected and executed (unless
+disabled in ``pytest.ini`` file).
+
+``--tb=no`` disables the python traceback which might be irrelevant unless the
+test script itself is debugged.
+
+Execute single test
+^^^^^^^^^^^^^^^^^^^
+
+.. code:: shell
+
+   cd test_to_be_run
+   ./test_to_be_run.py
+
+For further options, refer to pytest documentation.
+
+Test will set exit code which can be used with ``git bisect``.
+
+For the simulated topology, see the description in the python file.
+
+If you need to clear the mininet setup between tests (if it isn't cleanly
+shutdown), then use the ``mn -c`` command to clean up the environment.
+
+StdErr log from daemos after exit
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To enable the reporting of any messages seen on StdErr after the daemons exit,
+the following env variable can be set::
+
+   export TOPOTESTS_CHECK_STDERR=Yes
+
+(The value doesn't matter at this time. The check is if the env variable exists
+or not) There is no pass/fail on this reporting. The Output will be reported to
+the console::
+
+   export TOPOTESTS_CHECK_MEMLEAK="/home/mydir/memleak_"
+
+This will enable the check and output to console and the writing of the
+information to files with the given prefix (followed by testname), ie
+:file:`/home/mydir/memcheck_test_bgp_multiview_topo1.txt` in case of a memory
+leak.
+
+Collect Memory Leak Information
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+FRR processes have the capabilities to report remaining memory allocations upon
+exit. To enable the reporting of the memory, define an enviroment variable
+``TOPOTESTS_CHECK_MEMLEAK`` with the file prefix, i.e.::
+
+   export TOPOTESTS_CHECK_MEMLEAK="/home/mydir/memleak_"
+
+This will enable the check and output to console and the writing of the
+information to files with the given prefix (followed by testname), ie
+:file:`/home/mydir/memcheck_test_bgp_multiview_topo1.txt` in case of a memory
+leak.
+
+Running Topotests with AddressSanitizer
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Topotests can be run with AddressSanitizer. It requires GCC 4.8 or newer.
+(Ubuntu 16.04 as suggested here is fine with GCC 5 as default). For more
+information on AddressSanitizer, see
+https://github.com/google/sanitizers/wiki/AddressSanitizer.
+
+The checks are done automatically in the library call of ``checkRouterRunning``
+(ie at beginning of tests when there is a check for all daemons running). No
+changes or extra configuration for topotests is required beside compiling the
+suite with AddressSanitizer enabled.
+
+If a daemon crashed, then the errorlog is checked for AddressSanitizer output.
+If found, then this is added with context (calling test) to
+:file:`/tmp/AddressSanitizer.txt` in Markdown compatible format.
+
+Compiling for GCC AddressSanitizer requires to use ``gcc`` as a linker as well
+(instead of ``ld``). Here is a suggest way to compile frr with AddressSanitizer
+for ``stable/3.0`` branch:
+
+.. code:: shell
+
+   git clone https://github.com/FRRouting/frr.git
+   cd frr
+   git checkout stable/3.0
+   ./bootstrap.sh
+   export CC=gcc
+   export CFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer"
+   export LD=gcc
+   export LDFLAGS="-g -fsanitize=address -ldl"
+   ./configure --enable-shared=no \
+       --prefix=/usr/lib/frr --sysconfdir=/etc/frr \
+       --localstatedir=/var/run/frr \
+       --sbindir=/usr/lib/frr --bindir=/usr/lib/frr \
+       --enable-exampledir=/usr/lib/frr/examples \
+       --with-moduledir=/usr/lib/frr/modules \
+       --enable-multipath=0 --enable-rtadv \
+       --enable-tcp-zebra --enable-fpm --enable-pimd
+   make
+   sudo make install
+   # Create symlink for vtysh, so topotest finds it in /usr/lib/frr
+   sudo ln -s /usr/lib/frr/vtysh /usr/bin/
+
+and create ``frr`` user and ``frrvty`` group as shown above.
+
+.. _topotests_docker:
+
+Running Tests with Docker
+-------------------------
+
+There is a Docker image which allows to run topotests.
+
+Quickstart
+^^^^^^^^^^
+
+If you have Docker installed, you can run the topotests in Docker. The easiest
+way to do this, is to use the make targets from this repository.
+
+Your current user needs to have access to the Docker daemon.  Alternatively you
+can run these commands as root.
+
+.. code:: console
+
+   make topotests
+
+This command will pull the most recent topotests image from Dockerhub, compile
+FRR inside of it, and run the topotests.
+
+Advanced Usage
+^^^^^^^^^^^^^^
+
+Internally, the topotests make target uses a shell script to pull the image and
+spawn the Docker container.
+
+There are several environment variables which can be used to modify the
+behavior of the script, these can be listed by calling it with ``-h``:
+
+.. code:: console
+
+   ./tests/topotests/docker/frr-topotests.sh -h
+
+For example, a volume is used to cache build artifacts between multiple runs of
+the image. If you need to force a complete recompile, you can set
+``TOPOTEST_CLEAN``:
+
+.. code:: console
+
+   TOPOTEST_CLEAN=1 ./tests/topotests/docker/frr-topotests.sh
+
+By default, ``frr-topotests.sh`` will build frr and run pytest. If you append
+arguments and the first one starts with ``/`` or ``./``, they will replace the
+call to pytest. If the appended arguments do not match this patttern, they will
+be provided to pytest as arguments.  So, to run a specific test with more
+verbose logging:
+
+.. code:: console
+
+   ./tests/topotests/docker/frr-topotests.sh -vv -s all-protocol-startup/test_all_protocol_startup.py
+
+And to compile FRR but drop into a shell instead of running pytest:
+
+.. code:: console
+
+   ./tests/topotests/docker/frr-topotests.sh /bin/bash
+
+Development
+^^^^^^^^^^^
+
+The Docker image just includes all the components to run the topotests, but not
+the topotests themselves. So if you just want to write tests and don't want to
+make changes to the environment provided by the Docker image. You don't need to
+build your own Docker image if you do not want to.
+
+When developing new tests, there is one caveat though: The startup script of
+the container will run a ``git-clean`` on its copy of the FRR tree to avoid any
+pollution of the container with build artefacts from the host. This will also
+result in your newly written tests being unavailable in the container unless at
+least added to the index with ``git-add``.
+
+If you do want to test changes to the Docker image, you can locally build the
+image and run the tests without pulling from the registry using the following
+commands:
+
+.. code:: console
+
+   make topotests-build
+   TOPOTEST_PULL=0 make topotests
+
+
+.. _topotests-guidelines:
+
+Guidelines
+----------
+
+Executing Tests
+^^^^^^^^^^^^^^^
+
+To run the whole suite of tests the following commands must be executed at the
+top level directory of topotest:
+
+.. code:: shell
+
+   $ # Change to the top level directory of topotests.
+   $ cd path/to/topotests
+   $ # Tests must be run as root, since Mininet requires it.
+   $ sudo pytest
+
+In order to run a specific test, you can use the following command:
+
+.. code:: shell
+
+   $ # running a specific topology
+   $ sudo pytest ospf-topo1/
+   $ # or inside the test folder
+   $ cd ospf-topo1
+   $ sudo pytest # to run all tests inside the directory
+   $ sudo pytest test_ospf_topo1.py # to run a specific test
+   $ # or outside the test folder
+   $ cd ..
+   $ sudo pytest ospf-topo1/test_ospf_topo1.py # to run a specific one
+
+The output of the tested daemons will be available at the temporary folder of
+your machine:
+
+.. code:: shell
+
+   $ ls /tmp/topotest/ospf-topo1.test_ospf-topo1/r1
+   ...
+   zebra.err # zebra stderr output
+   zebra.log # zebra log file
+   zebra.out # zebra stdout output
+   ...
+
+You can also run memory leak tests to get reports:
+
+.. code:: shell
+
+   $ # Set the environment variable to apply to a specific test...
+   $ sudo env TOPOTESTS_CHECK_MEMLEAK="/tmp/memleak_report_" pytest ospf-topo1/test_ospf_topo1.py
+   $ # ...or apply to all tests adding this line to the configuration file
+   $ echo 'memleak_path = /tmp/memleak_report_' >> pytest.ini
+   $ # You can also use your editor
+   $ $EDITOR pytest.ini
+   $ # After running tests you should see your files:
+   $ ls /tmp/memleak_report_*
+   memleak_report_test_ospf_topo1.txt
+
+Writing a New Test
+^^^^^^^^^^^^^^^^^^
+
+This section will guide you in all recommended steps to produce a standard
+topology test.
+
+This is the recommended test writing routine:
+
+- Write a topology (Graphviz recommended)
+- Obtain configuration files
+- Write the test itself
+- Create a Pull Request
+
+Topotest File Hierarchy
+"""""""""""""""""""""""
+
+Before starting to write any tests one must know the file hierarchy. The
+repository hierarchy looks like this:
+
+.. code:: shell
+
+   $ cd path/to/topotest
+   $ find ./*
+   ...
+   ./README.md # repository read me
+   ./GUIDELINES.md # this file
+   ./conftest.py # test hooks - pytest related functions
+   ./example-test # example test folder
+   ./example-test/__init__.py # python package marker - must always exist.
+   ./example-test/test_template.jpg # generated topology picture - see next section
+   ./example-test/test_template.dot # Graphviz dot file
+   ./example-test/test_template.py # the topology plus the test
+   ...
+   ./ospf-topo1 # the ospf topology test
+   ./ospf-topo1/r1 # router 1 configuration files
+   ./ospf-topo1/r1/zebra.conf # zebra configuration file
+   ./ospf-topo1/r1/ospfd.conf # ospf configuration file
+   ./ospf-topo1/r1/ospfroute.txt # 'show ip ospf' output reference file
+   # removed other for shortness sake
+   ...
+   ./lib # shared test/topology functions
+   ./lib/topogen.py # topogen implementation
+   ./lib/topotest.py # topotest implementation
+
+Guidelines for creating/editing topotest:
+
+- New topologies that don't fit the existing directories should create its own
+- Always remember to add the ``__init__.py`` to new folders, this makes auto
+  complete engines and pylint happy
+- Router (Quagga/FRR) specific code should go on topotest.py
+- Generic/repeated router actions should have an abstraction in
+  topogen.TopoRouter.
+- Generic/repeated non-router code should go to topotest.py
+- pytest related code should go to conftest.py (e.g. specialized asserts)
+
+Defining the Topology
+"""""""""""""""""""""
+
+The first step to write a new test is to define the topology. This step can be
+done in many ways, but the recommended is to use Graphviz to generate a drawing
+of the topology. It allows us to see the topology graphically and to see the
+names of equipments, links and addresses.
+
+Here is an example of Graphviz dot file that generates the template topology
+:file:`tests/topotests/example-test/test_template.dot` (the inlined code might
+get outdated, please see the linked file)::
+
+   graph template {
+       label="template";
+
+       # Routers
+       r1 [
+           shape=doubleoctagon,
+           label="r1",
+           fillcolor="#f08080",
+           style=filled,
+       ];
+       r2 [
+           shape=doubleoctagon,
+           label="r2",
+           fillcolor="#f08080",
+           style=filled,
+       ];
+
+       # Switches
+       s1 [
+           shape=oval,
+           label="s1\n192.168.0.0/24",
+           fillcolor="#d0e0d0",
+           style=filled,
+       ];
+       s2 [
+           shape=oval,
+           label="s2\n192.168.1.0/24",
+           fillcolor="#d0e0d0",
+           style=filled,
+       ];
+
+       # Connections
+       r1 -- s1 [label="eth0\n.1"];
+
+       r1 -- s2 [label="eth1\n.100"];
+       r2 -- s2 [label="eth0\n.1"];
+   }
+
+Here is the produced graph:
+
+.. graphviz::
+
+   graph template {
+       label="template";
+
+       # Routers
+       r1 [
+           shape=doubleoctagon,
+           label="r1",
+           fillcolor="#f08080",
+           style=filled,
+       ];
+       r2 [
+           shape=doubleoctagon,
+           label="r2",
+           fillcolor="#f08080",
+           style=filled,
+       ];
+
+       # Switches
+       s1 [
+           shape=oval,
+           label="s1\n192.168.0.0/24",
+           fillcolor="#d0e0d0",
+           style=filled,
+       ];
+       s2 [
+           shape=oval,
+           label="s2\n192.168.1.0/24",
+           fillcolor="#d0e0d0",
+           style=filled,
+       ];
+
+       # Connections
+       r1 -- s1 [label="eth0\n.1"];
+
+       r1 -- s2 [label="eth1\n.100"];
+       r2 -- s2 [label="eth0\n.1"];
+   }
+
+Generating / Obtaining Configuration Files
+""""""""""""""""""""""""""""""""""""""""""
+
+In order to get the configuration files or command output for each router, we
+need to run the topology and execute commands in ``vtysh``. The quickest way to
+achieve that is writing the topology building code and running the topology.
+
+To bootstrap your test topology, do the following steps:
+
+- Copy the template test
+
+.. code:: shell
+
+   $ mkdir new-topo/
+   $ touch new-topo/__init__.py
+   $ cp example-test/test_template.py new-topo/test_new_topo.py
+
+- Modify the template according to your dot file
+
+Here is the template topology described in the previous section in python code:
+
+.. code:: py
+
+   class TemplateTopo(Topo):
+       "Test topology builder"
+       def build(self, *_args, **_opts):
+           "Build function"
+           tgen = get_topogen(self)
+
+           # Create 2 routers
+           for routern in range(1, 3):
+               tgen.add_router('r{}'.format(routern))
+
+           # Create a switch with just one router connected to it to simulate a
+           # empty network.
+           switch = tgen.add_switch('s1')
+           switch.add_link(tgen.gears['r1'])
+
+           # Create a connection between r1 and r2
+           switch = tgen.add_switch('s2')
+           switch.add_link(tgen.gears['r1'])
+           switch.add_link(tgen.gears['r2'])
+
+- Run the topology
+
+Topogen allows us to run the topology without running any tests, you can do
+that using the following example commands:
+
+.. code:: shell
+
+   $ # Running your bootstraped topology
+   $ sudo pytest -s --topology-only new-topo/test_new_topo.py
+   $ # Running the test_template.py topology
+   $ sudo pytest -s --topology-only example-test/test_template.py
+   $ # Running the ospf_topo1.py topology
+   $ sudo pytest -s --topology-only ospf-topo1/test_ospf_topo1.py
+
+Parameters explanation:
+
+.. program:: pytest
+
+.. option:: -s
+
+   Actives input/output capture. This is required by mininet in order to show
+   the interactive shell.
+
+.. option:: --topology-only
+
+   Don't run any tests, just build the topology.
+
+After executing the commands above, you should get the following terminal
+output:
+
+.. code:: shell
+
+   === test session starts ===
+   platform linux2 -- Python 2.7.12, pytest-3.1.2, py-1.4.34, pluggy-0.4.0
+   rootdir: /media/sf_src/topotests, inifile: pytest.ini
+   collected 3 items
+
+   ospf-topo1/test_ospf_topo1.py *** Starting controller
+
+   *** Starting 6 switches
+   switch1 switch2 switch3 switch4 switch5 switch6 ...
+   r2: frr zebra started
+   r2: frr ospfd started
+   r3: frr zebra started
+   r3: frr ospfd started
+   r1: frr zebra started
+   r1: frr ospfd started
+   r4: frr zebra started
+   r4: frr ospfd started
+   *** Starting CLI:
+   mininet>
+
+The last line shows us that we are now using the Mininet CLI (Command Line
+Interface), from here you can call your router ``vtysh`` or even bash.
+
+Here are some commands example:
+
+.. code:: shell
+
+   mininet> r1 ping 10.0.3.1
+   PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data.
+   64 bytes from 10.0.3.1: icmp_seq=1 ttl=64 time=0.576 ms
+   64 bytes from 10.0.3.1: icmp_seq=2 ttl=64 time=0.083 ms
+   64 bytes from 10.0.3.1: icmp_seq=3 ttl=64 time=0.088 ms
+   ^C
+   --- 10.0.3.1 ping statistics ---
+   3 packets transmitted, 3 received, 0% packet loss, time 1998ms
+   rtt min/avg/max/mdev = 0.083/0.249/0.576/0.231 ms
+
+
+
+   mininet> r1 ping 10.0.3.3
+   PING 10.0.3.3 (10.0.3.3) 56(84) bytes of data.
+   64 bytes from 10.0.3.3: icmp_seq=1 ttl=64 time=2.87 ms
+   64 bytes from 10.0.3.3: icmp_seq=2 ttl=64 time=0.080 ms
+   64 bytes from 10.0.3.3: icmp_seq=3 ttl=64 time=0.091 ms
+   ^C
+   --- 10.0.3.3 ping statistics ---
+   3 packets transmitted, 3 received, 0% packet loss, time 2003ms
+   rtt min/avg/max/mdev = 0.080/1.014/2.872/1.313 ms
+
+
+
+   mininet> r3 vtysh
+
+   Hello, this is FRRouting (version 3.1-devrzalamena-build).
+   Copyright 1996-2005 Kunihiro Ishiguro, et al.
+
+   frr-1# show running-config
+   Building configuration...
+
+   Current configuration:
+   !
+   frr version 3.1-devrzalamena-build
+   frr defaults traditional
+   hostname r3
+   no service integrated-vtysh-config
+   !
+   log file zebra.log
+   !
+   log file ospfd.log
+   !
+   interface r3-eth0
+    ip address 10.0.3.1/24
+   !
+   interface r3-eth1
+    ip address 10.0.10.1/24
+   !
+   interface r3-eth2
+    ip address 172.16.0.2/24
+   !
+   router ospf
+    ospf router-id 10.0.255.3
+    redistribute kernel
+    redistribute connected
+    redistribute static
+    network 10.0.3.0/24 area 0
+    network 10.0.10.0/24 area 0
+    network 172.16.0.0/24 area 1
+   !
+   line vty
+   !
+   end
+   frr-1#
+
+After you successfully configured your topology, you can obtain the
+configuration files (per-daemon) using the following commands:
+
+.. code:: shell
+
+   mininet> r3 vtysh -d ospfd
+
+   Hello, this is FRRouting (version 3.1-devrzalamena-build).
+   Copyright 1996-2005 Kunihiro Ishiguro, et al.
+
+   frr-1# show running-config
+   Building configuration...
+
+   Current configuration:
+   !
+   frr version 3.1-devrzalamena-build
+   frr defaults traditional
+   no service integrated-vtysh-config
+   !
+   log file ospfd.log
+   !
+   router ospf
+    ospf router-id 10.0.255.3
+    redistribute kernel
+    redistribute connected
+    redistribute static
+    network 10.0.3.0/24 area 0
+    network 10.0.10.0/24 area 0
+    network 172.16.0.0/24 area 1
+   !
+   line vty
+   !
+   end
+   frr-1#
+
+Writing Tests
+"""""""""""""
+
+Test topologies should always be bootstrapped from
+:file:`tests/topotests/example-test/test_template.py` because it contains
+important boilerplate code that can't be avoided, like:
+
+- imports: os, sys, pytest, topotest/topogen and mininet topology class
+- The global variable CWD (Current Working directory): which is most likely
+  going to be used to reference the routers configuration file location
+
+Example:
+
+.. code:: py
+
+   # For all registered routers, load the zebra configuration file
+   for rname, router in router_list.iteritems():
+       router.load_config(
+           TopoRouter.RD_ZEBRA,
+           os.path.join(CWD, '{}/zebra.conf'.format(rname))
+       )
+       # os.path.join() joins the CWD string with arguments adding the necessary
+       # slashes ('/'). Arguments must not begin with '/'.
+
+- The topology class that inherits from Mininet Topo class:
+
+.. code:: py
+
+   class TemplateTopo(Topo):
+     def build(self, *_args, **_opts):
+       tgen = get_topogen(self)
+       # topology build code
+
+- pytest ``setup_module()`` and ``teardown_module()`` to start the topology
+
+.. code:: py
+
+   def setup_module(_m):
+       tgen = Topogen(TemplateTopo)
+       tgen.start_topology('debug')
+
+   def teardown_module(_m):
+       tgen = get_topogen()
+       tgen.stop_topology()
+
+- ``__main__`` initialization code (to support running the script directly)
+
+.. code:: py
+
+   if __name__ == '__main__':
+       sys.exit(pytest.main(["-s"]))
+
+Requirements:
+
+- Test code should always be declared inside functions that begin with the
+  ``test_`` prefix. Functions beginning with different prefixes will not be run
+  by pytest.
+- Configuration files and long output commands should go into separated files
+  inside folders named after the equipment.
+- Tests must be able to run without any interaction. To make sure your test
+  conforms with this, run it without the :option:`-s` parameter.
+
+Tips:
+
+- Keep results in stack variables, so people inspecting code with ``pdb`` can
+  easily print their values.
+
+Don't do this:
+
+.. code:: py
+
+   assert foobar(router1, router2)
+
+Do this instead:
+
+.. code:: py
+
+   result = foobar(router1, router2)
+   assert result
+
+- Use ``assert`` messages to indicate where the test failed.
+
+Example:
+
+.. code:: py
+
+   for router in router_list:
+      # ...
+      assert condition, 'Router "{}" condition failed'.format(router.name)
+
+Debugging Execution
+^^^^^^^^^^^^^^^^^^^
+
+The most effective ways to inspect topology tests are:
+
+- Run pytest with ``--pdb`` option. This option will cause a pdb shell to
+  appear when an assertion fails
+
+Example: ``pytest -s --pdb ospf-topo1/test_ospf_topo1.py``
+
+- Set a breakpoint in the test code with ``pdb``
+
+Example:
+
+.. code:: py
+
+   # Add the pdb import at the beginning of the file
+   import pdb
+   # ...
+
+   # Add a breakpoint where you think the problem is
+   def test_bla():
+     # ...
+     pdb.set_trace()
+     # ...
+
+The `Python Debugger <https://docs.python.org/2.7/library/pdb.html>`__ (pdb)
+shell allows us to run many useful operations like:
+
+- Setting breaking point on file/function/conditions (e.g. ``break``,
+  ``condition``)
+- Inspecting variables (e.g. ``p`` (print), ``pp`` (pretty print))
+- Running python code
+
+.. tip::
+
+   The TopoGear (equipment abstraction class) implements the ``__str__`` method
+   that allows the user to inspect equipment information.
+
+Example of pdb usage:
+
+.. code:: shell
+
+   > /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(121)test_ospf_convergence()
+   -> for rnum in range(1, 5):
+   (Pdb) help
+   Documented commands (type help <topic>):
+   ========================================
+   EOF    bt         cont      enable  jump  pp       run      unt
+   a      c          continue  exit    l     q        s        until
+   alias  cl         d         h       list  quit     step     up
+   args   clear      debug     help    n     r        tbreak   w
+   b      commands   disable   ignore  next  restart  u        whatis
+   break  condition  down      j       p     return   unalias  where
+
+   Miscellaneous help topics:
+   ==========================
+   exec  pdb
+
+   Undocumented commands:
+   ======================
+   retval  rv
+
+   (Pdb) list
+   116                                   title2="Expected output")
+   117
+   118     def test_ospf_convergence():
+   119         "Test OSPF daemon convergence"
+   120         pdb.set_trace()
+   121  ->     for rnum in range(1, 5):
+   122             router = 'r{}'.format(rnum)
+   123
+   124             # Load expected results from the command
+   125             reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router))
+   126             expected = open(reffile).read()
+   (Pdb) step
+   > /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(122)test_ospf_convergence()
+   -> router = 'r{}'.format(rnum)
+   (Pdb) step
+   > /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(125)test_ospf_convergence()
+   -> reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router))
+   (Pdb) print rnum
+   1
+   (Pdb) print router
+   r1
+   (Pdb) tgen = get_topogen()
+   (Pdb) pp tgen.gears[router]
+   <lib.topogen.TopoRouter object at 0x7f74e06c9850>
+   (Pdb) pp str(tgen.gears[router])
+   'TopoGear<name="r1",links=["r1-eth0"<->"s1-eth0","r1-eth1"<->"s3-eth0"]> TopoRouter<>'
+   (Pdb) l 125
+   120         pdb.set_trace()
+   121         for rnum in range(1, 5):
+   122             router = 'r{}'.format(rnum)
+   123
+   124             # Load expected results from the command
+   125  ->         reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router))
+   126             expected = open(reffile).read()
+   127
+   128             # Run test function until we get an result. Wait at most 60 seconds.
+   129             test_func = partial(compare_show_ip_ospf, router, expected)
+   130             result, diff = topotest.run_and_expect(test_func, '',
+   (Pdb) router1 = tgen.gears[router]
+   (Pdb) router1.vtysh_cmd('show ip ospf route')
+   '============ OSPF network routing table ============\r\nN    10.0.1.0/24           [10] area: 0.0.0.0\r\n                           directly attached to r1-eth0\r\nN    10.0.2.0/24           [20] area: 0.0.0.0\r\n                           via 10.0.3.3, r1-eth1\r\nN    10.0.3.0/24           [10] area: 0.0.0.0\r\n                           directly attached to r1-eth1\r\nN    10.0.10.0/24          [20] area: 0.0.0.0\r\n                           via 10.0.3.1, r1-eth1\r\nN IA 172.16.0.0/24         [20] area: 0.0.0.0\r\n                           via 10.0.3.1, r1-eth1\r\nN IA 172.16.1.0/24         [30] area: 0.0.0.0\r\n                           via 10.0.3.1, r1-eth1\r\n\r\n============ OSPF router routing table =============\r\nR    10.0.255.2            [10] area: 0.0.0.0, ASBR\r\n                           via 10.0.3.3, r1-eth1\r\nR    10.0.255.3            [10] area: 0.0.0.0, ABR, ASBR\r\n                           via 10.0.3.1, r1-eth1\r\nR    10.0.255.4         IA [20] area: 0.0.0.0, ASBR\r\n                           via 10.0.3.1, r1-eth1\r\n\r\n============ OSPF external routing table ===========\r\n\r\n\r\n'
+    (Pdb) tgen.mininet_cli()
+    *** Starting CLI:
+    mininet>
+
+To enable more debug messages in other Topogen subsystems (like Mininet), more
+logging messages can be displayed by modifying the test configuration file
+``pytest.ini``:
+
+.. code:: ini
+
+   [topogen]
+   # Change the default verbosity line from 'info'...
+   #verbosity = info
+   # ...to 'debug'
+   verbosity = debug
+
+Instructions for use, write or debug topologies can be found in :ref:`topotests-guidelines`.
+To learn/remember common code snippets see :ref:`topotests-snippets`.
+
+Before creating a new topology, make sure that there isn't one already that
+does what you need. If nothing is similar, then you may create a new topology,
+preferably, using the newest template
+(:file:`tests/topotests/example-test/test_template.py`).
+
+.. include:: topotests-snippets.rst
+
+License
+-------
+
+All the configs and scripts are licensed under a ISC-style license. See Python
+scripts for details.
index 42a8250ae05dab766820451c20ea37ccba533fc6..ef9ebe8ddc3d4caba1e0c132a18d50f4a2612738 100644 (file)
@@ -38,11 +38,12 @@ to four distinct sets of clauses:
       the ordered entry in the route-map. See below.
 
    Call Action
-      Call to another route-map, after any :term:`Set Actions` have been carried out.
-      If the route-map called returns `deny` then processing of the route-map
-      finishes and the route is denied, regardless of the :term:Matching Policy` or
-      the :term:`Exit Policy`. If the called route-map returns `permit`, then
-      :term:`Matching Policy` and :term:`Exit Policy` govern further behaviour, as normal.
+      Call to another route-map, after any :term:`Set Actions` have been
+      carried out.  If the route-map called returns `deny` then processing of
+      the route-map finishes and the route is denied, regardless of the
+      :term:`Matching Policy` or the :term:`Exit Policy`. If the called
+      route-map returns `permit`, then :term:`Matching Policy` and :term:`Exit
+      Policy` govern further behaviour, as normal.
 
    Exit Policy
       An entry may, optionally, specify an alternative :dfn:`Exit Policy` to
index c2d32a718e59dd6329332b68987498c7db3dc8fe..a78fac8fc1d0ec7647dbfd49b3ef5aa559df9c8b 100644 (file)
@@ -56,6 +56,14 @@ keyword. At present, no sharp commands will be preserved in the config.
    log and when all routes have been successfully deleted the debug log will be
    updated with this information as well.
 
+.. index:: sharp data route
+.. clicmd:: sharp data route
+
+   Allow end user doing route install and deletion to get timing information
+   from the vty or vtysh instead of having to read the log file.  This command
+   is informational only and you should look at sharp_vty.c for explanation
+   of the output as that it may change.
+
 .. index:: sharp label
 .. clicmd:: sharp label <ipv4|ipv6> vrf NAME label (0-1000000)
 
@@ -67,3 +75,9 @@ keyword. At present, no sharp commands will be preserved in the config.
 
    Instruct zebra to monitor and notify sharp when the specified nexthop is
    changed. The notification from zebra is written into the debug log.
+
+.. index:: sharp data nexthop
+.. clicmd:: sharp data nexthop
+
+   Allow end user to dump associated data with the nexthop tracking that
+   may have been turned on.
index 876e1cac0735ade2c1fee7248b3d86b096799cb9..6033290914f4b1dae5e7559db30efc294b9eaaae 100644 (file)
@@ -301,14 +301,14 @@ void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn)
 }
 
 void show_ip_eigrp_nexthop_entry(struct vty *vty, struct eigrp *eigrp,
-                                struct eigrp_nexthop_entry *te, int *first)
+                                struct eigrp_nexthop_entry *te, bool *first)
 {
        if (te->reported_distance == EIGRP_MAX_METRIC)
                return;
 
        if (*first) {
                show_ip_eigrp_prefix_entry(vty, te->prefix);
-               *first = 0;
+               *first = false;
        }
 
        if (te->adv_router == eigrp->neighbor_self)
index 389ac1b5fddc8b93f5c72aa23ce9bff2ae980ac4..34b55ab419a930bc926c51389dd83b25972f391e 100644 (file)
@@ -156,8 +156,9 @@ extern void show_ip_eigrp_neighbor_sub(struct vty *, struct eigrp_neighbor *,
                                       int);
 extern void show_ip_eigrp_prefix_entry(struct vty *,
                                       struct eigrp_prefix_entry *);
-extern void show_ip_eigrp_nexthop_entry(struct vty *, struct eigrp *,
-                                       struct eigrp_nexthop_entry *, int *);
+extern void show_ip_eigrp_nexthop_entry(struct vty *vty, struct eigrp *eigrp,
+                                       struct eigrp_nexthop_entry *ne,
+                                       bool *first);
 
 extern void eigrp_debug_init(void);
 
index e6cfe1deea7f00127bbb6c55bf737708d4102111..4ad1005f2ff964e38cc8105accbccf7069ec0c99 100644 (file)
@@ -114,6 +114,8 @@ int eigrp_if_delete_hook(struct interface *ifp)
        eigrp = ei->eigrp;
        listnode_delete(eigrp->eiflist, ei);
 
+       eigrp_fifo_free(ei->obuf);
+
        XFREE(MTYPE_EIGRP_IF_INFO, ifp->info);
        ifp->info = NULL;
 
@@ -265,16 +267,11 @@ void eigrp_if_stream_unset(struct eigrp_interface *ei)
 {
        struct eigrp *eigrp = ei->eigrp;
 
-       if (ei->obuf) {
-               eigrp_fifo_free(ei->obuf);
-               ei->obuf = NULL;
-
-               if (ei->on_write_q) {
-                       listnode_delete(eigrp->oi_write_q, ei);
-                       if (list_isempty(eigrp->oi_write_q))
-                               thread_cancel(eigrp->t_write);
-                       ei->on_write_q = 0;
-               }
+       if (ei->on_write_q) {
+               listnode_delete(eigrp->oi_write_q, ei);
+               if (list_isempty(eigrp->oi_write_q))
+                       thread_cancel(eigrp->t_write);
+               ei->on_write_q = 0;
        }
 }
 
@@ -351,7 +348,6 @@ void eigrp_if_free(struct eigrp_interface *ei, int source)
 
        eigrp_if_down(ei);
 
-       list_delete(&ei->nbrs);
        listnode_delete(ei->eigrp->eiflist, ei);
 }
 
index 2d0ebf1bc56b083b56cb4073d2bad2383e5f6e3e..23f5a705eb40cfc02af4230a491aca5b0d55b0a0 100644 (file)
@@ -161,7 +161,7 @@ void eigrp_nexthop_entry_add(struct eigrp_prefix_entry *node,
                listnode_add_sort(node->entries, entry);
                entry->prefix = node;
 
-               eigrp_zebra_route_add(node->destination, l);
+               eigrp_zebra_route_add(node->destination, l, node->fdistance);
        }
 
        list_delete(&l);
@@ -477,7 +477,8 @@ void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix)
        successors = eigrp_topology_get_successor_max(prefix, eigrp->max_paths);
 
        if (successors) {
-               eigrp_zebra_route_add(prefix->destination, successors);
+               eigrp_zebra_route_add(prefix->destination, successors,
+                                     prefix->fdistance);
                for (ALL_LIST_ELEMENTS_RO(successors, node, entry))
                        entry->flags |= EIGRP_NEXTHOP_ENTRY_INTABLE_FLAG;
 
index 474f683989c07fbd5e75792136295f44f7c2f0e5..104f35244ea84b0589b669dd300abe32ddf7608c 100644 (file)
@@ -455,9 +455,33 @@ DEFUN (no_eigrp_neighbor,
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ip_eigrp_topology,
-       show_ip_eigrp_topology_cmd,
-       "show ip eigrp topology [all-links]",
+static void eigrp_vty_display_prefix_entry(struct vty *vty,
+                                          struct eigrp *eigrp,
+                                          struct eigrp_prefix_entry *pe,
+                                          bool all)
+{
+       bool first = true;
+       struct eigrp_nexthop_entry *te;
+       struct listnode *node;
+
+       for (ALL_LIST_ELEMENTS_RO(pe->entries, node, te)) {
+               if (all
+                   || (((te->flags
+                         & EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG)
+                        == EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG)
+                       || ((te->flags
+                            & EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG)
+                           == EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG))) {
+                       show_ip_eigrp_nexthop_entry(vty, eigrp, te,
+                                                   &first);
+                       first = false;
+               }
+       }
+}
+
+DEFPY (show_ip_eigrp_topology_all,
+       show_ip_eigrp_topology_all_cmd,
+       "show ip eigrp topology [all-links$all]",
        SHOW_STR
        IP_STR
        "IP-EIGRP show commands\n"
@@ -465,11 +489,8 @@ DEFUN (show_ip_eigrp_topology,
        "Show all links in topology table\n")
 {
        struct eigrp *eigrp;
-       struct listnode *node;
        struct eigrp_prefix_entry *tn;
-       struct eigrp_nexthop_entry *te;
        struct route_node *rn;
-       int first;
 
        eigrp = eigrp_lookup();
        if (eigrp == NULL) {
@@ -484,34 +505,62 @@ DEFUN (show_ip_eigrp_topology,
                        continue;
 
                tn = rn->info;
-               first = 1;
-               for (ALL_LIST_ELEMENTS_RO(tn->entries, node, te)) {
-                       if (argc == 5
-                           || (((te->flags
-                                 & EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG)
-                                == EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG)
-                               || ((te->flags
-                                    & EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG)
-                                   == EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG))) {
-                               show_ip_eigrp_nexthop_entry(vty, eigrp, te,
-                                                           &first);
-                               first = 0;
-                       }
-               }
+               eigrp_vty_display_prefix_entry(vty, eigrp, tn,
+                                              all ? true : false);
        }
 
        return CMD_SUCCESS;
+
 }
 
-ALIAS(show_ip_eigrp_topology, show_ip_eigrp_topology_detail_cmd,
-      "show ip eigrp topology <A.B.C.D|A.B.C.D/M|detail|summary>",
-      SHOW_STR IP_STR
-      "IP-EIGRP show commands\n"
-      "IP-EIGRP topology\n"
-      "Netwok to display information about\n"
-      "IP prefix <network>/<length>, e.g., 192.168.0.0/16\n"
-      "Show all links in topology table\n"
-      "Show a summary of the topology table\n")
+DEFPY (show_ip_eigrp_topology,
+       show_ip_eigrp_topology_cmd,
+       "show ip eigrp topology <A.B.C.D$address|A.B.C.D/M$prefix>",
+       SHOW_STR
+       IP_STR
+       "IP-EIGRP show commands\n"
+       "IP-EIGRP topology\n"
+       "For a specific address\n"
+       "For a specific prefix\n")
+{
+       struct eigrp *eigrp;
+       struct eigrp_prefix_entry *tn;
+       struct route_node *rn;
+       struct prefix cmp;
+
+       eigrp = eigrp_lookup();
+       if (eigrp == NULL) {
+               vty_out(vty, " EIGRP Routing Process not enabled\n");
+               return CMD_SUCCESS;
+       }
+
+       show_ip_eigrp_topology_header(vty, eigrp);
+
+       if (address_str)
+               prefix_str = address_str;
+
+       if (str2prefix(prefix_str, &cmp) < 0) {
+               vty_out(vty, "%% Malformed address\n");
+               return CMD_WARNING;
+       }
+
+       rn = route_node_match(eigrp->topology_table, &cmp);
+       if (!rn) {
+               vty_out(vty, "%% Network not in table\n");
+               return CMD_WARNING;
+       }
+
+       if (!rn->info) {
+               vty_out(vty, "%% Network not in table\n");
+               route_unlock_node(rn);
+               return CMD_WARNING;
+       }
+
+       tn = rn->info;
+       eigrp_vty_display_prefix_entry(vty, eigrp, tn, argc == 5);
+
+       return CMD_SUCCESS;
+}
 
 DEFUN (show_ip_eigrp_interfaces,
        show_ip_eigrp_interfaces_cmd,
@@ -1485,8 +1534,7 @@ void eigrp_vty_show_init(void)
        install_element(VIEW_NODE, &show_ip_eigrp_neighbors_cmd);
 
        install_element(VIEW_NODE, &show_ip_eigrp_topology_cmd);
-
-       install_element(VIEW_NODE, &show_ip_eigrp_topology_detail_cmd);
+       install_element(VIEW_NODE, &show_ip_eigrp_topology_all_cmd);
 }
 
 /* eigrpd's interface node. */
index a810e0146851090d6b0cbb9c53ef01919496b694..09d876afaa2c4ddd0e07916f038943b6dacd16ce 100644 (file)
@@ -353,7 +353,8 @@ static struct interface *zebra_interface_if_lookup(struct stream *s)
        return if_lookup_by_name(ifname_tmp, VRF_DEFAULT);
 }
 
-void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
+void eigrp_zebra_route_add(struct prefix *p, struct list *successors,
+                          uint32_t distance)
 {
        struct zapi_route api;
        struct zapi_nexthop *api_nh;
@@ -368,9 +369,11 @@ void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
        api.vrf_id = VRF_DEFAULT;
        api.type = ZEBRA_ROUTE_EIGRP;
        api.safi = SAFI_UNICAST;
+       api.metric = distance;
        memcpy(&api.prefix, p, sizeof(*p));
 
        SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+       SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
 
        /* Nexthop, ifindex, distance and metric information. */
        for (ALL_LIST_ELEMENTS_RO(successors, node, te)) {
index 1c418dddef61c2f38833c32ef78c7117e58a7a61..86b337cfe685f686c91207e8388bf7a9c297c9f3 100644 (file)
@@ -33,7 +33,8 @@
 
 extern void eigrp_zebra_init(void);
 
-extern void eigrp_zebra_route_add(struct prefix *, struct list *);
+extern void eigrp_zebra_route_add(struct prefix *, struct list *,
+                                 uint32_t distance);
 extern void eigrp_zebra_route_delete(struct prefix *);
 extern int eigrp_redistribute_set(struct eigrp *, int, struct eigrp_metrics);
 extern int eigrp_redistribute_unset(struct eigrp *, int);
index 815de513fc592e70366efd6bc61178cf60ea6815..20f3e62a7418bdd147d43b7082eaa36b4d6b7954 100644 (file)
@@ -338,12 +338,14 @@ static void isis_redist_routemap_set(struct isis_redist *redist,
 {
        if (redist->map_name) {
                XFREE(MTYPE_ISIS, redist->map_name);
+               route_map_counter_decrement(redist->map);
                redist->map = NULL;
        }
 
        if (routemap && strlen(routemap)) {
                redist->map_name = XSTRDUP(MTYPE_ISIS, routemap);
                redist->map = route_map_lookup_by_name(routemap);
+               route_map_counter_increment(redist->map);
        }
 }
 
index 12a1d7fbe04062a1c8ae24863c568a8ea00b2878..c424a5bc98ae1d31df7cc6563af701cbbeec8308 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -29,6 +29,7 @@
 #include "memory.h"
 #include "command.h"
 #include "lib_errors.h"
+#include "lib/hook.h"
 
 #ifndef SUNOS_5
 #include <sys/un.h>
 
 DEFINE_MTYPE_STATIC(LIB, ZLOG, "Logging")
 
+/* hook for external logging */
+DEFINE_HOOK(zebra_ext_log, (int priority, const char *format, va_list args),
+           (priority, format, args));
+
 static int logfile_fd = -1; /* Used in signal handler. */
 
 struct zlog *zlog_default = NULL;
@@ -213,6 +218,9 @@ void vzlog(int priority, const char *format, va_list args)
        tsctl.already_rendered = 0;
        struct zlog *zl = zlog_default;
 
+       /* call external hook */
+       hook_call(zebra_ext_log, priority, format, args);
+
        /* When zlog_default is also NULL, use stderr for logging. */
        if (zl == NULL) {
                tsctl.precision = 0;
@@ -1019,6 +1027,7 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK),
        DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI),
        DESC_ENTRY(ZEBRA_ADVERTISE_DEFAULT_GW),
+       DESC_ENTRY(ZEBRA_ADVERTISE_SVI_MACIP),
        DESC_ENTRY(ZEBRA_ADVERTISE_SUBNET),
        DESC_ENTRY(ZEBRA_LOCAL_ES_ADD),
        DESC_ENTRY(ZEBRA_LOCAL_ES_DEL),
index be1d9fb5922896b083a2009a4f2fb577a833b5b3..8fb98a02aba84d6ab426e48f9972b8333a005d94 100644 (file)
--- a/lib/log.h
+++ b/lib/log.h
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdio.h>
+#include <stdarg.h>
+#include "lib/hook.h"
+
+/* Hook for external logging function */
+DECLARE_HOOK(zebra_ext_log, (int priority, const char *format, va_list args),
+            (priority, format, args));
 
 /* Here is some guidance on logging levels to use:
  *
index fee23a75ac67e1d11463c102b2e68a87444ba1b5..149e294d500108f52af0f1172fbe5137e763d42c 100644 (file)
@@ -35,7 +35,6 @@ struct memgroup **mg_insert = &mg_first;
 
 DEFINE_MGROUP(LIB, "libfrr")
 DEFINE_MTYPE(LIB, TMP, "Temporary memory")
-DEFINE_MTYPE(LIB, PREFIX_FLOWSPEC, "Prefix Flowspec")
 
 static inline void mt_count_alloc(struct memtype *mt, size_t size, void *ptr)
 {
index 2d6c1447786a467d39fc147acb981947380ad996..1a0269f8bb1fc6adce96cc75c5c21af36e3dcaad 100644 (file)
@@ -137,7 +137,6 @@ struct memgroup {
 
 DECLARE_MGROUP(LIB)
 DECLARE_MTYPE(TMP)
-DECLARE_MTYPE(PREFIX_FLOWSPEC)
 
 
 extern void *qmalloc(struct memtype *mt, size_t size)
index 07eb1785b7f911bddf536bcb2220d18bb4882fe3..babd4304d13f29a47ef9e6778266be63b328ea66 100644 (file)
@@ -30,6 +30,7 @@
 #include "lib_errors.h"
 
 DEFINE_MTYPE_STATIC(LIB, PREFIX, "Prefix")
+DEFINE_MTYPE_STATIC(LIB, PREFIX_FLOWSPEC, "Prefix Flowspec")
 
 /* Maskbit. */
 static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
index 7435272761c631f5ddd69121ee4a0684363f9462..f297096633140f327af9c0a1b5307c49855d8a53 100755 (executable)
@@ -121,7 +121,7 @@ sub codelist {
        }
        $str =~ s/ $//;
        push @lines, $str . "\\n\" \\\n";
-       push @lines, "  \"       > - selected route, * - FIB route, q - queued route, f - failed route\\n\\n\"";
+       push @lines, "  \"       > - selected route, * - FIB route, q - queued route, r - rejected route\\n\\n\"";
        return join("", @lines);
 }
 
index 5c6d106d8392bfb8b985caf4019239e8fdda2c28..61e597520e6daf11b67290e76e2f52f44a7d8418 100644 (file)
@@ -1007,6 +1007,34 @@ static int vty_show_route_map(struct vty *vty, const char *name)
        return CMD_SUCCESS;
 }
 
+/* Unused route map details */
+static int vty_show_unused_route_map(struct vty *vty)
+{
+       struct list *maplist = list_new();
+       struct listnode *ln;
+       struct route_map *map;
+
+       for (map = route_map_master.head; map; map = map->next) {
+               /* If use_count is zero, No protocol is using this routemap.
+                * so adding to the list.
+                */
+               if (!map->use_count)
+                       listnode_add(maplist, map);
+       }
+
+       if (maplist->count > 0) {
+               vty_out(vty, "\n%s:\n", frr_protonameinst);
+               list_sort(maplist, sort_route_map);
+
+               for (ALL_LIST_ELEMENTS_RO(maplist, ln, map))
+                       vty_show_route_map_entry(vty, map);
+       } else {
+               vty_out(vty, "\n%s: None\n", frr_protonameinst);
+       }
+
+       list_delete(&maplist);
+       return CMD_SUCCESS;
+}
 
 /* New route map allocation. Please note route map's name must be
    specified. */
@@ -2759,6 +2787,15 @@ DEFUN (rmap_show_name,
        return vty_show_route_map(vty, name);
 }
 
+DEFUN (rmap_show_unused,
+       rmap_show_unused_cmd,
+       "show route-map-unused",
+       SHOW_STR
+       "unused route-map information\n")
+{
+       return vty_show_unused_route_map(vty);
+}
+
 DEFUN (rmap_call,
        rmap_call_cmd,
        "call WORD",
@@ -2949,6 +2986,23 @@ static void rmap_autocomplete(vector comps, struct cmd_token *token)
                vector_set(comps, XSTRDUP(MTYPE_COMPLETION, map->name));
 }
 
+/* Increment the use_count counter while attaching the route map */
+void route_map_counter_increment(struct route_map *map)
+{
+       if (map)
+               map->use_count++;
+}
+
+/* Decrement the use_count counter while detaching the route map. */
+void route_map_counter_decrement(struct route_map *map)
+{
+       if (map) {
+               if (map->use_count <= 0)
+                       return;
+               map->use_count--;
+       }
+}
+
 static const struct cmd_variable_handler rmap_var_handlers[] = {
        {/* "route-map WORD" */
         .varname = "route_map",
@@ -3006,6 +3060,7 @@ void route_map_init(void)
 
        /* Install show command */
        install_element(ENABLE_NODE, &rmap_show_name_cmd);
+       install_element(ENABLE_NODE, &rmap_show_unused_cmd);
 
        install_element(RMAP_NODE, &match_interface_cmd);
        install_element(RMAP_NODE, &no_match_interface_cmd);
index 463aa91725a98b64b10a7516c9a5320fb641af7c..6fd88ba5de831e7bb43e695e39695e76a138347d 100644 (file)
@@ -169,6 +169,9 @@ struct route_map {
        /* How many times have we applied this route-map */
        uint64_t applied;
 
+       /* Counter to track active usage of this route-map */
+       uint16_t use_count;
+
        QOBJ_FIELDS
 };
 DECLARE_QOBJ_TYPE(route_map)
@@ -379,4 +382,10 @@ extern void route_map_no_set_tag_hook(int (*func)(struct vty *vty,
 extern void *route_map_rule_tag_compile(const char *arg);
 extern void route_map_rule_tag_free(void *rule);
 
+/* Increment the route-map used counter */
+extern void route_map_counter_increment(struct route_map *map);
+
+/* Decrement the route-map used counter */
+extern void route_map_counter_decrement(struct route_map *map);
+
 #endif /* _ZEBRA_ROUTEMAP_H */
index 24ef24c7744930fb8978ad40d41112c4a0fad91c..fa69ec600ec93180ea90ac4e4c27c143601f2991 100644 (file)
@@ -99,8 +99,10 @@ struct work_queue *work_queue_new(struct thread_master *m,
        return new;
 }
 
-void work_queue_free_original(struct work_queue *wq)
+void work_queue_free_and_null(struct work_queue **wqp)
 {
+       struct work_queue *wq = *wqp;
+
        if (wq->thread != NULL)
                thread_cancel(wq->thread);
 
@@ -114,13 +116,8 @@ void work_queue_free_original(struct work_queue *wq)
 
        XFREE(MTYPE_WORK_QUEUE_NAME, wq->name);
        XFREE(MTYPE_WORK_QUEUE, wq);
-       return;
-}
 
-void work_queue_free_and_null(struct work_queue **wq)
-{
-       work_queue_free_original(*wq);
-       *wq = NULL;
+       *wqp = NULL;
 }
 
 bool work_queue_is_scheduled(struct work_queue *wq)
index 7c846550631df99d904f79aca57eb094e3007589..cbbacc0561522514563ed88e06fa832f0218a785 100644 (file)
@@ -159,19 +159,10 @@ extern struct work_queue *work_queue_new(struct thread_master *, const char *);
  * The usage of work_queue_free is being transitioned to pass
  * in the double pointer to remove use after free's.
  */
-#if CONFDATE > 20190205
-CPP_NOTICE("work_queue_free without double pointer is deprecated, please fixup")
-#endif
-extern void work_queue_free_and_null(struct work_queue **);
-extern void work_queue_free_original(struct work_queue *);
-#define work_queue_free(X)                                                     \
-       do {                                                                   \
-               work_queue_free_original((X));                                 \
-               CPP_WARN("Please use work_queue_free_and_null");               \
-       } while (0)
+extern void work_queue_free_and_null(struct work_queue **wqp);
 
 /* Add the supplied data as an item onto the workqueue */
-extern void work_queue_add(struct work_queue *, void *);
+extern void work_queue_add(struct work_queue *wq, void *item);
 
 /* plug the queue, ie prevent it from being drained / processed */
 extern void work_queue_plug(struct work_queue *wq);
index a01da776691df59af7965bb2893670b102e1fb5e..9db1dd74f2d91421a679ffbbfa8778ee13b84fcf 100644 (file)
@@ -414,9 +414,6 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
        /* We need router-id information. */
        zebra_message_send(zclient, ZEBRA_ROUTER_ID_ADD, vrf_id);
 
-       /* We need interface information. */
-       zebra_message_send(zclient, ZEBRA_INTERFACE_ADD, vrf_id);
-
        /* Set unwanted redistribute route. */
        for (afi = AFI_IP; afi < AFI_MAX; afi++)
                vrf_bitmap_set(zclient->redist[afi][zclient->redist_default],
@@ -481,9 +478,6 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
        /* We need router-id information. */
        zebra_message_send(zclient, ZEBRA_ROUTER_ID_DELETE, vrf_id);
 
-       /* We need interface information. */
-       zebra_message_send(zclient, ZEBRA_INTERFACE_DELETE, vrf_id);
-
        /* Set unwanted redistribute route. */
        for (afi = AFI_IP; afi < AFI_MAX; afi++)
                vrf_bitmap_unset(zclient->redist[afi][zclient->redist_default],
@@ -596,6 +590,8 @@ int zclient_start(struct zclient *zclient)
 
        zebra_hello_send(zclient);
 
+       zebra_message_send(zclient, ZEBRA_INTERFACE_ADD, VRF_DEFAULT);
+
        /* Inform the successful connection. */
        if (zclient->zebra_connected)
                (*zclient->zebra_connected)(zclient);
index e00821f2f67a1577535fcc709fd88713200a6981..3a054e5e7213e8f6a5eff878e9dcdc34321f1d14 100644 (file)
@@ -125,6 +125,7 @@ typedef enum {
        ZEBRA_FEC_UNREGISTER,
        ZEBRA_FEC_UPDATE,
        ZEBRA_ADVERTISE_DEFAULT_GW,
+       ZEBRA_ADVERTISE_SVI_MACIP,
        ZEBRA_ADVERTISE_SUBNET,
        ZEBRA_ADVERTISE_ALL_VNI,
        ZEBRA_LOCAL_ES_ADD,
index 671267aa05e7ace5f568db226f6db7af91ae3615..3153c29aa18ae66998f3b68435536a78f8b0b68a 100644 (file)
@@ -856,16 +856,22 @@ void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry)
 
 static void ospf6_asbr_routemap_set(int type, const char *mapname)
 {
-       if (ospf6->rmap[type].name)
+       if (ospf6->rmap[type].name) {
+               route_map_counter_decrement(ospf6->rmap[type].map);
                free(ospf6->rmap[type].name);
+       }
        ospf6->rmap[type].name = strdup(mapname);
        ospf6->rmap[type].map = route_map_lookup_by_name(mapname);
+       route_map_counter_increment(ospf6->rmap[type].map);
 }
 
 static void ospf6_asbr_routemap_unset(int type)
 {
        if (ospf6->rmap[type].name)
                free(ospf6->rmap[type].name);
+
+       route_map_counter_decrement(ospf6->rmap[type].map);
+
        ospf6->rmap[type].name = NULL;
        ospf6->rmap[type].map = NULL;
 }
@@ -939,6 +945,10 @@ static void ospf6_asbr_routemap_update(const char *mapname)
                                                "%s: route-map %s update, reset redist %s",
                                                __PRETTY_FUNCTION__, mapname,
                                                ZROUTE_NAME(type));
+
+                               route_map_counter_increment(
+                                       ospf6->rmap[type].map);
+
                                ospf6_asbr_distribute_list_update(type);
                        }
                } else
index 30f5a2a80e54030326f12a74805477a17b56a41c..ecc55c2ee5ec0ee0611daf5381c4947f6cdb2b7f 100644 (file)
@@ -2098,10 +2098,22 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
 
                if (current == NULL
                    || (ret = ospf_lsa_more_recent(current, lsa)) < 0) {
+                       /* CVE-2017-3224 */
+                       if (current && (lsa->data->ls_seqnum ==
+                                       htonl(OSPF_MAX_SEQUENCE_NUMBER)
+                                       && !IS_LSA_MAXAGE(lsa))) {
+                               zlog_debug(
+                                       "Link State Update[%s]: has Max Seq but not MaxAge. Dropping it",
+                                       dump_lsa_key(lsa));
+
+                               DISCARD_LSA(lsa, 4);
+                               continue;
+                       }
+
                        /* Actual flooding procedure. */
                        if (ospf_flood(oi->ospf, nbr, current, lsa)
                            < 0) /* Trap NSSA later. */
-                               DISCARD_LSA(lsa, 4);
+                               DISCARD_LSA(lsa, 5);
                        continue;
                }
 
@@ -2158,7 +2170,7 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
                                                        oi->ls_ack,
                                                        ospf_lsa_lock(lsa));
 
-                               DISCARD_LSA(lsa, 5);
+                               DISCARD_LSA(lsa, 6);
                        } else
                        /* Acknowledge the receipt of the LSA by sending a
                           Link State Acknowledgment packet back out the
@@ -2166,7 +2178,7 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
                           interface. */
                        {
                                ospf_ls_ack_send(nbr, lsa);
-                               DISCARD_LSA(lsa, 6);
+                               DISCARD_LSA(lsa, 7);
                        }
                }
 
@@ -2183,7 +2195,7 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
                        if (IS_LSA_MAXAGE(current)
                            && current->data->ls_seqnum
                                       == htonl(OSPF_MAX_SEQUENCE_NUMBER)) {
-                               DISCARD_LSA(lsa, 7);
+                               DISCARD_LSA(lsa, 8);
                        }
                        /* Otherwise, as long as the database copy has not been
                           sent in a
@@ -2206,7 +2218,7 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
                                        ospf_ls_upd_send_lsa(
                                                nbr, current,
                                                OSPF_SEND_PACKET_DIRECT);
-                               DISCARD_LSA(lsa, 8);
+                               DISCARD_LSA(lsa, 9);
                        }
                }
        }
index 54009639fc37ea03af10f486c15fbdb3b580182b..a15e605aca1f49b93dae44b4759be818feaf7f7a 100644 (file)
@@ -70,11 +70,19 @@ static void ospf_route_map_update(const char *name)
                                        /* Keep old route-map. */
                                        struct route_map *old = ROUTEMAP(red);
 
-                                       /* Update route-map. */
-                                       ROUTEMAP(red) =
-                                               route_map_lookup_by_name(
-                                                       ROUTEMAP_NAME(red));
-
+                                       if (!old) {
+                                               /* Route-map creation */
+                                               /* Update route-map. */
+                                               ROUTEMAP(red) =
+                                                       route_map_lookup_by_name(
+                                                               ROUTEMAP_NAME(red));
+
+                                                       route_map_counter_increment(
+                                                               ROUTEMAP(red));
+                                       } else {
+                                               /* Route-map deletion */
+                                               ROUTEMAP(red) = NULL;
+                                       }
                                        /* No update for this distribute type.
                                         */
                                        if (old == NULL
index a86800f901c3baf0e6750f14bfcc94ffde1799a4..ea2c492e183e6c64ab90db27fa2d778052388c4d 100644 (file)
@@ -983,17 +983,22 @@ int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei,
 /* OSPF route-map set for redistribution */
 void ospf_routemap_set(struct ospf_redist *red, const char *name)
 {
-       if (ROUTEMAP_NAME(red))
+       if (ROUTEMAP_NAME(red)) {
+               route_map_counter_decrement(ROUTEMAP(red));
                free(ROUTEMAP_NAME(red));
+       }
 
        ROUTEMAP_NAME(red) = strdup(name);
        ROUTEMAP(red) = route_map_lookup_by_name(name);
+       route_map_counter_increment(ROUTEMAP(red));
 }
 
 void ospf_routemap_unset(struct ospf_redist *red)
 {
-       if (ROUTEMAP_NAME(red))
+       if (ROUTEMAP_NAME(red)) {
+               route_map_counter_decrement(ROUTEMAP(red));
                free(ROUTEMAP_NAME(red));
+       }
 
        ROUTEMAP_NAME(red) = NULL;
        ROUTEMAP(red) = NULL;
index 7089e21513c7d41c111ccc7ed74c098c73eedfe8..d2d2445a1553539faa26e48fd11025a8fab248d7 100644 (file)
 #include "pim_bfd.h"
 #include "bfd.h"
 
+#ifndef VTYSH_EXTRACT_PL
+#include "pimd/pim_cmd_clippy.c"
+#endif
+
 static struct cmd_node interface_node = {
        INTERFACE_NODE, "%s(config-if)# ", 1 /* vtysh ? yes */
 };
@@ -5138,6 +5142,12 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
+       if (result == PIM_GROUP_BAD_ADDR_MASK_COMBO) {
+               vty_out(vty, "%% Inconsistent address and mask: %s\n",
+                       group);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
        return CMD_SUCCESS;
 }
 
@@ -6394,6 +6404,31 @@ static int pim_cmd_interface_add(struct interface *ifp)
        return 1;
 }
 
+DEFPY_HIDDEN (interface_ip_pim_activeactive,
+             interface_ip_pim_activeactive_cmd,
+             "[no$no] ip pim active-active",
+             NO_STR
+             IP_STR
+             PIM_STR
+             "Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct pim_interface *pim_ifp;
+
+       if (!no && !pim_cmd_interface_add(ifp)) {
+               vty_out(vty, "Could not enable PIM SM active-active on interface\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       pim_ifp = ifp->info;
+       if (no)
+               pim_ifp->activeactive = false;
+       else
+               pim_ifp->activeactive = true;
+
+       return CMD_SUCCESS;
+}
+
 DEFUN_HIDDEN (interface_ip_pim_ssm,
        interface_ip_pim_ssm_cmd,
        "ip pim ssm",
@@ -8722,6 +8757,7 @@ void pim_cmd_init(void)
                        &interface_ip_igmp_query_max_response_time_dsec_cmd);
        install_element(INTERFACE_NODE,
                        &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
+       install_element(INTERFACE_NODE, &interface_ip_pim_activeactive_cmd);
        install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
        install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
        install_element(INTERFACE_NODE, &interface_ip_pim_sm_cmd);
index 0451ab1e71695e103561fe7c72c91dfceaeeae28..6933f4d5bd0af0457e1134bee61e79db40f0ecb4 100644 (file)
@@ -170,6 +170,8 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
        pim_ifp->sec_addr_list->cmp =
                (int (*)(void *, void *))pim_sec_addr_comp;
 
+       pim_ifp->activeactive = false;
+
        RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
 
        ifp->info = pim_ifp;
index a7dc097f882cbda1a7237e2391313ef2c744c063..5066998cb53bcb75a157ffda9f3e0cd6dcf45adf 100644 (file)
@@ -124,6 +124,9 @@ struct pim_interface {
        /* boundary prefix-list */
        char *boundary_oil_plist;
 
+       /* Turn on Active-Active for this interface */
+       bool activeactive;
+
        int64_t pim_ifstat_start; /* start timestamp for stats */
        uint32_t pim_ifstat_hello_sent;
        uint32_t pim_ifstat_hello_sendfail;
index 1290bfe56b153d4ec3e658bbf56cd20c05f0ee70..2e12d728cfd4d68927ffc2420d0e0d296ec0d7ef 100644 (file)
@@ -392,8 +392,10 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
        if (channel_oil->oif_flags[pim_ifp->mroute_vif_index]
            & PIM_OIF_FLAG_PROTO_ANY) {
 
-               channel_oil->oif_creation[pim_ifp->mroute_vif_index] =
-                       pim_time_monotonic_sec();
+               /* Updating time here is not required as this time has to
+                * indicate when the interface is added
+                */
+
                channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask;
                /* Check the OIF really exists before returning, and only log
                   warning otherwise */
index 6b76794b75eecdfd6499975c409505fa0a50a9e4..08f2ffc4ea5396794b3d5ae46c41d83c11de8de4 100644 (file)
@@ -345,6 +345,7 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
        struct rp_info *tmp_rp_info;
        char buffer[BUFSIZ];
        struct prefix nht_p;
+       struct prefix temp;
        struct pim_nexthop_cache pnc;
        struct route_node *rn;
 
@@ -352,8 +353,17 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
 
        if (group_range == NULL)
                result = str2prefix("224.0.0.0/4", &rp_info->group);
-       else
+       else {
                result = str2prefix(group_range, &rp_info->group);
+               if (result) {
+                       prefix_copy(&temp, &rp_info->group);
+                       apply_mask(&temp);
+                       if (!prefix_same(&rp_info->group, &temp)) {
+                               XFREE(MTYPE_PIM_RP, rp_info);
+                               return PIM_GROUP_BAD_ADDR_MASK_COMBO;
+                       }
+               }
+       }
 
        if (!result) {
                XFREE(MTYPE_PIM_RP, rp_info);
index f6385a0ac9ef7ca214d1fffe14f4ff03eb4c58a2..649578874842e9855b61906a35b36b38326167d3 100644 (file)
@@ -362,6 +362,9 @@ int pim_interface_config_write(struct vty *vty)
                                        }
                                }
 
+                               if (pim_ifp->activeactive)
+                                       vty_out(vty, " ip pim active-active\n");
+
                                /* boundary */
                                if (pim_ifp->boundary_oil_plist) {
                                        vty_out(vty,
index b7111cf7bf2d21a024d3fd89eabf05a697cb694a..11ca6e8a108010bba7a44ff19fca425c5b6af770 100644 (file)
@@ -267,6 +267,27 @@ static int pim_zebra_if_state_down(int command, struct zclient *zclient,
        return 0;
 }
 
+static int pim_zebra_interface_vrf_update(int command, struct zclient *zclient,
+                                         zebra_size_t length, vrf_id_t vrf_id)
+{
+       struct interface *ifp;
+       vrf_id_t new_vrf_id;
+
+       ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
+                                             &new_vrf_id);
+       if (!ifp)
+               return 0;
+
+       if (PIM_DEBUG_ZEBRA)
+               zlog_debug("%s: %s updating from %u to %u",
+                          __PRETTY_FUNCTION__,
+                          ifp->name, vrf_id, new_vrf_id);
+
+       if_update_to_new_vrf(ifp, new_vrf_id);
+
+       return 0;
+}
+
 #ifdef PIM_DEBUG_IFADDR_DUMP
 static void dump_if_address(struct interface *ifp)
 {
@@ -762,6 +783,7 @@ void pim_zebra_init(void)
        zclient->interface_down = pim_zebra_if_state_down;
        zclient->interface_address_add = pim_zebra_if_address_add;
        zclient->interface_address_delete = pim_zebra_if_address_del;
+       zclient->interface_vrf_update = pim_zebra_interface_vrf_update;
        zclient->nexthop_update = pim_parse_nexthop_update;
 
        zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
index 73ea9f82c4ec569a9d8c08c90a5c350231f72bda..50c19658dab044f4cc528d369bb8f87c0209d49e 100644 (file)
 /* Remember 32 bits!!! */
 
 /* PIM error codes */
-#define PIM_SUCCESS                0
-#define PIM_GROUP_BAD_ADDRESS     -2
-#define PIM_GROUP_OVERLAP         -3
-#define PIM_GROUP_PFXLIST_OVERLAP -4
-#define PIM_RP_BAD_ADDRESS        -5
-#define PIM_RP_NO_PATH            -6
-#define PIM_RP_NOT_FOUND          -7
-#define PIM_RP_PFXLIST_IN_USE     -8
-#define PIM_IFACE_NOT_FOUND       -9
-#define PIM_UPDATE_SOURCE_DUP     -10
+#define PIM_SUCCESS                      0
+#define PIM_GROUP_BAD_ADDRESS           -2
+#define PIM_GROUP_OVERLAP               -3
+#define PIM_GROUP_PFXLIST_OVERLAP       -4
+#define PIM_RP_BAD_ADDRESS              -5
+#define PIM_RP_NO_PATH                  -6
+#define PIM_RP_NOT_FOUND                -7
+#define PIM_RP_PFXLIST_IN_USE           -8
+#define PIM_IFACE_NOT_FOUND             -9
+#define PIM_UPDATE_SOURCE_DUP           -10
+#define PIM_GROUP_BAD_ADDR_MASK_COMBO   -11
 
 const char *const PIM_ALL_SYSTEMS;
 const char *const PIM_ALL_ROUTERS;
index 99701430c59588be5d92c7b20ebe0e799ffbc779..7d8df7d1053b3c84e5d48804e354648e9fc5524f 100644 (file)
@@ -115,6 +115,9 @@ noinst_HEADERS += \
        pimd/mtracebis_routeget.h \
        # end
 
+pimd/pim_cmd_clippy.c: $(CLIPPY_DEPS)
+pimd/pim_cmd.$(OBJEXT): pimd/pim_cmd_clippy.c
+
 pimd_pimd_LDADD = pimd/libpim.a lib/libfrr.la $(LIBCAP)
 pimd_pimd_SOURCES = pimd/pim_main.c
 
index 3ae0aabfe2a61ac746b090726f1ad595e82f8a11..01934a94e2ef0126576a11fd7aac129c7433ac44 100644 (file)
@@ -1,6 +1,8 @@
 [Unit]
 Description=FRRouting (FRR)
-After=syslog.target networking.service
+Wants=network.target
+After=network-pre.target systemd-sysctl.service
+Before=network.target
 OnFailure=heartbeat-failed@%n.service
 
 [Service]
@@ -19,5 +21,4 @@ ExecStop=/usr/lib/frr/frr stop
 ExecReload=/usr/lib/frr/frr reload
 
 [Install]
-WantedBy=network-online.target
-
+WantedBy=multi-user.target
index 0ce5324057cf849c30483021df4013e40dc54d60..38b4aed5bcebeb7872beaab227524916a64bcda4 100644 (file)
@@ -3438,10 +3438,13 @@ static void rip_routemap_update_redistribute(void)
 
        if (rip) {
                for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
-                       if (rip->route_map[i].name)
+                       if (rip->route_map[i].name) {
                                rip->route_map[i].map =
                                        route_map_lookup_by_name(
                                                rip->route_map[i].name);
+                               route_map_counter_increment(
+                                       rip->route_map[i].map);
+                       }
                }
        }
 }
index 0022c726c5eb43f4ee3bb2358f4febf45fd3c8ec..70655beff1e1e1b4e86f18e6a81510445d6b460c 100644 (file)
@@ -2522,10 +2522,13 @@ static void ripng_routemap_update_redistribute(void)
 
        if (ripng) {
                for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
-                       if (ripng->route_map[i].name)
+                       if (ripng->route_map[i].name) {
                                ripng->route_map[i].map =
                                        route_map_lookup_by_name(
                                                ripng->route_map[i].name);
+                               route_map_counter_increment(
+                                       ripng->route_map[i].map);
+                       }
                }
        }
 }
diff --git a/sharpd/sharp_globals.h b/sharpd/sharp_globals.h
new file mode 100644 (file)
index 0000000..065fb09
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * SHARP - code to track globals
+ * Copyright (C) 2019 Cumulus Networks, Inc.
+ *               Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __SHARP_GLOBAL_H__
+#define __SHARP_GLOBAL_H__
+
+DECLARE_MGROUP(SHARPD)
+
+struct sharp_routes {
+       /* The original prefix for route installation */
+       struct prefix orig_prefix;
+
+       /* The nexthop group we are using for installation */
+       struct nexthop nhop;
+       struct nexthop_group nhop_group;
+
+       uint32_t total_routes;
+       uint32_t installed_routes;
+       uint32_t removed_routes;
+       int32_t repeat;
+
+       uint8_t inst;
+
+       struct timeval t_start;
+       struct timeval t_end;
+};
+
+struct sharp_global {
+       /* Global data about route install/deletions */
+       struct sharp_routes r;
+
+       /* The list of nexthops that we are watching and data about them */
+       struct list *nhs;
+};
+
+extern struct sharp_global sg;
+#endif
index 175a276089b6962b1e0ad8a3cdc707c3501411e3..39453ee9adc1d49e6a2ad1047d65878818673ab2 100644 (file)
 
 #include "sharp_zebra.h"
 #include "sharp_vty.h"
+#include "sharp_globals.h"
 
-uint32_t total_routes = 0;
-uint32_t installed_routes = 0;
-uint32_t removed_routes = 0;
+DEFINE_MGROUP(SHARPD, "sharpd")
 
 zebra_capabilities_t _caps_p[] = {
 };
@@ -125,7 +124,13 @@ FRR_DAEMON_INFO(sharpd, SHARP, .vty_port = SHARP_VTY_PORT,
                .privs = &sharp_privs, .yang_modules = sharpd_yang_modules,
                .n_yang_modules = array_size(sharpd_yang_modules), )
 
-extern void sharp_vty_init(void);
+struct sharp_global sg;
+
+static void sharp_global_init(void)
+{
+       memset(&sg, 0, sizeof(sg));
+       sg.nhs = list_new();
+}
 
 int main(int argc, char **argv, char **envp)
 {
@@ -151,6 +156,8 @@ int main(int argc, char **argv, char **envp)
 
        master = frr_init();
 
+       sharp_global_init();
+
        nexthop_group_init(NULL, NULL, NULL, NULL);
        vrf_init(NULL, NULL, NULL, NULL, NULL);
 
diff --git a/sharpd/sharp_nht.c b/sharpd/sharp_nht.c
new file mode 100644 (file)
index 0000000..174f186
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SHARP - code to track nexthops
+ * Copyright (C) Cumulus Networks, Inc.
+ *               Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include "memory.h"
+#include "nexthop.h"
+#include "nexthop_group.h"
+#include "vty.h"
+
+#include "sharp_nht.h"
+#include "sharp_globals.h"
+
+DEFINE_MTYPE_STATIC(SHARPD, NH_TRACKER, "Nexthop Tracker")
+
+struct sharp_nh_tracker *sharp_nh_tracker_get(struct prefix *p)
+{
+       struct listnode *node;
+       struct sharp_nh_tracker *nht;
+
+       for (ALL_LIST_ELEMENTS_RO(sg.nhs, node, nht)) {
+               if (prefix_same(&nht->p, p))
+                       break;
+       }
+
+       if (nht)
+               return nht;
+
+       nht = XCALLOC(MTYPE_NH_TRACKER, sizeof(*nht));
+       prefix_copy(&nht->p, p);
+
+       listnode_add(sg.nhs, nht);
+       return nht;
+}
+
+void sharp_nh_tracker_dump(struct vty *vty)
+{
+       struct listnode *node;
+       struct sharp_nh_tracker *nht;
+
+       for (ALL_LIST_ELEMENTS_RO(sg.nhs, node, nht)) {
+               char buf[PREFIX_STRLEN];
+
+               vty_out(vty, "%s: Nexthops: %u Updates: %u\n",
+                       prefix2str(&nht->p, buf, sizeof(buf)),
+                       nht->nhop_num,
+                       nht->updates);
+       }
+}
diff --git a/sharpd/sharp_nht.h b/sharpd/sharp_nht.h
new file mode 100644 (file)
index 0000000..0b00774
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * SHARP - code to track nexthops
+ * Copyright (C) Cumulus Networks, Inc.
+ *               Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __SHARP_NHT_H__
+#define __SHARP_NHT_H__
+
+struct sharp_nh_tracker {
+       /* What are we watching */
+       struct prefix p;
+
+       /* Number of valid nexthops */
+       uint32_t nhop_num;
+
+       uint32_t updates;
+};
+
+extern struct sharp_nh_tracker *sharp_nh_tracker_get(struct prefix *p);
+
+extern void sharp_nh_tracker_dump(struct vty *vty);
+#endif
index 86c8bfe1c2e79945398cd24f8d3631a823ec58ab..0c02bd304dcda3e100a58fa794c10c129163757d 100644 (file)
 #include "zclient.h"
 #include "nexthop_group.h"
 
+#include "sharpd/sharp_globals.h"
 #include "sharpd/sharp_zebra.h"
+#include "sharpd/sharp_nht.h"
 #include "sharpd/sharp_vty.h"
 #ifndef VTYSH_EXTRACT_PL
 #include "sharpd/sharp_vty_clippy.c"
 #endif
 
-extern uint32_t total_routes;
-extern uint32_t installed_routes;
-extern uint32_t removed_routes;
-
-uint8_t inst;
-struct prefix prefix;
-struct prefix orig_prefix;
-struct nexthop nhop;
-struct nexthop_group nhop_group;
-uint32_t rts;
-int32_t repeat;
-
 DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
-      "sharp watch nexthop X:X::X:X$nhop",
+      "sharp watch nexthop X:X::X:X$nhop [connected$connected]",
       "Sharp routing Protocol\n"
       "Watch for changes\n"
       "Watch for nexthop changes\n"
-      "The v6 nexthop to signal for watching\n")
+      "The v6 nexthop to signal for watching\n"
+      "Should the route be connected\n")
 {
        struct prefix p;
 
@@ -63,17 +54,19 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
        memcpy(&p.u.prefix6, &nhop, 16);
        p.family = AF_INET6;
 
-       sharp_zebra_nexthop_watch(&p, true);
+       sharp_nh_tracker_get(&p);
+       sharp_zebra_nexthop_watch(&p, true, !!connected);
 
        return CMD_SUCCESS;
 }
 
 DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
-      "sharp watch nexthop A.B.C.D$nhop",
+      "sharp watch nexthop A.B.C.D$nhop [connected$connected]",
       "Sharp routing Protocol\n"
       "Watch for changes\n"
       "Watch for nexthop changes\n"
-      "The v4 nexthop to signal for watching\n")
+      "The v4 nexthop to signal for watching\n"
+      "Should the route be connected\n")
 {
        struct prefix p;
 
@@ -83,7 +76,41 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
        p.u.prefix4 = nhop;
        p.family = AF_INET;
 
-       sharp_zebra_nexthop_watch(&p, true);
+       sharp_nh_tracker_get(&p);
+       sharp_zebra_nexthop_watch(&p, true, !!connected);
+
+       return CMD_SUCCESS;
+}
+
+DEFPY(sharp_nht_data_dump,
+      sharp_nht_data_dump_cmd,
+      "sharp data nexthop",
+      "Sharp routing Protocol\n"
+      "Nexthop information\n"
+      "Data Dump\n")
+{
+       sharp_nh_tracker_dump(vty);
+
+       return CMD_SUCCESS;
+}
+
+DEFPY (install_routes_data_dump,
+       install_routes_data_dump_cmd,
+       "sharp data route",
+       "Sharp routing Protocol\n"
+       "Data about what is going on\n"
+       "Route Install/Removal Information\n")
+{
+       char buf[PREFIX_STRLEN];
+       struct timeval r;
+
+       timersub(&sg.r.t_end, &sg.r.t_start, &r);
+       vty_out(vty, "Prefix: %s Total: %u %u %u Time: %ld.%ld\n",
+               prefix2str(&sg.r.orig_prefix, buf, sizeof(buf)),
+               sg.r.total_routes,
+               sg.r.installed_routes,
+               sg.r.removed_routes,
+               r.tv_sec, r.tv_usec);
 
        return CMD_SUCCESS;
 }
@@ -107,18 +134,21 @@ DEFPY (install_routes,
        "Should we repeat this command\n"
        "How many times to repeat this command\n")
 {
-       total_routes = routes;
-       installed_routes = 0;
+       struct prefix prefix;
+       uint32_t rts;
+
+       sg.r.total_routes = routes;
+       sg.r.installed_routes = 0;
 
        if (rpt >= 2)
-               repeat = rpt * 2;
+               sg.r.repeat = rpt * 2;
        else
-               repeat = 0;
+               sg.r.repeat = 0;
 
        memset(&prefix, 0, sizeof(prefix));
-       memset(&orig_prefix, 0, sizeof(orig_prefix));
-       memset(&nhop, 0, sizeof(nhop));
-       memset(&nhop_group, 0, sizeof(nhop_group));
+       memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
+       memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
+       memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
 
        if (start4.s_addr != 0) {
                prefix.family = AF_INET;
@@ -129,7 +159,7 @@ DEFPY (install_routes,
                prefix.prefixlen = 128;
                prefix.u.prefix6 = start6;
        }
-       orig_prefix = prefix;
+       sg.r.orig_prefix = prefix;
 
        if (nexthop_group) {
                struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
@@ -140,22 +170,22 @@ DEFPY (install_routes,
                        return CMD_WARNING;
                }
 
-               nhop_group.nexthop = nhgc->nhg.nexthop;
+               sg.r.nhop_group.nexthop = nhgc->nhg.nexthop;
        } else {
                if (nexthop4.s_addr != INADDR_ANY) {
-                       nhop.gate.ipv4 = nexthop4;
-                       nhop.type = NEXTHOP_TYPE_IPV4;
+                       sg.r.nhop.gate.ipv4 = nexthop4;
+                       sg.r.nhop.type = NEXTHOP_TYPE_IPV4;
                } else {
-                       nhop.gate.ipv6 = nexthop6;
-                       nhop.type = NEXTHOP_TYPE_IPV6;
+                       sg.r.nhop.gate.ipv6 = nexthop6;
+                       sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
                }
 
-               nhop_group.nexthop = &nhop;
+               sg.r.nhop_group.nexthop = &sg.r.nhop;
        }
 
-       inst = instance;
+       sg.r.inst = instance;
        rts = routes;
-       sharp_install_routes_helper(&prefix, inst, &nhop_group, rts);
+       sharp_install_routes_helper(&prefix, sg.r.inst, &sg.r.nhop_group, rts);
 
        return CMD_SUCCESS;
 }
@@ -202,8 +232,11 @@ DEFPY (remove_routes,
        "instance to use\n"
        "Value of instance\n")
 {
-       total_routes = routes;
-       removed_routes = 0;
+       struct prefix prefix;
+
+       sg.r.total_routes = routes;
+       sg.r.removed_routes = 0;
+       uint32_t rts;
 
        memset(&prefix, 0, sizeof(prefix));
 
@@ -217,9 +250,9 @@ DEFPY (remove_routes,
                prefix.u.prefix6 = start6;
        }
 
-       inst = instance;
+       sg.r.inst = instance;
        rts = routes;
-       sharp_remove_routes_helper(&prefix, inst, rts);
+       sharp_remove_routes_helper(&prefix, sg.r.inst, rts);
 
        return CMD_SUCCESS;
 }
@@ -238,9 +271,11 @@ DEFUN_NOSH (show_debugging_sharpd,
 
 void sharp_vty_init(void)
 {
+       install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
        install_element(ENABLE_NODE, &install_routes_cmd);
        install_element(ENABLE_NODE, &remove_routes_cmd);
        install_element(ENABLE_NODE, &vrf_label_cmd);
+       install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
        install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
        install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
 
index c9f333e34be84f3ec274db895f2be178fb208ea3..30e616a05775a6b127e5f4b9254314abf47e4b03 100644 (file)
@@ -36,6 +36,8 @@
 #include "nexthop.h"
 #include "nexthop_group.h"
 
+#include "sharp_globals.h"
+#include "sharp_nht.h"
 #include "sharp_zebra.h"
 
 /* Zebra structure to hold current status. */
@@ -129,16 +131,6 @@ static int interface_state_down(int command, struct zclient *zclient,
        return 0;
 }
 
-static struct timeval t_start;
-static struct timeval t_end;
-extern uint32_t total_routes;
-extern uint32_t installed_routes;
-extern uint32_t removed_routes;
-extern int32_t repeat;
-extern struct prefix orig_prefix;
-extern struct nexthop_group nhop_group;
-extern uint8_t inst;
-
 void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
                                 struct nexthop_group *nhg,
                                 uint32_t routes)
@@ -154,7 +146,7 @@ void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
        } else
                temp = ntohl(p->u.val32[3]);
 
-       monotime(&t_start);
+       monotime(&sg.r.t_start);
        for (i = 0; i < routes; i++) {
                route_add(p, (uint8_t)instance, nhg);
                if (v4)
@@ -178,7 +170,7 @@ void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
        } else
                temp = ntohl(p->u.val32[3]);
 
-       monotime(&t_start);
+       monotime(&sg.r.t_start);
        for (i = 0; i < routes; i++) {
                route_delete(p, (uint8_t)instance);
                if (v4)
@@ -190,21 +182,21 @@ void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
 
 static void handle_repeated(bool installed)
 {
-       struct prefix p = orig_prefix;
-       repeat--;
+       struct prefix p = sg.r.orig_prefix;
+       sg.r.repeat--;
 
-       if (repeat <= 0)
+       if (sg.r.repeat <= 0)
                return;
 
        if (installed) {
-               removed_routes = 0;
-               sharp_remove_routes_helper(&p, inst, total_routes);
+               sg.r.removed_routes = 0;
+               sharp_remove_routes_helper(&p, sg.r.inst, sg.r.total_routes);
        }
 
-       if (!installed) {
-               installed_routes = 0;
-               sharp_install_routes_helper(&p, inst, &nhop_group,
-                                           total_routes);
+       if (installed) {
+               sg.r.installed_routes = 0;
+               sharp_install_routes_helper(&p, sg.r.inst, &sg.r.nhop_group,
+                                           sg.r.total_routes);
        }
 }
 
@@ -221,10 +213,10 @@ static int route_notify_owner(int command, struct zclient *zclient,
 
        switch (note) {
        case ZAPI_ROUTE_INSTALLED:
-               installed_routes++;
-               if (total_routes == installed_routes) {
-                       monotime(&t_end);
-                       timersub(&t_end, &t_start, &r);
+               sg.r.installed_routes++;
+               if (sg.r.total_routes == sg.r.installed_routes) {
+                       monotime(&sg.r.t_end);
+                       timersub(&sg.r.t_end, &sg.r.t_start, &r);
                        zlog_debug("Installed All Items %ld.%ld", r.tv_sec,
                                   r.tv_usec);
                        handle_repeated(true);
@@ -237,10 +229,10 @@ static int route_notify_owner(int command, struct zclient *zclient,
                zlog_debug("Better Admin Distance won over us");
                break;
        case ZAPI_ROUTE_REMOVED:
-               removed_routes++;
-               if (total_routes == removed_routes) {
-                       monotime(&t_end);
-                       timersub(&t_end, &t_start, &r);
+               sg.r.removed_routes++;
+               if (sg.r.total_routes == sg.r.removed_routes) {
+                       monotime(&sg.r.t_end);
+                       timersub(&sg.r.t_end, &sg.r.t_start, &r);
                        zlog_debug("Removed all Items %ld.%ld", r.tv_sec,
                                   r.tv_usec);
                        handle_repeated(false);
@@ -328,14 +320,14 @@ void route_delete(struct prefix *p, uint8_t instance)
        return;
 }
 
-void sharp_zebra_nexthop_watch(struct prefix *p, bool watch)
+void sharp_zebra_nexthop_watch(struct prefix *p, bool watch, bool connected)
 {
        int command = ZEBRA_NEXTHOP_REGISTER;
 
        if (!watch)
                command = ZEBRA_NEXTHOP_UNREGISTER;
 
-       if (zclient_send_rnh(zclient, command, p, true, VRF_DEFAULT) < 0)
+       if (zclient_send_rnh(zclient, command, p, connected, VRF_DEFAULT) < 0)
                zlog_warn("%s: Failure to send nexthop to zebra",
                          __PRETTY_FUNCTION__);
 }
@@ -343,6 +335,7 @@ void sharp_zebra_nexthop_watch(struct prefix *p, bool watch)
 static int sharp_nexthop_update(int command, struct zclient *zclient,
                                zebra_size_t length, vrf_id_t vrf_id)
 {
+       struct sharp_nh_tracker *nht;
        struct zapi_route nhr;
        char buf[PREFIX_STRLEN];
        int i;
@@ -355,6 +348,11 @@ static int sharp_nexthop_update(int command, struct zclient *zclient,
 
        zlog_debug("Received update for %s",
                   prefix2str(&nhr.prefix, buf, sizeof(buf)));
+
+       nht = sharp_nh_tracker_get(&nhr.prefix);
+       nht->nhop_num = nhr.nexthop_num;
+       nht->updates++;
+
        for (i = 0; i < nhr.nexthop_num; i++) {
                struct zapi_nexthop *znh = &nhr.nexthops[i];
 
index 7326056cae773e044dd9a6eed23ab97295a4ebf4..7e6ac7670bd9ad5c5aa0a3d503717974528b9272 100644 (file)
@@ -28,7 +28,8 @@ extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label);
 extern void route_add(struct prefix *p, uint8_t instance,
                      struct nexthop_group *nhg);
 extern void route_delete(struct prefix *p, uint8_t instance);
-extern void sharp_zebra_nexthop_watch(struct prefix *p, bool watch);
+extern void sharp_zebra_nexthop_watch(struct prefix *p, bool watch,
+                                     bool connected);
 
 extern void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
                                         struct nexthop_group *nhg,
index c00d90ea0a148a9cd54cffc27f1f9a90bf1f0213..4a9028f6feee69207c2b131fecab167bd20bf714 100644 (file)
@@ -11,12 +11,15 @@ man8 += $(MANBUILD)/sharpd.8
 endif
 
 sharpd_libsharp_a_SOURCES = \
+       sharpd/sharp_nht.c \
        sharpd/sharp_zebra.c \
        sharpd/sharp_vty.c \
        # end
 
 noinst_HEADERS += \
+       sharpd/sharp_nht.h \
        sharpd/sharp_vty.h \
+       sharpd/sharp_globals.h \
        sharpd/sharp_zebra.h \
        # end
 
diff --git a/tests/Makefile.in b/tests/Makefile.in
new file mode 100644 (file)
index 0000000..29d903e
--- /dev/null
@@ -0,0 +1,1338 @@
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Automake fragment intended to be shared by Makefile.am files in the
+# tree.
+#
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+check_PROGRAMS = lib/test_buffer$(EXEEXT) lib/test_checksum$(EXEEXT) \
+       lib/test_heavy_thread$(EXEEXT) lib/test_heavy_wq$(EXEEXT) \
+       lib/test_heavy$(EXEEXT) lib/test_memory$(EXEEXT) \
+       lib/test_nexthop_iter$(EXEEXT) lib/test_privs$(EXEEXT) \
+       lib/test_ringbuf$(EXEEXT) lib/test_srcdest_table$(EXEEXT) \
+       lib/test_segv$(EXEEXT) lib/test_sig$(EXEEXT) \
+       lib/test_stream$(EXEEXT) lib/test_table$(EXEEXT) \
+       lib/test_timer_correctness$(EXEEXT) \
+       lib/test_timer_performance$(EXEEXT) lib/test_ttable$(EXEEXT) \
+       lib/cli/test_cli$(EXEEXT) lib/cli/test_commands$(EXEEXT) \
+       $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
+       $(am__EXEEXT_4)
+@ZEROMQ_TRUE@am__append_1 = \
+@ZEROMQ_TRUE@  lib/test_zmq \
+@ZEROMQ_TRUE@  # end
+
+subdir = tests
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compare_version.m4 \
+       $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \
+       $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+       $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+       $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+@BGPD_TRUE@am__EXEEXT_1 = bgpd/test_aspath$(EXEEXT) \
+@BGPD_TRUE@    bgpd/test_capability$(EXEEXT) \
+@BGPD_TRUE@    bgpd/test_packet$(EXEEXT) \
+@BGPD_TRUE@    bgpd/test_ecommunity$(EXEEXT) \
+@BGPD_TRUE@    bgpd/test_mp_attr$(EXEEXT) bgpd/test_mpath$(EXEEXT)
+@ISISD_TRUE@@SOLARIS_FALSE@am__EXEEXT_2 =  \
+@ISISD_TRUE@@SOLARIS_FALSE@    isisd/test_fuzz_isis_tlv$(EXEEXT) \
+@ISISD_TRUE@@SOLARIS_FALSE@    isisd/test_isis_vertex_queue$(EXEEXT)
+@OSPF6D_TRUE@am__EXEEXT_3 = ospf6d/test_lsdb$(EXEEXT)
+@ZEROMQ_TRUE@am__EXEEXT_4 = lib/test_zmq$(EXEEXT)
+am__dirstamp = $(am__leading_dot)dirstamp
+am_bgpd_test_aspath_OBJECTS = bgpd/test_aspath.$(OBJEXT)
+bgpd_test_aspath_OBJECTS = $(am_bgpd_test_aspath_OBJECTS)
+@ENABLE_BGP_VNC_TRUE@am__DEPENDENCIES_1 =  \
+@ENABLE_BGP_VNC_TRUE@  @top_builddir@/$(LIBRFP)/librfp.a
+am__DEPENDENCIES_2 = ../lib/libfrr.la
+am__DEPENDENCIES_3 = ../bgpd/libbgp.a $(am__DEPENDENCIES_1) \
+       $(am__DEPENDENCIES_2)
+bgpd_test_aspath_DEPENDENCIES = $(am__DEPENDENCIES_3)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+am_bgpd_test_capability_OBJECTS = bgpd/test_capability.$(OBJEXT)
+bgpd_test_capability_OBJECTS = $(am_bgpd_test_capability_OBJECTS)
+bgpd_test_capability_DEPENDENCIES = $(am__DEPENDENCIES_3)
+am_bgpd_test_ecommunity_OBJECTS = bgpd/test_ecommunity.$(OBJEXT)
+bgpd_test_ecommunity_OBJECTS = $(am_bgpd_test_ecommunity_OBJECTS)
+bgpd_test_ecommunity_DEPENDENCIES = $(am__DEPENDENCIES_3)
+am_bgpd_test_mp_attr_OBJECTS = bgpd/test_mp_attr.$(OBJEXT)
+bgpd_test_mp_attr_OBJECTS = $(am_bgpd_test_mp_attr_OBJECTS)
+bgpd_test_mp_attr_DEPENDENCIES = $(am__DEPENDENCIES_3)
+am_bgpd_test_mpath_OBJECTS = bgpd/test_mpath.$(OBJEXT)
+bgpd_test_mpath_OBJECTS = $(am_bgpd_test_mpath_OBJECTS)
+bgpd_test_mpath_DEPENDENCIES = $(am__DEPENDENCIES_3)
+am_bgpd_test_packet_OBJECTS = bgpd/test_packet.$(OBJEXT)
+bgpd_test_packet_OBJECTS = $(am_bgpd_test_packet_OBJECTS)
+bgpd_test_packet_DEPENDENCIES = $(am__DEPENDENCIES_3)
+am_isisd_test_fuzz_isis_tlv_OBJECTS =  \
+       isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.$(OBJEXT)
+isisd_test_fuzz_isis_tlv_OBJECTS =  \
+       $(am_isisd_test_fuzz_isis_tlv_OBJECTS)
+am__DEPENDENCIES_4 = ../isisd/libisis.a $(am__DEPENDENCIES_2)
+isisd_test_fuzz_isis_tlv_DEPENDENCIES = $(am__DEPENDENCIES_4)
+am_isisd_test_isis_vertex_queue_OBJECTS =  \
+       isisd/test_isis_vertex_queue.$(OBJEXT)
+isisd_test_isis_vertex_queue_OBJECTS =  \
+       $(am_isisd_test_isis_vertex_queue_OBJECTS)
+isisd_test_isis_vertex_queue_DEPENDENCIES = $(am__DEPENDENCIES_4)
+am_lib_cli_test_cli_OBJECTS = lib/cli/test_cli.$(OBJEXT) \
+       lib/cli/common_cli.$(OBJEXT)
+lib_cli_test_cli_OBJECTS = $(am_lib_cli_test_cli_OBJECTS)
+lib_cli_test_cli_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_cli_test_commands_OBJECTS =  \
+       lib/cli/test_commands_defun.$(OBJEXT) \
+       lib/cli/test_commands.$(OBJEXT) helpers/c/prng.$(OBJEXT)
+lib_cli_test_commands_OBJECTS = $(am_lib_cli_test_commands_OBJECTS)
+lib_cli_test_commands_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_buffer_OBJECTS = lib/test_buffer.$(OBJEXT)
+lib_test_buffer_OBJECTS = $(am_lib_test_buffer_OBJECTS)
+lib_test_buffer_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_checksum_OBJECTS = lib/test_checksum.$(OBJEXT)
+lib_test_checksum_OBJECTS = $(am_lib_test_checksum_OBJECTS)
+lib_test_checksum_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_heavy_OBJECTS = lib/test_heavy.$(OBJEXT) \
+       helpers/c/main.$(OBJEXT)
+lib_test_heavy_OBJECTS = $(am_lib_test_heavy_OBJECTS)
+lib_test_heavy_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_heavy_thread_OBJECTS = lib/test_heavy_thread.$(OBJEXT) \
+       helpers/c/main.$(OBJEXT)
+lib_test_heavy_thread_OBJECTS = $(am_lib_test_heavy_thread_OBJECTS)
+lib_test_heavy_thread_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_heavy_wq_OBJECTS = lib/test_heavy_wq.$(OBJEXT) \
+       helpers/c/main.$(OBJEXT)
+lib_test_heavy_wq_OBJECTS = $(am_lib_test_heavy_wq_OBJECTS)
+lib_test_heavy_wq_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_memory_OBJECTS = lib/test_memory.$(OBJEXT)
+lib_test_memory_OBJECTS = $(am_lib_test_memory_OBJECTS)
+lib_test_memory_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_nexthop_iter_OBJECTS = lib/test_nexthop_iter.$(OBJEXT) \
+       helpers/c/prng.$(OBJEXT)
+lib_test_nexthop_iter_OBJECTS = $(am_lib_test_nexthop_iter_OBJECTS)
+lib_test_nexthop_iter_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_privs_OBJECTS = lib/test_privs.$(OBJEXT)
+lib_test_privs_OBJECTS = $(am_lib_test_privs_OBJECTS)
+lib_test_privs_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_ringbuf_OBJECTS = lib/test_ringbuf.$(OBJEXT)
+lib_test_ringbuf_OBJECTS = $(am_lib_test_ringbuf_OBJECTS)
+lib_test_ringbuf_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_segv_OBJECTS = lib/test_segv.$(OBJEXT)
+lib_test_segv_OBJECTS = $(am_lib_test_segv_OBJECTS)
+lib_test_segv_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_sig_OBJECTS = lib/test_sig.$(OBJEXT)
+lib_test_sig_OBJECTS = $(am_lib_test_sig_OBJECTS)
+lib_test_sig_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_srcdest_table_OBJECTS = lib/test_srcdest_table.$(OBJEXT) \
+       helpers/c/prng.$(OBJEXT)
+lib_test_srcdest_table_OBJECTS = $(am_lib_test_srcdest_table_OBJECTS)
+lib_test_srcdest_table_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_stream_OBJECTS = lib/test_stream.$(OBJEXT)
+lib_test_stream_OBJECTS = $(am_lib_test_stream_OBJECTS)
+lib_test_stream_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_table_OBJECTS = lib/test_table.$(OBJEXT)
+lib_test_table_OBJECTS = $(am_lib_test_table_OBJECTS)
+lib_test_table_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_timer_correctness_OBJECTS =  \
+       lib/test_timer_correctness.$(OBJEXT) helpers/c/prng.$(OBJEXT)
+lib_test_timer_correctness_OBJECTS =  \
+       $(am_lib_test_timer_correctness_OBJECTS)
+lib_test_timer_correctness_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_timer_performance_OBJECTS =  \
+       lib/test_timer_performance.$(OBJEXT) helpers/c/prng.$(OBJEXT)
+lib_test_timer_performance_OBJECTS =  \
+       $(am_lib_test_timer_performance_OBJECTS)
+lib_test_timer_performance_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_ttable_OBJECTS = lib/test_ttable.$(OBJEXT)
+lib_test_ttable_OBJECTS = $(am_lib_test_ttable_OBJECTS)
+lib_test_ttable_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_lib_test_zmq_OBJECTS = lib/lib_test_zmq-test_zmq.$(OBJEXT)
+lib_test_zmq_OBJECTS = $(am_lib_test_zmq_OBJECTS)
+am__DEPENDENCIES_5 =
+lib_test_zmq_DEPENDENCIES = ../lib/libfrrzmq.la $(am__DEPENDENCIES_2) \
+       $(am__DEPENDENCIES_5)
+lib_test_zmq_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(lib_test_zmq_CFLAGS) \
+       $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+am_ospf6d_test_lsdb_OBJECTS = ospf6d/test_lsdb.$(OBJEXT) \
+       lib/cli/common_cli.$(OBJEXT)
+ospf6d_test_lsdb_OBJECTS = $(am_ospf6d_test_lsdb_OBJECTS)
+am__DEPENDENCIES_6 = ../ospf6d/libospf6.a $(am__DEPENDENCIES_2)
+ospf6d_test_lsdb_DEPENDENCIES = $(am__DEPENDENCIES_6)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(bgpd_test_aspath_SOURCES) $(bgpd_test_capability_SOURCES) \
+       $(bgpd_test_ecommunity_SOURCES) $(bgpd_test_mp_attr_SOURCES) \
+       $(bgpd_test_mpath_SOURCES) $(bgpd_test_packet_SOURCES) \
+       $(isisd_test_fuzz_isis_tlv_SOURCES) \
+       $(isisd_test_isis_vertex_queue_SOURCES) \
+       $(lib_cli_test_cli_SOURCES) $(lib_cli_test_commands_SOURCES) \
+       $(lib_test_buffer_SOURCES) $(lib_test_checksum_SOURCES) \
+       $(lib_test_heavy_SOURCES) $(lib_test_heavy_thread_SOURCES) \
+       $(lib_test_heavy_wq_SOURCES) $(lib_test_memory_SOURCES) \
+       $(lib_test_nexthop_iter_SOURCES) $(lib_test_privs_SOURCES) \
+       $(lib_test_ringbuf_SOURCES) $(lib_test_segv_SOURCES) \
+       $(lib_test_sig_SOURCES) $(lib_test_srcdest_table_SOURCES) \
+       $(lib_test_stream_SOURCES) $(lib_test_table_SOURCES) \
+       $(lib_test_timer_correctness_SOURCES) \
+       $(lib_test_timer_performance_SOURCES) \
+       $(lib_test_ttable_SOURCES) $(lib_test_zmq_SOURCES) \
+       $(ospf6d_test_lsdb_SOURCES)
+DIST_SOURCES = $(bgpd_test_aspath_SOURCES) \
+       $(bgpd_test_capability_SOURCES) \
+       $(bgpd_test_ecommunity_SOURCES) $(bgpd_test_mp_attr_SOURCES) \
+       $(bgpd_test_mpath_SOURCES) $(bgpd_test_packet_SOURCES) \
+       $(isisd_test_fuzz_isis_tlv_SOURCES) \
+       $(isisd_test_isis_vertex_queue_SOURCES) \
+       $(lib_cli_test_cli_SOURCES) $(lib_cli_test_commands_SOURCES) \
+       $(lib_test_buffer_SOURCES) $(lib_test_checksum_SOURCES) \
+       $(lib_test_heavy_SOURCES) $(lib_test_heavy_thread_SOURCES) \
+       $(lib_test_heavy_wq_SOURCES) $(lib_test_memory_SOURCES) \
+       $(lib_test_nexthop_iter_SOURCES) $(lib_test_privs_SOURCES) \
+       $(lib_test_ringbuf_SOURCES) $(lib_test_segv_SOURCES) \
+       $(lib_test_sig_SOURCES) $(lib_test_srcdest_table_SOURCES) \
+       $(lib_test_stream_SOURCES) $(lib_test_table_SOURCES) \
+       $(lib_test_timer_correctness_SOURCES) \
+       $(lib_test_timer_performance_SOURCES) \
+       $(lib_test_ttable_SOURCES) $(lib_test_zmq_SOURCES) \
+       $(ospf6d_test_lsdb_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/../common.am $(srcdir)/Makefile.in \
+       $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BGPD = @BGPD@
+BISON_CLOSEBRACE = @BISON_CLOSEBRACE@
+BISON_OPENBRACE = @BISON_OPENBRACE@
+BISON_VERBOSE = @BISON_VERBOSE@
+CARES_CFLAGS = @CARES_CFLAGS@
+CARES_LIBS = @CARES_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFG_MODULE = @CFG_MODULE@
+CFG_SBIN = @CFG_SBIN@
+CFG_STATE = @CFG_STATE@
+CFG_SYSCONF = @CFG_SYSCONF@
+CFLAGS = @CFLAGS@
+CONFDATE = @CONFDATE@
+CONFIG_ARGS = @CONFIG_ARGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURSES = @CURSES@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\"
+DEPDIR = @DEPDIR@
+DFLT_NAME = @DFLT_NAME@
+DLLTOOL = @DLLTOOL@
+DOC = @DOC@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_LIBPCREPOSIX = @HAVE_LIBPCREPOSIX@
+HOSTTOOLS = @HOSTTOOLS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAP = @LIBCAP@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBPAM = @LIBPAM@
+LIBREADLINE = @LIBREADLINE@
+LIBRFP = @LIBRFP@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NETSNMP_CONFIG = @NETSNMP_CONFIG@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_EXTRAVERSION = @PACKAGE_EXTRAVERSION@
+PACKAGE_FULLNAME = @PACKAGE_FULLNAME@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOBUF_C_CFLAGS = @PROTOBUF_C_CFLAGS@
+PROTOBUF_C_LIBS = @PROTOBUF_C_LIBS@
+PROTOC_C = @PROTOC_C@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+PYTHONCONFIG = @PYTHONCONFIG@
+PYTHON_CFLAGS = @PYTHON_CFLAGS@
+PYTHON_LIBS = @PYTHON_LIBS@
+RANLIB = @RANLIB@
+RFPINC = @RFPINC@
+RFPTEST = @RFPTEST@
+RTRLIB_CFLAGS = @RTRLIB_CFLAGS@
+RTRLIB_LIBS = @RTRLIB_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOLARIS = @SOLARIS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+VNC_RFP_PATH = @VNC_RFP_PATH@
+VTYSH = @VTYSH@
+WERROR = @WERROR@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+ZEROMQ_CFLAGS = @ZEROMQ_CFLAGS@
+ZEROMQ_LIBS = @ZEROMQ_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_PYTHONCONFIG = @ac_ct_PYTHONCONFIG@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+enable_group = @enable_group@
+enable_user = @enable_user@
+enable_vty_group = @enable_vty_group@
+exampledir = @exampledir@
+exec_prefix = @exec_prefix@
+frr_statedir = @frr_statedir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgsrcrcdir = @pkgsrcrcdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_V_CLIPPY = $(am__v_CLIPPY_$(V))
+am__v_CLIPPY_ = $(am__v_CLIPPY_$(AM_DEFAULT_VERBOSITY))
+am__v_CLIPPY_0 = @echo "  CLIPPY  " $@;
+am__v_CLIPPY_1 = 
+CLIPPY_DEPS = $(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py
+SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h
+
+# Uncomment to use an non-system version of libprotobuf-c.
+#
+# Q_PROTOBUF_C_CLIENT_INCLUDES = -I$(top_srcdir)/third-party/protobuf-c/src
+# Q_PROTOBUF_C_CLIENT_LDOPTS = $(top_builddir)/third-party/protobuf-c/src/libprotobuf-c.la
+@HAVE_PROTOBUF_TRUE@Q_PROTOBUF_C_CLIENT_INCLUDES = 
+@HAVE_PROTOBUF_TRUE@Q_PROTOBUF_C_CLIENT_LDOPTS = -lprotobuf-c
+@HAVE_PROTOBUF_TRUE@Q_PROTOC = protoc
+@HAVE_PROTOBUF_TRUE@Q_PROTOC_C = protoc-c
+@HAVE_PROTOBUF_TRUE@AM_V_PROTOC_C = $(am__v_PROTOC_C_$(V))
+@HAVE_PROTOBUF_TRUE@am__v_PROTOC_C_ = $(am__v_PROTOC_C_$(AM_DEFAULT_VERBOSITY))
+@HAVE_PROTOBUF_TRUE@am__v_PROTOC_C_0 = @echo "  PROTOC_C" $@;
+@HAVE_PROTOBUF_TRUE@am__v_PROTOC_C_1 = 
+
+#
+# Information about how to link to various libraries.
+#
+@HAVE_PROTOBUF_TRUE@Q_FRR_PB_CLIENT_LDOPTS = $(top_srcdir)/qpb/libfrr_pb.la $(Q_PROTOBUF_C_CLIENT_LDOPTS)
+@HAVE_PROTOBUF_TRUE@Q_FPM_PB_CLIENT_LDOPTS = $(top_srcdir)/fpm/libfrrfpm_pb.la $(Q_FRR_PB_CLIENT_LDOPTS)
+AUTOMAKE_OPTIONS = subdir-objects
+AM_CPPFLAGS = \
+       -I.. \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/lib \
+       -I$(top_builddir)/lib \
+       -I$(top_srcdir)/tests/helpers/c \
+       -I$(top_builddir)/tests/helpers/c \
+       -O
+
+@BGPD_FALSE@TESTS_BGPD = 
+@BGPD_TRUE@TESTS_BGPD = \
+@BGPD_TRUE@    bgpd/test_aspath \
+@BGPD_TRUE@    bgpd/test_capability \
+@BGPD_TRUE@    bgpd/test_packet \
+@BGPD_TRUE@    bgpd/test_ecommunity \
+@BGPD_TRUE@    bgpd/test_mp_attr \
+@BGPD_TRUE@    bgpd/test_mpath
+
+@ISISD_FALSE@TESTS_ISISD = 
+@ISISD_TRUE@@SOLARIS_FALSE@TESTS_ISISD = \
+@ISISD_TRUE@@SOLARIS_FALSE@    isisd/test_fuzz_isis_tlv \
+@ISISD_TRUE@@SOLARIS_FALSE@    isisd/test_isis_vertex_queue \
+@ISISD_TRUE@@SOLARIS_FALSE@    # end
+
+@ISISD_TRUE@@SOLARIS_TRUE@TESTS_ISISD = 
+@OSPF6D_FALSE@TESTS_OSPF6D = 
+@OSPF6D_TRUE@TESTS_OSPF6D = \
+@OSPF6D_TRUE@  ospf6d/test_lsdb \
+@OSPF6D_TRUE@  # end
+
+@ENABLE_BGP_VNC_FALSE@BGP_VNC_RFP_LIB = 
+@ENABLE_BGP_VNC_TRUE@BGP_VNC_RFP_LIB = @top_builddir@/$(LIBRFP)/librfp.a
+noinst_HEADERS = \
+       ./helpers/c/prng.h \
+       ./helpers/c/tests.h \
+       ./lib/cli/common_cli.h
+
+lib_test_buffer_SOURCES = lib/test_buffer.c
+lib_test_checksum_SOURCES = lib/test_checksum.c
+lib_test_heavy_thread_SOURCES = lib/test_heavy_thread.c helpers/c/main.c
+lib_test_heavy_wq_SOURCES = lib/test_heavy_wq.c helpers/c/main.c
+lib_test_heavy_SOURCES = lib/test_heavy.c helpers/c/main.c
+lib_test_memory_SOURCES = lib/test_memory.c
+lib_test_nexthop_iter_SOURCES = lib/test_nexthop_iter.c helpers/c/prng.c
+lib_test_privs_SOURCES = lib/test_privs.c
+lib_test_srcdest_table_SOURCES = lib/test_srcdest_table.c \
+                                 helpers/c/prng.c
+
+lib_test_ringbuf_SOURCES = lib/test_ringbuf.c
+lib_test_segv_SOURCES = lib/test_segv.c
+lib_test_sig_SOURCES = lib/test_sig.c
+lib_test_stream_SOURCES = lib/test_stream.c
+lib_test_table_SOURCES = lib/test_table.c
+lib_test_timer_correctness_SOURCES = lib/test_timer_correctness.c \
+                                     helpers/c/prng.c
+
+lib_test_timer_performance_SOURCES = lib/test_timer_performance.c \
+                                     helpers/c/prng.c
+
+lib_test_ttable_SOURCES = lib/test_ttable.c
+lib_test_zmq_SOURCES = lib/test_zmq.c
+lib_test_zmq_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS)
+lib_cli_test_cli_SOURCES = lib/cli/test_cli.c lib/cli/common_cli.c
+lib_cli_test_commands_SOURCES = lib/cli/test_commands_defun.c \
+                                lib/cli/test_commands.c \
+                                helpers/c/prng.c
+
+bgpd_test_aspath_SOURCES = bgpd/test_aspath.c
+bgpd_test_capability_SOURCES = bgpd/test_capability.c
+bgpd_test_packet_SOURCES = bgpd/test_packet.c
+bgpd_test_ecommunity_SOURCES = bgpd/test_ecommunity.c
+bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c
+bgpd_test_mpath_SOURCES = bgpd/test_mpath.c
+isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv.c
+isisd_test_fuzz_isis_tlv_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/tests/isisd
+isisd_test_isis_vertex_queue_SOURCES = isisd/test_isis_vertex_queue.c
+ospf6d_test_lsdb_SOURCES = ospf6d/test_lsdb.c lib/cli/common_cli.c
+ALL_TESTS_LDADD = ../lib/libfrr.la @LIBCAP@
+BGP_TEST_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) $(ALL_TESTS_LDADD) -lm
+ISISD_TEST_LDADD = ../isisd/libisis.a $(ALL_TESTS_LDADD)
+OSPF6_TEST_LDADD = ../ospf6d/libospf6.a $(ALL_TESTS_LDADD)
+lib_test_buffer_LDADD = $(ALL_TESTS_LDADD)
+lib_test_checksum_LDADD = $(ALL_TESTS_LDADD)
+lib_test_heavy_thread_LDADD = $(ALL_TESTS_LDADD) -lm
+lib_test_heavy_wq_LDADD = $(ALL_TESTS_LDADD) -lm
+lib_test_heavy_LDADD = $(ALL_TESTS_LDADD) -lm
+lib_test_memory_LDADD = $(ALL_TESTS_LDADD)
+lib_test_nexthop_iter_LDADD = $(ALL_TESTS_LDADD)
+lib_test_privs_LDADD = $(ALL_TESTS_LDADD)
+lib_test_ringbuf_LDADD = $(ALL_TESTS_LDADD)
+lib_test_srcdest_table_LDADD = $(ALL_TESTS_LDADD)
+lib_test_segv_LDADD = $(ALL_TESTS_LDADD)
+lib_test_sig_LDADD = $(ALL_TESTS_LDADD)
+lib_test_stream_LDADD = $(ALL_TESTS_LDADD)
+lib_test_table_LDADD = $(ALL_TESTS_LDADD) -lm
+lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD)
+lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD)
+lib_test_ttable_LDADD = $(ALL_TESTS_LDADD)
+lib_test_zmq_LDADD = ../lib/libfrrzmq.la $(ALL_TESTS_LDADD) $(ZEROMQ_LIBS)
+lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD)
+lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD)
+bgpd_test_aspath_LDADD = $(BGP_TEST_LDADD)
+bgpd_test_capability_LDADD = $(BGP_TEST_LDADD)
+bgpd_test_packet_LDADD = $(BGP_TEST_LDADD)
+bgpd_test_ecommunity_LDADD = $(BGP_TEST_LDADD)
+bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD)
+bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD)
+isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD)
+isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD)
+ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD)
+EXTRA_DIST = \
+    runtests.py \
+    bgpd/test_aspath.py \
+    bgpd/test_capability.py \
+    bgpd/test_ecommunity.py \
+    bgpd/test_mp_attr.py \
+    bgpd/test_mpath.py \
+    helpers/python/frrsix.py \
+    helpers/python/frrtest.py \
+    isisd/test_fuzz_isis_tlv.py \
+    isisd/test_fuzz_isis_tlv_tests.h.gz \
+    isisd/test_isis_vertex_queue.py \
+    lib/cli/test_commands.in \
+    lib/cli/test_commands.py \
+    lib/cli/test_commands.refout \
+    lib/cli/test_cli.in \
+    lib/cli/test_cli.py \
+    lib/cli/test_cli.refout \
+    lib/test_nexthop_iter.py \
+    lib/test_ringbuf.py \
+    lib/test_srcdest_table.py \
+    lib/test_stream.py \
+    lib/test_stream.refout \
+    lib/test_table.py \
+    lib/test_timer_correctness.py \
+    lib/test_ttable.py \
+    lib/test_ttable.refout \
+    ospf6d/test_lsdb.py \
+    ospf6d/test_lsdb.in \
+    ospf6d/test_lsdb.refout \
+    # end
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: _clippy.c .proto .pb-c.c .pb-c.h .pb.h .c .l .lo .o .obj .y
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(srcdir)/../common.am $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu tests/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+$(srcdir)/../common.am $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-checkPROGRAMS:
+       @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+       echo " rm -f" $$list; \
+       rm -f $$list || exit $$?; \
+       test -n "$(EXEEXT)" || exit 0; \
+       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+       echo " rm -f" $$list; \
+       rm -f $$list
+bgpd/$(am__dirstamp):
+       @$(MKDIR_P) bgpd
+       @: > bgpd/$(am__dirstamp)
+bgpd/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) bgpd/$(DEPDIR)
+       @: > bgpd/$(DEPDIR)/$(am__dirstamp)
+bgpd/test_aspath.$(OBJEXT): bgpd/$(am__dirstamp) \
+       bgpd/$(DEPDIR)/$(am__dirstamp)
+
+bgpd/test_aspath$(EXEEXT): $(bgpd_test_aspath_OBJECTS) $(bgpd_test_aspath_DEPENDENCIES) $(EXTRA_bgpd_test_aspath_DEPENDENCIES) bgpd/$(am__dirstamp)
+       @rm -f bgpd/test_aspath$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(bgpd_test_aspath_OBJECTS) $(bgpd_test_aspath_LDADD) $(LIBS)
+bgpd/test_capability.$(OBJEXT): bgpd/$(am__dirstamp) \
+       bgpd/$(DEPDIR)/$(am__dirstamp)
+
+bgpd/test_capability$(EXEEXT): $(bgpd_test_capability_OBJECTS) $(bgpd_test_capability_DEPENDENCIES) $(EXTRA_bgpd_test_capability_DEPENDENCIES) bgpd/$(am__dirstamp)
+       @rm -f bgpd/test_capability$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(bgpd_test_capability_OBJECTS) $(bgpd_test_capability_LDADD) $(LIBS)
+bgpd/test_ecommunity.$(OBJEXT): bgpd/$(am__dirstamp) \
+       bgpd/$(DEPDIR)/$(am__dirstamp)
+
+bgpd/test_ecommunity$(EXEEXT): $(bgpd_test_ecommunity_OBJECTS) $(bgpd_test_ecommunity_DEPENDENCIES) $(EXTRA_bgpd_test_ecommunity_DEPENDENCIES) bgpd/$(am__dirstamp)
+       @rm -f bgpd/test_ecommunity$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(bgpd_test_ecommunity_OBJECTS) $(bgpd_test_ecommunity_LDADD) $(LIBS)
+bgpd/test_mp_attr.$(OBJEXT): bgpd/$(am__dirstamp) \
+       bgpd/$(DEPDIR)/$(am__dirstamp)
+
+bgpd/test_mp_attr$(EXEEXT): $(bgpd_test_mp_attr_OBJECTS) $(bgpd_test_mp_attr_DEPENDENCIES) $(EXTRA_bgpd_test_mp_attr_DEPENDENCIES) bgpd/$(am__dirstamp)
+       @rm -f bgpd/test_mp_attr$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(bgpd_test_mp_attr_OBJECTS) $(bgpd_test_mp_attr_LDADD) $(LIBS)
+bgpd/test_mpath.$(OBJEXT): bgpd/$(am__dirstamp) \
+       bgpd/$(DEPDIR)/$(am__dirstamp)
+
+bgpd/test_mpath$(EXEEXT): $(bgpd_test_mpath_OBJECTS) $(bgpd_test_mpath_DEPENDENCIES) $(EXTRA_bgpd_test_mpath_DEPENDENCIES) bgpd/$(am__dirstamp)
+       @rm -f bgpd/test_mpath$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(bgpd_test_mpath_OBJECTS) $(bgpd_test_mpath_LDADD) $(LIBS)
+bgpd/test_packet.$(OBJEXT): bgpd/$(am__dirstamp) \
+       bgpd/$(DEPDIR)/$(am__dirstamp)
+
+bgpd/test_packet$(EXEEXT): $(bgpd_test_packet_OBJECTS) $(bgpd_test_packet_DEPENDENCIES) $(EXTRA_bgpd_test_packet_DEPENDENCIES) bgpd/$(am__dirstamp)
+       @rm -f bgpd/test_packet$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(bgpd_test_packet_OBJECTS) $(bgpd_test_packet_LDADD) $(LIBS)
+isisd/$(am__dirstamp):
+       @$(MKDIR_P) isisd
+       @: > isisd/$(am__dirstamp)
+isisd/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) isisd/$(DEPDIR)
+       @: > isisd/$(DEPDIR)/$(am__dirstamp)
+isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.$(OBJEXT):  \
+       isisd/$(am__dirstamp) isisd/$(DEPDIR)/$(am__dirstamp)
+
+isisd/test_fuzz_isis_tlv$(EXEEXT): $(isisd_test_fuzz_isis_tlv_OBJECTS) $(isisd_test_fuzz_isis_tlv_DEPENDENCIES) $(EXTRA_isisd_test_fuzz_isis_tlv_DEPENDENCIES) isisd/$(am__dirstamp)
+       @rm -f isisd/test_fuzz_isis_tlv$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(isisd_test_fuzz_isis_tlv_OBJECTS) $(isisd_test_fuzz_isis_tlv_LDADD) $(LIBS)
+isisd/test_isis_vertex_queue.$(OBJEXT): isisd/$(am__dirstamp) \
+       isisd/$(DEPDIR)/$(am__dirstamp)
+
+isisd/test_isis_vertex_queue$(EXEEXT): $(isisd_test_isis_vertex_queue_OBJECTS) $(isisd_test_isis_vertex_queue_DEPENDENCIES) $(EXTRA_isisd_test_isis_vertex_queue_DEPENDENCIES) isisd/$(am__dirstamp)
+       @rm -f isisd/test_isis_vertex_queue$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(isisd_test_isis_vertex_queue_OBJECTS) $(isisd_test_isis_vertex_queue_LDADD) $(LIBS)
+lib/cli/$(am__dirstamp):
+       @$(MKDIR_P) lib/cli
+       @: > lib/cli/$(am__dirstamp)
+lib/cli/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) lib/cli/$(DEPDIR)
+       @: > lib/cli/$(DEPDIR)/$(am__dirstamp)
+lib/cli/test_cli.$(OBJEXT): lib/cli/$(am__dirstamp) \
+       lib/cli/$(DEPDIR)/$(am__dirstamp)
+lib/cli/common_cli.$(OBJEXT): lib/cli/$(am__dirstamp) \
+       lib/cli/$(DEPDIR)/$(am__dirstamp)
+
+lib/cli/test_cli$(EXEEXT): $(lib_cli_test_cli_OBJECTS) $(lib_cli_test_cli_DEPENDENCIES) $(EXTRA_lib_cli_test_cli_DEPENDENCIES) lib/cli/$(am__dirstamp)
+       @rm -f lib/cli/test_cli$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_cli_test_cli_OBJECTS) $(lib_cli_test_cli_LDADD) $(LIBS)
+lib/cli/test_commands_defun.$(OBJEXT): lib/cli/$(am__dirstamp) \
+       lib/cli/$(DEPDIR)/$(am__dirstamp)
+lib/cli/test_commands.$(OBJEXT): lib/cli/$(am__dirstamp) \
+       lib/cli/$(DEPDIR)/$(am__dirstamp)
+helpers/c/$(am__dirstamp):
+       @$(MKDIR_P) helpers/c
+       @: > helpers/c/$(am__dirstamp)
+helpers/c/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) helpers/c/$(DEPDIR)
+       @: > helpers/c/$(DEPDIR)/$(am__dirstamp)
+helpers/c/prng.$(OBJEXT): helpers/c/$(am__dirstamp) \
+       helpers/c/$(DEPDIR)/$(am__dirstamp)
+
+lib/cli/test_commands$(EXEEXT): $(lib_cli_test_commands_OBJECTS) $(lib_cli_test_commands_DEPENDENCIES) $(EXTRA_lib_cli_test_commands_DEPENDENCIES) lib/cli/$(am__dirstamp)
+       @rm -f lib/cli/test_commands$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_cli_test_commands_OBJECTS) $(lib_cli_test_commands_LDADD) $(LIBS)
+lib/$(am__dirstamp):
+       @$(MKDIR_P) lib
+       @: > lib/$(am__dirstamp)
+lib/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) lib/$(DEPDIR)
+       @: > lib/$(DEPDIR)/$(am__dirstamp)
+lib/test_buffer.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_buffer$(EXEEXT): $(lib_test_buffer_OBJECTS) $(lib_test_buffer_DEPENDENCIES) $(EXTRA_lib_test_buffer_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_buffer$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_buffer_OBJECTS) $(lib_test_buffer_LDADD) $(LIBS)
+lib/test_checksum.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_checksum$(EXEEXT): $(lib_test_checksum_OBJECTS) $(lib_test_checksum_DEPENDENCIES) $(EXTRA_lib_test_checksum_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_checksum$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_checksum_OBJECTS) $(lib_test_checksum_LDADD) $(LIBS)
+lib/test_heavy.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+helpers/c/main.$(OBJEXT): helpers/c/$(am__dirstamp) \
+       helpers/c/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_heavy$(EXEEXT): $(lib_test_heavy_OBJECTS) $(lib_test_heavy_DEPENDENCIES) $(EXTRA_lib_test_heavy_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_heavy$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_heavy_OBJECTS) $(lib_test_heavy_LDADD) $(LIBS)
+lib/test_heavy_thread.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_heavy_thread$(EXEEXT): $(lib_test_heavy_thread_OBJECTS) $(lib_test_heavy_thread_DEPENDENCIES) $(EXTRA_lib_test_heavy_thread_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_heavy_thread$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_heavy_thread_OBJECTS) $(lib_test_heavy_thread_LDADD) $(LIBS)
+lib/test_heavy_wq.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_heavy_wq$(EXEEXT): $(lib_test_heavy_wq_OBJECTS) $(lib_test_heavy_wq_DEPENDENCIES) $(EXTRA_lib_test_heavy_wq_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_heavy_wq$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_heavy_wq_OBJECTS) $(lib_test_heavy_wq_LDADD) $(LIBS)
+lib/test_memory.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_memory$(EXEEXT): $(lib_test_memory_OBJECTS) $(lib_test_memory_DEPENDENCIES) $(EXTRA_lib_test_memory_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_memory$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_memory_OBJECTS) $(lib_test_memory_LDADD) $(LIBS)
+lib/test_nexthop_iter.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_nexthop_iter$(EXEEXT): $(lib_test_nexthop_iter_OBJECTS) $(lib_test_nexthop_iter_DEPENDENCIES) $(EXTRA_lib_test_nexthop_iter_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_nexthop_iter$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_nexthop_iter_OBJECTS) $(lib_test_nexthop_iter_LDADD) $(LIBS)
+lib/test_privs.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_privs$(EXEEXT): $(lib_test_privs_OBJECTS) $(lib_test_privs_DEPENDENCIES) $(EXTRA_lib_test_privs_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_privs$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_privs_OBJECTS) $(lib_test_privs_LDADD) $(LIBS)
+lib/test_ringbuf.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_ringbuf$(EXEEXT): $(lib_test_ringbuf_OBJECTS) $(lib_test_ringbuf_DEPENDENCIES) $(EXTRA_lib_test_ringbuf_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_ringbuf$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_ringbuf_OBJECTS) $(lib_test_ringbuf_LDADD) $(LIBS)
+lib/test_segv.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_segv$(EXEEXT): $(lib_test_segv_OBJECTS) $(lib_test_segv_DEPENDENCIES) $(EXTRA_lib_test_segv_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_segv$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_segv_OBJECTS) $(lib_test_segv_LDADD) $(LIBS)
+lib/test_sig.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_sig$(EXEEXT): $(lib_test_sig_OBJECTS) $(lib_test_sig_DEPENDENCIES) $(EXTRA_lib_test_sig_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_sig$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_sig_OBJECTS) $(lib_test_sig_LDADD) $(LIBS)
+lib/test_srcdest_table.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_srcdest_table$(EXEEXT): $(lib_test_srcdest_table_OBJECTS) $(lib_test_srcdest_table_DEPENDENCIES) $(EXTRA_lib_test_srcdest_table_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_srcdest_table$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_srcdest_table_OBJECTS) $(lib_test_srcdest_table_LDADD) $(LIBS)
+lib/test_stream.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_stream$(EXEEXT): $(lib_test_stream_OBJECTS) $(lib_test_stream_DEPENDENCIES) $(EXTRA_lib_test_stream_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_stream$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_stream_OBJECTS) $(lib_test_stream_LDADD) $(LIBS)
+lib/test_table.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_table$(EXEEXT): $(lib_test_table_OBJECTS) $(lib_test_table_DEPENDENCIES) $(EXTRA_lib_test_table_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_table$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_table_OBJECTS) $(lib_test_table_LDADD) $(LIBS)
+lib/test_timer_correctness.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_timer_correctness$(EXEEXT): $(lib_test_timer_correctness_OBJECTS) $(lib_test_timer_correctness_DEPENDENCIES) $(EXTRA_lib_test_timer_correctness_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_timer_correctness$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_timer_correctness_OBJECTS) $(lib_test_timer_correctness_LDADD) $(LIBS)
+lib/test_timer_performance.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_timer_performance$(EXEEXT): $(lib_test_timer_performance_OBJECTS) $(lib_test_timer_performance_DEPENDENCIES) $(EXTRA_lib_test_timer_performance_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_timer_performance$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_timer_performance_OBJECTS) $(lib_test_timer_performance_LDADD) $(LIBS)
+lib/test_ttable.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_ttable$(EXEEXT): $(lib_test_ttable_OBJECTS) $(lib_test_ttable_DEPENDENCIES) $(EXTRA_lib_test_ttable_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_ttable$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(lib_test_ttable_OBJECTS) $(lib_test_ttable_LDADD) $(LIBS)
+lib/lib_test_zmq-test_zmq.$(OBJEXT): lib/$(am__dirstamp) \
+       lib/$(DEPDIR)/$(am__dirstamp)
+
+lib/test_zmq$(EXEEXT): $(lib_test_zmq_OBJECTS) $(lib_test_zmq_DEPENDENCIES) $(EXTRA_lib_test_zmq_DEPENDENCIES) lib/$(am__dirstamp)
+       @rm -f lib/test_zmq$(EXEEXT)
+       $(AM_V_CCLD)$(lib_test_zmq_LINK) $(lib_test_zmq_OBJECTS) $(lib_test_zmq_LDADD) $(LIBS)
+ospf6d/$(am__dirstamp):
+       @$(MKDIR_P) ospf6d
+       @: > ospf6d/$(am__dirstamp)
+ospf6d/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) ospf6d/$(DEPDIR)
+       @: > ospf6d/$(DEPDIR)/$(am__dirstamp)
+ospf6d/test_lsdb.$(OBJEXT): ospf6d/$(am__dirstamp) \
+       ospf6d/$(DEPDIR)/$(am__dirstamp)
+
+ospf6d/test_lsdb$(EXEEXT): $(ospf6d_test_lsdb_OBJECTS) $(ospf6d_test_lsdb_DEPENDENCIES) $(EXTRA_ospf6d_test_lsdb_DEPENDENCIES) ospf6d/$(am__dirstamp)
+       @rm -f ospf6d/test_lsdb$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(ospf6d_test_lsdb_OBJECTS) $(ospf6d_test_lsdb_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+       -rm -f bgpd/*.$(OBJEXT)
+       -rm -f helpers/c/*.$(OBJEXT)
+       -rm -f isisd/*.$(OBJEXT)
+       -rm -f lib/*.$(OBJEXT)
+       -rm -f lib/cli/*.$(OBJEXT)
+       -rm -f ospf6d/*.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_aspath.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_capability.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_ecommunity.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_mp_attr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_mpath.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@bgpd/$(DEPDIR)/test_packet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@helpers/c/$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@helpers/c/$(DEPDIR)/prng.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@isisd/$(DEPDIR)/test_isis_vertex_queue.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_test_zmq-test_zmq.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_buffer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_checksum.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_heavy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_heavy_thread.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_heavy_wq.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_memory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_nexthop_iter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_privs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_ringbuf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_segv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_sig.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_srcdest_table.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_stream.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_table.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_timer_correctness.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_timer_performance.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/test_ttable.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/$(DEPDIR)/common_cli.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/$(DEPDIR)/test_cli.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/$(DEPDIR)/test_commands.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@lib/cli/$(DEPDIR)/test_commands_defun.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ospf6d/$(DEPDIR)/test_lsdb.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.o: isisd/test_fuzz_isis_tlv.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(isisd_test_fuzz_isis_tlv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.o -MD -MP -MF isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Tpo -c -o isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.o `test -f 'isisd/test_fuzz_isis_tlv.c' || echo '$(srcdir)/'`isisd/test_fuzz_isis_tlv.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Tpo isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='isisd/test_fuzz_isis_tlv.c' object='isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(isisd_test_fuzz_isis_tlv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.o `test -f 'isisd/test_fuzz_isis_tlv.c' || echo '$(srcdir)/'`isisd/test_fuzz_isis_tlv.c
+
+isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.obj: isisd/test_fuzz_isis_tlv.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(isisd_test_fuzz_isis_tlv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.obj -MD -MP -MF isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Tpo -c -o isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.obj `if test -f 'isisd/test_fuzz_isis_tlv.c'; then $(CYGPATH_W) 'isisd/test_fuzz_isis_tlv.c'; else $(CYGPATH_W) '$(srcdir)/isisd/test_fuzz_isis_tlv.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Tpo isisd/$(DEPDIR)/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='isisd/test_fuzz_isis_tlv.c' object='isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(isisd_test_fuzz_isis_tlv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.obj `if test -f 'isisd/test_fuzz_isis_tlv.c'; then $(CYGPATH_W) 'isisd/test_fuzz_isis_tlv.c'; else $(CYGPATH_W) '$(srcdir)/isisd/test_fuzz_isis_tlv.c'; fi`
+
+lib/lib_test_zmq-test_zmq.o: lib/test_zmq.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_test_zmq_CFLAGS) $(CFLAGS) -MT lib/lib_test_zmq-test_zmq.o -MD -MP -MF lib/$(DEPDIR)/lib_test_zmq-test_zmq.Tpo -c -o lib/lib_test_zmq-test_zmq.o `test -f 'lib/test_zmq.c' || echo '$(srcdir)/'`lib/test_zmq.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) lib/$(DEPDIR)/lib_test_zmq-test_zmq.Tpo lib/$(DEPDIR)/lib_test_zmq-test_zmq.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='lib/test_zmq.c' object='lib/lib_test_zmq-test_zmq.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_test_zmq_CFLAGS) $(CFLAGS) -c -o lib/lib_test_zmq-test_zmq.o `test -f 'lib/test_zmq.c' || echo '$(srcdir)/'`lib/test_zmq.c
+
+lib/lib_test_zmq-test_zmq.obj: lib/test_zmq.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_test_zmq_CFLAGS) $(CFLAGS) -MT lib/lib_test_zmq-test_zmq.obj -MD -MP -MF lib/$(DEPDIR)/lib_test_zmq-test_zmq.Tpo -c -o lib/lib_test_zmq-test_zmq.obj `if test -f 'lib/test_zmq.c'; then $(CYGPATH_W) 'lib/test_zmq.c'; else $(CYGPATH_W) '$(srcdir)/lib/test_zmq.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) lib/$(DEPDIR)/lib_test_zmq-test_zmq.Tpo lib/$(DEPDIR)/lib_test_zmq-test_zmq.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='lib/test_zmq.c' object='lib/lib_test_zmq-test_zmq.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_test_zmq_CFLAGS) $(CFLAGS) -c -o lib/lib_test_zmq-test_zmq.obj `if test -f 'lib/test_zmq.c'; then $(CYGPATH_W) 'lib/test_zmq.c'; else $(CYGPATH_W) '$(srcdir)/lib/test_zmq.c'; fi`
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+       -rm -rf bgpd/.libs bgpd/_libs
+       -rm -rf isisd/.libs isisd/_libs
+       -rm -rf lib/.libs lib/_libs
+       -rm -rf lib/cli/.libs lib/cli/_libs
+       -rm -rf ospf6d/.libs ospf6d/_libs
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+       $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+       -rm -f bgpd/$(DEPDIR)/$(am__dirstamp)
+       -rm -f bgpd/$(am__dirstamp)
+       -rm -f helpers/c/$(DEPDIR)/$(am__dirstamp)
+       -rm -f helpers/c/$(am__dirstamp)
+       -rm -f isisd/$(DEPDIR)/$(am__dirstamp)
+       -rm -f isisd/$(am__dirstamp)
+       -rm -f lib/$(DEPDIR)/$(am__dirstamp)
+       -rm -f lib/$(am__dirstamp)
+       -rm -f lib/cli/$(DEPDIR)/$(am__dirstamp)
+       -rm -f lib/cli/$(am__dirstamp)
+       -rm -f ospf6d/$(DEPDIR)/$(am__dirstamp)
+       -rm -f ospf6d/$(am__dirstamp)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+       mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf bgpd/$(DEPDIR) helpers/c/$(DEPDIR) isisd/$(DEPDIR) lib/$(DEPDIR) lib/cli/$(DEPDIR) ospf6d/$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf bgpd/$(DEPDIR) helpers/c/$(DEPDIR) isisd/$(DEPDIR) lib/$(DEPDIR) lib/cli/$(DEPDIR) ospf6d/$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
+       clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \
+       ctags ctags-am distclean distclean-compile distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-html install-html-am install-info \
+       install-info-am install-man install-pdf install-pdf-am \
+       install-ps install-ps-am install-strip installcheck \
+       installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+.c_clippy.c:
+       @{ test -x $(top_builddir)/$(HOSTTOOLS)lib/clippy || $(MAKE) -C $(top_builddir)/$(HOSTTOOLS) lib/clippy; }
+       $(AM_V_CLIPPY)$(top_builddir)/$(HOSTTOOLS)lib/clippy $(top_srcdir)/python/clidef.py -o $@ $<
+
+.l.c:
+       $(AM_V_LEX)$(am__skiplex) $(LEXCOMPILE) $<
+.y.c:
+       $(AM_V_YACC)$(am__skipyacc) $(YACCCOMPILE) $<
+
+# Rules
+@HAVE_PROTOBUF_TRUE@.proto.pb.h:
+@HAVE_PROTOBUF_TRUE@   $(Q_PROTOC) -I$(top_srcdir) --cpp_out=$(top_srcdir) $(top_srcdir)/$^
+
+@HAVE_PROTOBUF_TRUE@.proto.pb-c.c:
+@HAVE_PROTOBUF_TRUE@   $(AM_V_PROTOC_C)$(Q_PROTOC_C) -I$(top_srcdir) --c_out=$(top_srcdir) $(top_srcdir)/$^
+@HAVE_PROTOBUF_TRUE@.pb-c.c.pb-c.h:
+@HAVE_PROTOBUF_TRUE@   @/bin/true
+
+PYTHON ?= python
+
+lib/cli/test_cli.o: lib/cli/test_cli_clippy.c
+ospf6d/test_lsdb.o: ospf6d/test_lsdb_clippy.c
+
+../vtysh/vtysh_cmd.c:
+       $(MAKE) -C ../vtysh vtysh_cmd.c
+
+lib/cli/test_commands_defun.c: ../vtysh/vtysh_cmd.c
+       sed \
+               -e 's/"vtysh\.h"/"tests.h"/' \
+               -e 's/vtysh_init_cmd/test_init_cmd/' \
+               -e 's/VTYSH_[A-Z][A-Z_0-9]*/0/g' \
+               < ../vtysh/vtysh_cmd.c \
+               > "$@"
+
+isisd/test_fuzz_isis_tlv_tests.h: $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
+       gzip -d < $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz > "$@"
+isisd/isisd_test_fuzz_isis_tlv-test_fuzz_isis_tlv.$(OBJEXT): \
+       isisd/test_fuzz_isis_tlv_tests.h
+
+.PHONY: tests.xml
+tests.xml: $(check_PROGRAMS)
+       $(PYTHON) $(srcdir)/runtests.py --junitxml=$@ -v $(srcdir)
+check: tests.xml
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tests/topotests/GUIDELINES.md b/tests/topotests/GUIDELINES.md
deleted file mode 100644 (file)
index 4bd3737..0000000
+++ /dev/null
@@ -1,571 +0,0 @@
-# Guidelines
-
-This document describes how to use the topotests testing framework.
-
-
-## Executing Tests
-
-To run the whole suite of tests the following commands must be executed at the
-top level directory of topotest:
-
-```shell
-$ # Change to the top level directory of topotests.
-$ cd path/to/topotests
-$ # Tests must be run as root, since Mininet requires it.
-$ sudo pytest
-```
-
-In order to run a specific test, you can use the following command:
-
-```shell
-$ # running a specific topology
-$ sudo pytest ospf-topo1/
-$ # or inside the test folder
-$ cd ospf-topo1
-$ sudo pytest # to run all tests inside the directory
-$ sudo pytest test_ospf_topo1.py # to run a specific test
-$ # or outside the test folder
-$ cd ..
-$ sudo pytest ospf-topo1/test_ospf_topo1.py # to run a specific one
-```
-
-The output of the tested daemons will be available at the temporary folder of
-your machine:
-
-```shell
-$ ls /tmp/topotest/ospf-topo1.test_ospf-topo1/r1
-...
-zebra.err # zebra stderr output
-zebra.log # zebra log file
-zebra.out # zebra stdout output
-...
-```
-
-You can also run memory leak tests to get reports:
-
-```shell
-$ # Set the environment variable to apply to a specific test...
-$ sudo env TOPOTESTS_CHECK_MEMLEAK="/tmp/memleak_report_" pytest ospf-topo1/test_ospf_topo1.py
-$ # ...or apply to all tests adding this line to the configuration file
-$ echo 'memleak_path = /tmp/memleak_report_' >> pytest.ini
-$ # You can also use your editor
-$ $EDITOR pytest.ini
-$ # After running tests you should see your files:
-$ ls /tmp/memleak_report_*
-memleak_report_test_ospf_topo1.txt
-```
-
-
-## Writing a New Test
-
-This section will guide you in all recommended steps to produce a standard
-topology test.
-
-This is the recommended test writing routine:
-
-* Write a topology (Graphviz recommended)
-* Obtain configuration files
-* Write the test itself
-* Create a Pull Request
-
-
-### Topotest File Hierarchy
-
-Before starting to write any tests one must know the file hierarchy. The
-repository hierarchy looks like this:
-
-```shell
-$ cd path/to/topotest
-$ find ./*
-...
-./README.md # repository read me
-./GUIDELINES.md # this file
-./conftest.py # test hooks - pytest related functions
-./example-test # example test folder
-./example-test/__init__.py # python package marker - must always exist.
-./example-test/test_template.jpg # generated topology picture - see next section
-./example-test/test_template.dot # Graphviz dot file
-./example-test/test_template.py # the topology plus the test
-...
-./ospf-topo1 # the ospf topology test
-./ospf-topo1/r1 # router 1 configuration files
-./ospf-topo1/r1/zebra.conf # zebra configuration file
-./ospf-topo1/r1/ospfd.conf # ospf configuration file
-./ospf-topo1/r1/ospfroute.txt # 'show ip ospf' output reference file
-# removed other for shortness sake
-...
-./lib # shared test/topology functions
-./lib/topogen.py # topogen implementation
-./lib/topotest.py # topotest implementation
-```
-
-Guidelines for creating/editing topotest:
-
-* New topologies that don't fit the existing directories should create its own
-* Always remember to add the `__init__.py` to new folders, this makes auto
-  complete engines and pylint happy
-* Router (Quagga/FRR) specific code should go on topotest.py
-* Generic/repeated router actions should have an abstraction in
-  topogen.TopoRouter.
-* Generic/repeated non-router code should go to topotest.py
-* pytest related code should go to conftest.py (e.g. specialized asserts)
-
-
-### Defining the Topology
-
-The first step to write a new test is to define the topology. This step can be
-done in many ways, but the recommended is to use Graphviz to generate a drawing
-of the Topology. It allows us to see the topology graphically and to see the
-names of equipments, links and addresses.
-
-Here is an example of Graphviz dot file that generates the
-[template topology](example-test/test_template.dot) (the inlined code might get
-outdated, please see the linked file):
-
-```dot
-graph template {
-       label="template";
-
-       # Routers
-       r1 [
-               shape=doubleoctagon,
-               label="r1",
-               fillcolor="#f08080",
-               style=filled,
-       ];
-       r2 [
-               shape=doubleoctagon,
-               label="r2",
-               fillcolor="#f08080",
-               style=filled,
-       ];
-
-       # Switches
-       s1 [
-               shape=oval,
-               label="s1\n192.168.0.0/24",
-               fillcolor="#d0e0d0",
-               style=filled,
-       ];
-       s2 [
-               shape=oval,
-               label="s2\n192.168.1.0/24",
-               fillcolor="#d0e0d0",
-               style=filled,
-       ];
-
-       # Connections
-       r1 -- s1 [label="eth0\n.1"];
-
-       r1 -- s2 [label="eth1\n.100"];
-       r2 -- s2 [label="eth0\n.1"];
-}
-```
-
-Here is the produced graph:
-
-![template topology graph](example-test/test_template.jpg)
-
-
-### Generating / Obtaining Configuration Files
-
-In order to get the configuration files or command output for each router, we
-need to run the topology and execute commands in vtysh. The quickest way to
-achieve that is writing the topology building code and running the topology.
-
-To bootstrap your test topology, do the following steps:
-
-* Copy the template test
-
-```shell
-$ mkdir new-topo/
-$ touch new-topo/__init__.py
-$ cp example-test/test_template.py new-topo/test_new_topo.py
-```
-
-* Modify the template according to your dot file
-
-Here is the template topology described in the previous section in python code:
-
-```py
-class TemplateTopo(Topo):
-    "Test topology builder"
-    def build(self, *_args, **_opts):
-        "Build function"
-        tgen = get_topogen(self)
-
-        # Create 2 routers
-        for routern in range(1, 3):
-            tgen.add_router('r{}'.format(routern))
-
-        # Create a switch with just one router connected to it to simulate a
-        # empty network.
-        switch = tgen.add_switch('s1')
-        switch.add_link(tgen.gears['r1'])
-
-        # Create a connection between r1 and r2
-        switch = tgen.add_switch('s2')
-        switch.add_link(tgen.gears['r1'])
-        switch.add_link(tgen.gears['r2'])
-```
-
-* Run the topology
-
-Topogen allows us to run the topology without running any tests, you can do that
-using the following example commands:
-
-```shell
-$ # Running your bootstraped topology
-$ sudo pytest -s --topology-only new-topo/test_new_topo.py
-$ # Running the test_template.py topology
-$ sudo pytest -s --topology-only example-test/test_template.py
-$ # Running the ospf_topo1.py topology
-$ sudo pytest -s --topology-only ospf-topo1/test_ospf_topo1.py
-```
-
-Parameters explanation:
-
-* `-s`: actives input/output capture. This is required by mininet in order to show
-  the interactive shell.
-* `--topology-only`: don't run any tests, just build the topology.
-
-After executing the commands above, you should get the following terminal
-output:
-
-```shell
-=== test session starts ===
-platform linux2 -- Python 2.7.12, pytest-3.1.2, py-1.4.34, pluggy-0.4.0
-rootdir: /media/sf_src/topotests, inifile: pytest.ini
-collected 3 items
-
-ospf-topo1/test_ospf_topo1.py *** Starting controller
-
-*** Starting 6 switches
-switch1 switch2 switch3 switch4 switch5 switch6 ...
-r2: frr zebra started
-r2: frr ospfd started
-r3: frr zebra started
-r3: frr ospfd started
-r1: frr zebra started
-r1: frr ospfd started
-r4: frr zebra started
-r4: frr ospfd started
-*** Starting CLI:
-mininet>
-```
-
-The last line shows us that we are now using the Mininet CLI (Command Line
-Interface), from here you can call your router vtysh or even bash.
-
-Here are some commands example:
-
-```shell
-mininet> r1 ping 10.0.3.1
-PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data.
-64 bytes from 10.0.3.1: icmp_seq=1 ttl=64 time=0.576 ms
-64 bytes from 10.0.3.1: icmp_seq=2 ttl=64 time=0.083 ms
-64 bytes from 10.0.3.1: icmp_seq=3 ttl=64 time=0.088 ms
-^C
---- 10.0.3.1 ping statistics ---
-3 packets transmitted, 3 received, 0% packet loss, time 1998ms
-rtt min/avg/max/mdev = 0.083/0.249/0.576/0.231 ms
-
-
-
-mininet> r1 ping 10.0.3.3
-PING 10.0.3.3 (10.0.3.3) 56(84) bytes of data.
-64 bytes from 10.0.3.3: icmp_seq=1 ttl=64 time=2.87 ms
-64 bytes from 10.0.3.3: icmp_seq=2 ttl=64 time=0.080 ms
-64 bytes from 10.0.3.3: icmp_seq=3 ttl=64 time=0.091 ms
-^C
---- 10.0.3.3 ping statistics ---
-3 packets transmitted, 3 received, 0% packet loss, time 2003ms
-rtt min/avg/max/mdev = 0.080/1.014/2.872/1.313 ms
-
-
-
-mininet> r3 vtysh
-
-Hello, this is FRRouting (version 3.1-devrzalamena-build).
-Copyright 1996-2005 Kunihiro Ishiguro, et al.
-
-frr-1# show running-config
-Building configuration...
-
-Current configuration:
-!
-frr version 3.1-devrzalamena-build
-frr defaults traditional
-hostname r3
-no service integrated-vtysh-config
-!
-log file zebra.log
-!
-log file ospfd.log
-!
-interface r3-eth0
- ip address 10.0.3.1/24
-!
-interface r3-eth1
- ip address 10.0.10.1/24
-!
-interface r3-eth2
- ip address 172.16.0.2/24
-!
-router ospf
- ospf router-id 10.0.255.3
- redistribute kernel
- redistribute connected
- redistribute static
- network 10.0.3.0/24 area 0
- network 10.0.10.0/24 area 0
- network 172.16.0.0/24 area 1
-!
-line vty
-!
-end
-frr-1#
-```
-
-After you successfully configured your topology, you can obtain the
-configuration files (per-daemon) using the following commands:
-
-```shell
-mininet> r3 vtysh -d ospfd
-
-Hello, this is FRRouting (version 3.1-devrzalamena-build).
-Copyright 1996-2005 Kunihiro Ishiguro, et al.
-
-frr-1# show running-config
-Building configuration...
-
-Current configuration:
-!
-frr version 3.1-devrzalamena-build
-frr defaults traditional
-no service integrated-vtysh-config
-!
-log file ospfd.log
-!
-router ospf
- ospf router-id 10.0.255.3
- redistribute kernel
- redistribute connected
- redistribute static
- network 10.0.3.0/24 area 0
- network 10.0.10.0/24 area 0
- network 172.16.0.0/24 area 1
-!
-line vty
-!
-end
-frr-1#
-```
-
-
-### Writing Tests
-
-Test topologies should always be bootstrapped from the
-[example-test/test_template.py](example-test/test_template.py),
-because it contains important boilerplate code that can't be avoided, like:
-
-* imports: os, sys, pytest, topotest/topogen and mininet topology class
-* The global variable CWD (Current Working directory): which is most likely
-  going to be used to reference the routers configuration file location
-
-  Example:
-
-```py
-# For all registered routers, load the zebra configuration file
-for rname, router in router_list.iteritems():
-    router.load_config(
-        TopoRouter.RD_ZEBRA,
-        os.path.join(CWD, '{}/zebra.conf'.format(rname))
-    )
-    # os.path.join() joins the CWD string with arguments adding the necessary
-    # slashes ('/'). Arguments must not begin with '/'.
-```
-
-* The topology class that inherits from Mininet Topo class
-
-```py
-class TemplateTopo(Topo):
-  def build(self, *_args, **_opts):
-    tgen = get_topogen(self)
-    # topology build code
-```
-
-* pytest `setup_module()` and `teardown_module()` to start the topology
-
-```py
-def setup_module(_m):
-    tgen = Topogen(TemplateTopo)
-    tgen.start_topology('debug')
-
-def teardown_module(_m):
-    tgen = get_topogen()
-    tgen.stop_topology()
-```
-
-* `__main__` initialization code (to support running the script directly)
-
-```py
-if __name__ == '__main__':
-    sys.exit(pytest.main(["-s"]))
-```
-
-Requirements:
-
-* Test code should always be declared inside functions that begin with the
-  `test_` prefix. Functions beginning with different prefixes will not be run by
-  pytest.
-* Configuration files and long output commands should go into separated files
-  inside folders named after the equipment.
-* Tests must be able to run without any interaction. To make sure your test
-  conforms with this, run it without the `-s` parameter.
-
-Tips:
-
-* Keep results in stack variables, so people inspecting code with `pdb` can
-  easily print their values.
-
-  Don't do this:
-
-  ```py
-  assert foobar(router1, router2)
-  ```
-
-  Do this instead:
-
-  ```py
-  result = foobar(router1, router2)
-  assert result
-  ```
-
-* Use `assert` messages to indicate where the test failed.
-
-  Example:
-
-  ```py
-  for router in router_list:
-      # ...
-      assert condition, 'Router "{}" condition failed'.format(router.name)
-  ```
-
-
-### Debugging Execution
-
-The most effective ways to inspect topology tests are:
-
-* Run pytest with `--pdb` option. This option will cause a pdb shell to appear
-  when an assertion fails
-
-  Example: `pytest -s --pdb ospf-topo1/test_ospf_topo1.py`
-
-* Set a breakpoint in the test code with `pdb`
-
-  Example:
-
-```py
-# Add the pdb import at the beginning of the file
-import pdb
-# ...
-
-# Add a breakpoint where you think the problem is
-def test_bla():
-  # ...
-  pdb.set_trace()
-  # ...
-```
-
-The [Python Debugger](https://docs.python.org/2.7/library/pdb.html) (pdb) shell
-allows us to run many useful operations like:
-
-* Setting breaking point on file/function/conditions (e.g. `break`, `condition`)
-* Inspecting variables (e.g. `p` (print), `pp` (pretty print))
-* Running python code
-
-TIP: The TopoGear (equipment abstraction class) implements the `__str__` method
-that allows the user to inspect equipment information.
-
-Example of pdb usage:
-
-```shell
-> /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(121)test_ospf_convergence()
--> for rnum in range(1, 5):
-(Pdb) help
-Documented commands (type help <topic>):
-========================================
-EOF    bt         cont      enable  jump  pp       run      unt
-a      c          continue  exit    l     q        s        until
-alias  cl         d         h       list  quit     step     up
-args   clear      debug     help    n     r        tbreak   w
-b      commands   disable   ignore  next  restart  u        whatis
-break  condition  down      j       p     return   unalias  where
-
-Miscellaneous help topics:
-==========================
-exec  pdb
-
-Undocumented commands:
-======================
-retval  rv
-
-(Pdb) list
-116                                   title2="Expected output")
-117
-118     def test_ospf_convergence():
-119         "Test OSPF daemon convergence"
-120         pdb.set_trace()
-121  ->     for rnum in range(1, 5):
-122             router = 'r{}'.format(rnum)
-123  
-124             # Load expected results from the command
-125             reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router))
-126             expected = open(reffile).read()
-(Pdb) step
-> /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(122)test_ospf_convergence()
--> router = 'r{}'.format(rnum)
-(Pdb) step
-> /media/sf_src/topotests/ospf-topo1/test_ospf_topo1.py(125)test_ospf_convergence()
--> reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router))
-(Pdb) print rnum
-1
-(Pdb) print router
-r1
-(Pdb) tgen = get_topogen()
-(Pdb) pp tgen.gears[router]
-<lib.topogen.TopoRouter object at 0x7f74e06c9850>
-(Pdb) pp str(tgen.gears[router])
-'TopoGear<name="r1",links=["r1-eth0"<->"s1-eth0","r1-eth1"<->"s3-eth0"]> TopoRouter<>'
-(Pdb) l 125
-120         pdb.set_trace()
-121         for rnum in range(1, 5):
-122             router = 'r{}'.format(rnum)
-123
-124             # Load expected results from the command
-125  ->         reffile = os.path.join(CWD, '{}/ospfroute.txt'.format(router))
-126             expected = open(reffile).read()
-127
-128             # Run test function until we get an result. Wait at most 60 seconds.
-129             test_func = partial(compare_show_ip_ospf, router, expected)
-130             result, diff = topotest.run_and_expect(test_func, '',
-(Pdb) router1 = tgen.gears[router]
-(Pdb) router1.vtysh_cmd('show ip ospf route')
-'============ OSPF network routing table ============\r\nN    10.0.1.0/24           [10] area: 0.0.0.0\r\n                           directly attached to r1-eth0\r\nN    10.0.2.0/24           [20] area: 0.0.0.0\r\n                           via 10.0.3.3, r1-eth1\r\nN    10.0.3.0/24           [10] area: 0.0.0.0\r\n                           directly attached to r1-eth1\r\nN    10.0.10.0/24          [20] area: 0.0.0.0\r\n                           via 10.0.3.1, r1-eth1\r\nN IA 172.16.0.0/24         [20] area: 0.0.0.0\r\n                           via 10.0.3.1, r1-eth1\r\nN IA 172.16.1.0/24         [30] area: 0.0.0.0\r\n                           via 10.0.3.1, r1-eth1\r\n\r\n============ OSPF router routing table =============\r\nR    10.0.255.2            [10] area: 0.0.0.0, ASBR\r\n                           via 10.0.3.3, r1-eth1\r\nR    10.0.255.3            [10] area: 0.0.0.0, ABR, ASBR\r\n                           via 10.0.3.1, r1-eth1\r\nR    10.0.255.4         IA [20] area: 0.0.0.0, ASBR\r\n                           via 10.0.3.1, r1-eth1\r\n\r\n============ OSPF external routing table ===========\r\n\r\n\r\n'
-(Pdb) tgen.mininet_cli()
-*** Starting CLI:
-mininet>
-```
-
-To enable more debug messages in other Topogen subsystems (like Mininet), more
-logging messages can be displayed by modifying the test configuration file
-`pytest.ini`:
-
-```ini
-[topogen]
-# Change the default verbosity line from 'info'...
-#verbosity = info
-# ...to 'debug'
-verbosity = debug
-```
index a495675ee9291cf3b5891bbc51fba6e4904055c8..d9d849b39f1fb034f4f421a7f1eb43e02c4673e3 100644 (file)
@@ -1,199 +1 @@
-# FRRouting Topology Tests with Mininet
-
-## Running tests with docker
-
-There is a docker image which allows to run topotests. Instructions can be
-found [here](docker/README.md).
-
-## Guidelines
-
-Instructions for  use, write or debug topologies can be found in the
-[guidelines](GUIDELINES.md). To learn/remember common code snippets see
-[here](SNIPPETS.md).
-
-Before creating a new topology, make sure that there isn't one already
-that does what you need. If nothing is similar, then you may create a
-new topology, preferably, using the newest
-[template](example-test/test_template.py).
-
-## Installation of Mininet for running tests
-Only tested with Ubuntu 16.04 and Ubuntu 18.04 (which uses Mininet 2.2.x)
-
-Instructions are the same for all setups (ie ExaBGP is only used for BGP 
-tests)
-
-### Installing Mininet Infrastructure:
-
-1. apt-get install mininet
-2. apt-get install python-pip
-3. apt-get install iproute
-4. pip install ipaddr
-5. pip install pytest
-6. pip install exabgp==3.4.17
-   (Newer 4.0 version of exabgp is not yet supported)
-7. useradd -d /var/run/exabgp/ -s /bin/false exabgp
-
-### Enable Coredumps
-Optional, will give better output
-
-1. apt-get install gdb
-2. disable apport (which move core files)
-
-       Set `enabled=0` in `/etc/default/apport`
-               
-3. Update security limits
-
-       Add/change `/etc/security/limits.conf` to
-       
-               #<domain>      <type>  <item>         <value>
-               *               soft    core          unlimited
-               root            soft    core          unlimited
-               *               hard    core          unlimited
-               root            hard    core          unlimited
-4. reboot (for options to take effect)
-
-## FRRouting (FRR) Installation
-FRR needs to be installed separatly. It is assume to be configured 
-like the standard Ubuntu Packages:
-
-- Binaries in /usr/lib/frr
-- State Directory /var/run/frr
-- Running under user frr, group frr
-- vtygroup: frrvty
-- config directory: /etc/frr
-- For FRR Packages, install the dbg package as well for coredump decoding
-
-No FRR config needs to be done and no FRR daemons should be run ahead
-of the test. They are all started as part of the test
-
-#### Manual FRRouting (FRR) build
-
-If you prefer to manually build FRR, then use the following suggested config:
-
-       ./configure \
-               --prefix=/usr \
-               --localstatedir=/var/run/frr \
-               --sbindir=/usr/lib/frr \
-               --sysconfdir=/etc/frr \
-               --enable-vtysh \
-               --enable-pimd \
-               --enable-multipath=64 \
-               --enable-user=frr \
-               --enable-group=frr \
-               --enable-vty-group=frrvty \
-               --with-pkg-extra-version=-my-manual-build
-
-And create frr User and frrvty group as follows:
-
-       addgroup --system --gid 92 frr
-       addgroup --system --gid 85 frrvty
-       adduser --system --ingroup frr --home /var/run/frr/ \
-          --gecos "FRRouting suite" --shell /bin/false frr
-       usermod -G frrvty frr
-
-## Executing Tests
-
-#### Execute all tests with output to console
-
-       py.test -s -v --tb=no
-
-All test_* scripts in subdirectories are detected and executed (unless
-disabled in `pytest.ini` file)
-
-`--tb=no` disables the python traceback which might be irrelevant unless the
-test script itself is debugged
-
-#### Execute single test
-
-       cd test_to_be_run
-       ./test_to_be_run.py
-
-For further options, refer to pytest documentation
-
-Test will set exit code which can be used with `git bisect`
-
-For the simulated topology, see the description in the python file
-
-If you need to clear the mininet setup between tests (if it isn't cleanly
-shutdown), then use the `mn -c` command to clean up the environment
-
-#### (Optional) StdErr log from daemos after exit
-
-To enable the reporting of any messages seen on StdErr after the
-daemons exit, the following env variable can be set.
-
-       export TOPOTESTS_CHECK_STDERR=Yes
-
-(The value doesn't matter at this time. The check is if the env variable
-exists or not)
-There is no pass/fail on this reporting. The Output will be reported to
-the console
-
-       export TOPOTESTS_CHECK_MEMLEAK="/home/mydir/memleak_"
-
-This will enable the check and output to console and the writing of
-the information to files with the given prefix (followed by testname),
-ie `/home/mydir/memcheck_test_bgp_multiview_topo1.txt` in case of a 
-memory leak.
-
-#### (Optional) Collect Memory Leak Information
-
-FreeRangeRouting processes have the capabilities to report remaining memory
-allocations upon exit. To enable the reporting of the memory, define an
-enviroment variable `TOPOTESTS_CHECK_MEMLEAK` with the file prefix, ie
-
-       export TOPOTESTS_CHECK_MEMLEAK="/home/mydir/memleak_"
-
-This will enable the check and output to console and the writing of
-the information to files with the given prefix (followed by testname),
-ie `/home/mydir/memcheck_test_bgp_multiview_topo1.txt` in case of a 
-memory leak.
-
-#### (Optional) Run topotests with GCC AddressSanitizer enabled
-
-Topotests can be run with the GCC AddressSanitizer. It requires GCC 4.8 or
-newer. (Ubuntu 16.04 as suggested here is fine with GCC 5 as default)
-For more information on AddressSanitizer, see 
-https://github.com/google/sanitizers/wiki/AddressSanitizer
-
-The checks are done automatically in the library call of `checkRouterRunning`
-(ie at beginning of tests when there is a check for all daemons running).
-No changes or extra configuration for topotests is required beside compiling
-the suite with AddressSanitizer enabled.
-
-If a daemon crashed, then the errorlog is checked for AddressSanitizer
-output. If found, then this is added with context (calling test) to
-`/tmp/AddressSanitizer.txt` in markdown compatible format.
-
-Compiling for GCC AddressSanitizer requires to use gcc as a linker as well
-(instead of ld). Here is a suggest way to compile frr with AddressSanitizer
-for `stable/3.0` branch:
-
-       git clone https://github.com/FRRouting/frr.git
-       cd frr
-       git checkout stable/3.0
-       ./bootstrap.sh
-       export CC=gcc
-       export CFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer"
-       export LD=gcc
-       export LDFLAGS="-g -fsanitize=address -ldl"
-       ./configure --enable-shared=no \
-               --prefix=/usr/lib/frr --sysconfdir=/etc/frr \
-               --localstatedir=/var/run/frr \
-               --sbindir=/usr/lib/frr --bindir=/usr/lib/frr \
-               --enable-exampledir=/usr/lib/frr/examples \
-               --with-moduledir=/usr/lib/frr/modules \
-               --enable-multipath=0 --enable-rtadv \
-               --enable-tcp-zebra --enable-fpm --enable-pimd
-       make
-       sudo make install
-       # Create symlink for vtysh, so topotest finds it in /usr/lib/frr
-       sudo ln -s /usr/lib/frr/vtysh /usr/bin/
-
-and create `frr` user and `frrvty` group as shown above
-
-## License
-
-All the configs and scripts are licensed under a ISC-style license. See
-Python scripts for details.
+Documentation is located in /doc/developer/topotests.rst
diff --git a/tests/topotests/SNIPPETS.md b/tests/topotests/SNIPPETS.md
deleted file mode 100644 (file)
index 6c16c44..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-# Snippets
-
-This document will describe common snippets of code that are frequently
-needed to perform some test checks.
-
-
-## Checking for router / test failures
-
-The following check uses the topogen API to check for software failure
-(e.g. zebra died) and/or for errors manually set by `Topogen.set_error()`.
-
-```py
-# Get the topology reference
-tgen = get_topogen()
-
-# Check for errors in the topology
-if tgen.routers_have_failure():
-    # Skip the test with the topology errors as reason
-    pytest.skip(tgen.errors)
-```
-
-
-## Checking FRR routers version
-
-This code snippet is usually run after the topology setup to make sure
-all routers instantiated in the topology have the correct software
-version.
-
-```py
-# Get the topology reference
-tgen = get_topogen()
-
-# Get the router list
-router_list = tgen.routers()
-
-# Run the check for all routers
-for router in router_list.values():
-    if router.has_version('<', '3'):
-        # Set topology error, so the next tests are skipped
-        tgen.set_error('unsupported version')
-```
-
-A sample of this snippet in a test can be found
-[here](ldp-vpls-topo1/test_ldp_vpls_topo1.py).
-
-
-## Interacting with equipments
-
-You might want to interact with the topology equipments during the tests
-and there are different ways to do so.
-
-Notes:
-
-1.
-> When using the Topogen API, all the equipments code derive from
-> `Topogear` ([lib/topogen.py](lib/topogen.py)). If you feel brave you
-> can look by yourself how the abstractions that will be mentioned here
-> works.
-
-2.
-> When not using the `Topogen` API there is only one way to interact
-> with the equipments, which is by calling the `mininet` API functions
-> directly to spawn commands.
-
-
-### Interacting with the Linux sandbox
-
-*Without `Topogen`*
-
-```py
-global net
-output = net['r1'].cmd('echo "foobar"')
-print 'output is: {}'.format(output)
-```
-
----
-
-*With `Topogen`*
-
-```py
-tgen = get_topogen()
-output = tgen.gears['r1'].run('echo "foobar"')
-print 'output is: {}'.format(output)
-```
-
-
-### Interacting with VTYSH
-
-*Without `Topogen`*
-
-```py
-global net
-output = net['r1'].cmd('vtysh "show ip route" 2>/dev/null')
-print 'output is: {}'.format(output)
-```
-
----
-
-*With `Topogen`*
-
-```py
-tgen = get_topogen()
-output = tgen.gears['r1'].vtysh_cmd("show ip route")
-print 'output is: {}'.format(output)
-```
-
-`Topogen` also supports sending multiple lines of command:
-
-```py
-tgen = get_topogen()
-output = tgen.gears['r1'].vtysh_cmd("""
-configure terminal
-router bgp 10
-  bgp router-id 10.0.255.1
-  neighbor 1.2.3.4 remote-as 10
-  !
-router bgp 11
-  bgp router-id 10.0.255.2
-  !
-""")
-print 'output is: {}'.format(output)
-```
-
-You might also want to run multiple commands and get only the commands
-that failed:
-
-```py
-tgen = get_topogen()
-output = tgen.gears['r1'].vtysh_multicmd("""
-configure terminal
-router bgp 10
-  bgp router-id 10.0.255.1
-  neighbor 1.2.3.4 remote-as 10
-  !
-router bgp 11
-  bgp router-id 10.0.255.2
-  !
-""", pretty_output=false)
-print 'output is: {}'.format(output)
-```
-
-Translating vtysh JSON output into Python structures:
-```py
-tgen = get_topogen()
-json_output = tgen.gears['r1'].vtysh_cmd("show ip route json", isjson=True)
-output = json.dumps(json_output, indent=4)
-print 'output is: {}'.format(output)
-
-# You can also access the data structure as normal. For example:
-# protocol = json_output['1.1.1.1/32']['protocol']
-# assert protocol == "ospf", "wrong protocol"
-```
-
-*NOTE:* `vtysh_(multi)cmd` is only available for router type of
-equipments.
-
-
-### Invoking `mininet` CLI
-
-*Without `Topogen`*
-
-```py
-CLI(net)
-```
-
----
-
-*With `Topogen`*
-```py
-tgen = get_topogen()
-tgen.mininet_cli()
-```
-
-
-## Reading files
-
-Loading a normal text file content in the current directory:
-
-```py
-# If you are using Topogen
-# CURDIR = CWD
-#
-# Otherwise find the directory manually:
-CURDIR = os.path.dirname(os.path.realpath(__file__))
-
-file_name = '{}/r1/show_ip_route.txt'.format(CURDIR)
-file_content = open(file_name).read()
-```
-
-Loading JSON from a file:
-
-```py
-import json
-
-file_name = '{}/r1/show_ip_route.json'.format(CURDIR)
-file_content = json.loads(open(file_name).read())
-```
-
-
-## Comparing JSON output
-
-After obtaining JSON output formated with Python data structures, you
-may use it to assert a minimalist schema:
-
-```py
-tgen = get_topogen()
-json_output = tgen.gears['r1'].vtysh_cmd("show ip route json", isjson=True)
-
-expect = {
-  '1.1.1.1/32': {
-    'protocol': 'ospf'
-  }
-}
-
-assertmsg = "route 1.1.1.1/32 was not learned through OSPF"
-assert json_cmp(json_output, expect) is None, assertmsg
-```
-
-`json_cmp` function description (it might be outdated, you can find the
-latest description in the source code at [lib/topotest.py](lib/topotest.py)):
-
-```text
-    JSON compare function. Receives two parameters:
-    * `d1`: json value
-    * `d2`: json subset which we expect
-
-    Returns `None` when all keys that `d1` has matches `d2`,
-    otherwise a string containing what failed.
-
-    Note: key absence can be tested by adding a key with value `None`.
-```
-
-
-## Pausing execution
-
-Preferably, choose the `sleep` function that `topotest` provides, as it
-prints a notice during the test execution to help debug topology test
-execution time.
-
-```py
-# Using the topotest sleep
-from lib import topotest
-
-topotest.sleep(10, 'waiting 10 seconds for bla')
-# or just tell it the time:
-# topotest.sleep(10)
-# It will print 'Sleeping for 10 seconds'.
-
-# Or you can also use the Python sleep, but it won't show anything
-from time import sleep
-sleep(5)
-```
-
-
-## `ip route` Linux command as JSON
-
-`topotest` has two helpers implemented that parses the output of
-`ip route` commands to JSON. It might simplify your comparison needs by
-only needing to provide a Python dictionary.
-
-```py
-from lib import topotest
-
-tgen = get_topogen()
-routes = topotest.ip4_route(tgen.gears['r1'])
-expected = {
-  '10.0.1.0/24': {},
-  '10.0.2.0/24': {
-    'dev': 'r1-eth0'
-  }
-}
-
-assertmsg = "failed to find 10.0.1.0/24 and/or 10.0.2.0/24"
-assert json_cmp(routes, expected) is None, assertmsg
-```
index 36dd5da5979599ca905598cfab63306775a70cf0..26fa7ca415e1226034fa631190865aef833c4137 100644 (file)
@@ -3,7 +3,7 @@
     {
       "prefix":"192.168.1.0/24",
       "protocol":"eigrp",
-      "metric":0,
+      "metric":28160,
       "nexthops":[
         {
           "directlyConnected":true,
@@ -31,7 +31,7 @@
       "prefix":"192.168.3.0/24",
       "protocol":"eigrp",
       "selected":true,
-      "metric":0,
+      "metric":33280,
       "nexthops":[
         {
           "fib":true,
@@ -47,7 +47,7 @@
     {
       "prefix":"193.1.1.0/26",
       "protocol":"eigrp",
-      "metric":0,
+      "metric":28160,
       "nexthops":[
         {
           "directlyConnected":true,
@@ -75,7 +75,7 @@
       "prefix":"193.1.2.0/24",
       "protocol":"eigrp",
       "selected":true,
-      "metric":0,
+      "metric":30720,
       "nexthops":[
         {
           "fib":true,
index 44903ce3ff6314899b379e91dcae9ac6b8a496d6..71c931b17a6728a11631d1794d4e8b6697fd243e 100644 (file)
@@ -4,7 +4,7 @@
       "prefix":"192.168.1.0/24",
       "protocol":"eigrp",
       "selected":true,
-      "metric":0,
+      "metric":30720,
       "nexthops":[
         {
           "fib":true,
@@ -21,7 +21,7 @@
       "prefix":"192.168.3.0/24",
       "protocol":"eigrp",
       "selected":true,
-      "metric":0,
+      "metric":30720,
       "nexthops":[
         {
           "fib":true,
@@ -37,7 +37,7 @@
     {
       "prefix":"193.1.1.0/26",
       "protocol":"eigrp",
-      "metric":0,
+      "metric":28160,
       "nexthops":[
         {
           "directlyConnected":true,
@@ -64,7 +64,7 @@
     {
       "prefix":"193.1.2.0/24",
       "protocol":"eigrp",
-      "metric":0,
+      "metric":28160,
       "nexthops":[
         {
           "directlyConnected":true,
index d80e1d97e62c7f4b94e357852cc5a3a3ce860b77..5e0b79d8113257ea7093dd03e4ef845b57b7835c 100644 (file)
@@ -4,7 +4,7 @@
       "prefix":"192.168.1.0/24",
       "protocol":"eigrp",
       "selected":true,
-      "metric":0,
+      "metric":33280,
       "nexthops":[
         {
           "fib":true,
@@ -38,7 +38,7 @@
     {
       "prefix":"192.168.3.0/24",
       "protocol":"eigrp",
-      "metric":0,
+      "metric":28160,
       "nexthops":[
         {
           "directlyConnected":true,
@@ -66,7 +66,7 @@
       "prefix":"193.1.1.0/26",
       "protocol":"eigrp",
       "selected":true,
-      "metric":0,
+      "metric":30720,
       "nexthops":[
         {
           "fib":true,
@@ -82,7 +82,7 @@
     {
       "prefix":"193.1.2.0/24",
       "protocol":"eigrp",
-      "metric":0,
+      "metric":28160,
       "nexthops":[
         {
           "directlyConnected":true,
index de8cb81f8ff25720d9a01831f4301b119d2ce568..8ea2f0b506e263c9194ad340855533b9dc535d04 100755 (executable)
@@ -153,7 +153,6 @@ def test_eigrp_routes():
         assertmsg = '"show ip eigrp topo" mismatches on {}'.format(router.name)
         assert topotest.json_cmp(actual, expected) is None, assertmsg
 
-
 def test_zebra_ipv4_routingTable():
     "Test 'show ip route'"
 
index b1cf342898d47288e019383cf7aceef22ba30b9d..e826793657641c1f3116e2dc15e04294f5775500 100644 (file)
@@ -1,3 +1,7 @@
+debug zebra kernel
+debug zebra dplane detail
+debug zebra rib
+debug zebra event
 !
 hostname r1
 password zebra
index c7568593b36d22c6dbcddc07ca8e2f9c644de47a..aa45f420fea3b8559649da23b1b903c294d14031 100644 (file)
@@ -1,7 +1,9 @@
 [Unit]
 Description=FRRouting
 Documentation=https://frrouting.readthedocs.io/en/latest/setup.html
-After=networking.service
+Wants=network.target
+After=network-pre.target systemd-sysctl.service
+Before=network.target
 OnFailure=heartbeat-failed@%n.service
 
 [Service]
@@ -20,4 +22,4 @@ ExecStop=/usr/lib/frr/frrinit.sh stop
 ExecReload=/usr/lib/frr/frrinit.sh reload
 
 [Install]
-WantedBy=network-online.target
+WantedBy=multi-user.target
index 340c9be60156e0d1456749dd904f4c6f6ec6f69c..41fd6ed7d68affd77e60c2e81735581a0bf2c379 100644 (file)
@@ -3330,7 +3330,7 @@ static void vtysh_client_sorted_insert(struct vtysh_client *head_client,
 
 #define MAXIMUM_INSTANCES 10
 
-static void vtysh_update_all_insances(struct vtysh_client *head_client)
+static void vtysh_update_all_instances(struct vtysh_client *head_client)
 {
        struct vtysh_client *client;
        DIR *dir;
@@ -3373,7 +3373,7 @@ static int vtysh_connect_all_instances(struct vtysh_client *head_client)
        struct vtysh_client *client;
        int rc = 0;
 
-       vtysh_update_all_insances(head_client);
+       vtysh_update_all_instances(head_client);
 
        client = head_client->next;
        while (client) {
index 0eb06d7f25919fb5586ee592ba44ff46e27d11fd..87999a1bbce03e66976b66e967959e8ee7d42d11 100644 (file)
 #include "command.h"
 #include "debug.h"
 
+#ifndef VTYSH_EXTRACT_PL
+#include "zebra/debug_clippy.c"
+#endif
+
 /* For debug statement. */
 unsigned long zebra_debug_event;
 unsigned long zebra_debug_packet;
@@ -34,6 +38,7 @@ unsigned long zebra_debug_mpls;
 unsigned long zebra_debug_vxlan;
 unsigned long zebra_debug_pw;
 unsigned long zebra_debug_dplane;
+unsigned long zebra_debug_mlag;
 
 DEFINE_HOOK(zebra_debug_show_debugging, (struct vty *vty), (vty));
 
@@ -94,6 +99,8 @@ DEFUN_NOSH (show_debugging_zebra,
                vty_out(vty, "  Zebra detailed dataplane debugging is on\n");
        else if (IS_ZEBRA_DEBUG_DPLANE)
                vty_out(vty, "  Zebra dataplane debugging is on\n");
+       if (IS_ZEBRA_DEBUG_MLAG)
+               vty_out(vty, "  Zebra mlag debugging is on\n");
 
        hook_call(zebra_debug_show_debugging, vty);
        return CMD_SUCCESS;
@@ -284,6 +291,21 @@ DEFUN (debug_zebra_dplane,
        return CMD_SUCCESS;
 }
 
+DEFPY (debug_zebra_mlag,
+       debug_zebra_mlag_cmd,
+       "[no$no] debug zebra mlag",
+       NO_STR
+       DEBUG_STR
+       "Zebra configuration\n"
+       "Debug option set for mlag events\n")
+{
+       if (no)
+               UNSET_FLAG(zebra_debug_mlag, ZEBRA_DEBUG_MLAG);
+       else
+               SET_FLAG(zebra_debug_mlag, ZEBRA_DEBUG_MLAG);
+       return CMD_SUCCESS;
+}
+
 DEFUN (no_debug_zebra_events,
        no_debug_zebra_events_cmd,
        "no debug zebra events",
@@ -507,6 +529,7 @@ void zebra_debug_init(void)
        zebra_debug_vxlan = 0;
        zebra_debug_pw = 0;
        zebra_debug_dplane = 0;
+       zebra_debug_mlag = 0;
 
        install_node(&debug_node, config_write_debug);
 
@@ -523,6 +546,7 @@ void zebra_debug_init(void)
        install_element(ENABLE_NODE, &debug_zebra_rib_cmd);
        install_element(ENABLE_NODE, &debug_zebra_fpm_cmd);
        install_element(ENABLE_NODE, &debug_zebra_dplane_cmd);
+       install_element(ENABLE_NODE, &debug_zebra_mlag_cmd);
        install_element(ENABLE_NODE, &no_debug_zebra_events_cmd);
        install_element(ENABLE_NODE, &no_debug_zebra_nht_cmd);
        install_element(ENABLE_NODE, &no_debug_zebra_mpls_cmd);
index cd15441ec8a446142d9cef5957d9458db0ad7430..c79cd96c214d53e99c17f1e99c686df2a9da09f8 100644 (file)
@@ -51,6 +51,8 @@
 #define ZEBRA_DEBUG_DPLANE           0x01
 #define ZEBRA_DEBUG_DPLANE_DETAILED  0x02
 
+#define ZEBRA_DEBUG_MLAG    0x01
+
 /* Debug related macro. */
 #define IS_ZEBRA_DEBUG_EVENT  (zebra_debug_event & ZEBRA_DEBUG_EVENT)
 
@@ -79,6 +81,8 @@
 #define IS_ZEBRA_DEBUG_DPLANE_DETAIL \
        (zebra_debug_dplane & ZEBRA_DEBUG_DPLANE_DETAILED)
 
+#define IS_ZEBRA_DEBUG_MLAG (zebra_debug_mlag & ZEBRA_DEBUG_MLAG)
+
 extern unsigned long zebra_debug_event;
 extern unsigned long zebra_debug_packet;
 extern unsigned long zebra_debug_kernel;
@@ -89,6 +93,7 @@ extern unsigned long zebra_debug_mpls;
 extern unsigned long zebra_debug_vxlan;
 extern unsigned long zebra_debug_pw;
 extern unsigned long zebra_debug_dplane;
+extern unsigned long zebra_debug_mlag;
 
 extern void zebra_debug_init(void);
 
index 8bb5c6e8ef6a34e75a2db25c20c1d1d475830383..c88aadc68378e8a517efb9e969bdbf85060faa30 100644 (file)
@@ -41,7 +41,7 @@
 #include "zebra/interface.h"
 #include "zebra/rib.h"
 #include "zebra/rt.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/redistribute.h"
 #include "zebra/debug.h"
 #include "zebra/irdp.h"
@@ -153,7 +153,7 @@ static int if_zebra_new_hook(struct interface *ifp)
         * of seconds and ask again.  Hopefully it's all settled
         * down upon startup.
         */
-       thread_add_timer(zebrad.master, if_zebra_speed_update, ifp, 15,
+       thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 15,
                         &zebra_if->speed_update);
        return 0;
 }
index ffc49d2c1364d14149c5e9cd755fb111de012b07..c0b772cd014d49626cc6197f88eb709b544eb876 100644 (file)
@@ -45,7 +45,7 @@
 #include "zebra/interface.h"
 #include "zebra/rtadv.h"
 #include "zebra/rib.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/redistribute.h"
 #include "zebra/irdp.h"
 #include "zebra/zebra_errors.h"
@@ -285,7 +285,7 @@ static void irdp_if_start(struct interface *ifp, int multicast,
                           timer);
 
        irdp->t_advertise = NULL;
-       thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer,
+       thread_add_timer(zrouter.master, irdp_send_thread, ifp, timer,
                         &irdp->t_advertise);
 }
 
index 9300ba6034f888ad41980ebbfe049ad94e38d6fd..a9734056bc09e320387ef932b2d89b9c47498ef1 100644 (file)
@@ -56,7 +56,7 @@
 #include "zebra/interface.h"
 #include "zebra/rtadv.h"
 #include "zebra/rib.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/redistribute.h"
 #include "zebra/irdp.h"
 #include "zebra/zebra_errors.h"
@@ -113,7 +113,7 @@ int irdp_sock_init(void)
        };
 
        t_irdp_raw = NULL;
-       thread_add_read(zebrad.master, irdp_read_raw, NULL, sock, &t_irdp_raw);
+       thread_add_read(zrouter.master, irdp_read_raw, NULL, sock, &t_irdp_raw);
 
        return sock;
 }
@@ -245,7 +245,7 @@ int irdp_send_thread(struct thread *t_advert)
                           timer);
 
        irdp->t_advertise = NULL;
-       thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer,
+       thread_add_timer(zrouter.master, irdp_send_thread, ifp, timer,
                         &irdp->t_advertise);
        return 0;
 }
@@ -306,7 +306,7 @@ void process_solicit(struct interface *ifp)
        timer = (random() % MAX_RESPONSE_DELAY) + 1;
 
        irdp->t_advertise = NULL;
-       thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer,
+       thread_add_timer(zrouter.master, irdp_send_thread, ifp, timer,
                         &irdp->t_advertise);
 }
 
index bebccd716820403b20c856e07e8f7da6ba0d75bc..774d84d66d87bd1274029bb5755e5c32bdab8033 100644 (file)
@@ -58,7 +58,7 @@
 #include "zebra/interface.h"
 #include "zebra/rtadv.h"
 #include "zebra/rib.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/redistribute.h"
 #include "zebra/irdp.h"
 #include "zebra/zebra_errors.h"
@@ -230,7 +230,7 @@ int irdp_read_raw(struct thread *r)
 
        int irdp_sock = THREAD_FD(r);
        t_irdp_raw = NULL;
-       thread_add_read(zebrad.master, irdp_read_raw, NULL, irdp_sock,
+       thread_add_read(zrouter.master, irdp_read_raw, NULL, irdp_sock,
                        &t_irdp_raw);
 
        ret = irdp_recvmsg(irdp_sock, (uint8_t *)buf, IRDP_RX_BUF, &ifindex);
index c88bfbb1018be693b562fa0fa5fd85bd5b9b4246..2f850c6338d51a9fdf7916a6bf264896d171ee6a 100644 (file)
@@ -43,7 +43,8 @@
 #include "mpls.h"
 #include "lib_errors.h"
 
-#include "zebra/zserv.h"
+//#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/zebra_ns.h"
 #include "zebra/zebra_vrf.h"
 #include "zebra/rt.h"
@@ -388,7 +389,7 @@ static int kernel_read(struct thread *thread)
        netlink_parse_info(netlink_information_fetch, &zns->netlink, &dp_info,
                           5, 0);
        zns->t_netlink = NULL;
-       thread_add_read(zebrad.master, kernel_read, zns, zns->netlink.sock,
+       thread_add_read(zrouter.master, kernel_read, zns, zns->netlink.sock,
                        &zns->t_netlink);
 
        return 0;
@@ -1158,7 +1159,7 @@ void kernel_init(struct zebra_ns *zns)
 
        zns->t_netlink = NULL;
 
-       thread_add_read(zebrad.master, kernel_read, zns,
+       thread_add_read(zrouter.master, kernel_read, zns,
                        zns->netlink.sock, &zns->t_netlink);
 
        rt_netlink_init();
index acd7f911dcefbf62888908f7305a67387ad1bc87..792756efebdbaf161b5ea7a21e7d2ea8012fff51 100644 (file)
@@ -43,7 +43,7 @@
 
 #include "zebra/rt.h"
 #include "zebra/interface.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/debug.h"
 #include "zebra/kernel_socket.h"
 #include "zebra/rib.h"
@@ -1372,7 +1372,7 @@ static int kernel_read(struct thread *thread)
                return 0;
        }
 
-       thread_add_read(zebrad.master, kernel_read, NULL, sock, NULL);
+       thread_add_read(zrouter.master, kernel_read, NULL, sock, NULL);
 
        if (IS_ZEBRA_DEBUG_KERNEL)
                rtmsg_debug(&buf.r.rtm);
@@ -1445,7 +1445,7 @@ static void routing_socket(struct zebra_ns *zns)
          zlog_warn ("Can't set O_NONBLOCK to routing socket");*/
 
        /* kernel_read needs rewrite. */
-       thread_add_read(zebrad.master, kernel_read, NULL, routing_sock, NULL);
+       thread_add_read(zrouter.master, kernel_read, NULL, routing_sock, NULL);
 }
 
 /* Exported interface function.  This function simply calls
index 13472059a0614ce0fee7ebe1b4264dcf81ac1f7a..1b17845e41ec14bd16893a367399b05fd4f80e8d 100644 (file)
@@ -34,7 +34,8 @@
 #include "lib/zclient.h"
 #include "lib/libfrr.h"
 
-#include "zebra/zserv.h"
+//#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/label_manager.h"
 #include "zebra/zebra_errors.h"
 
@@ -294,7 +295,7 @@ static int lm_zclient_connect(struct thread *t)
        if (zclient_socket_connect(zclient) < 0) {
                flog_err(EC_ZEBRA_LM_CLIENT_CONNECTION_FAILED,
                         "Error connecting synchronous zclient!");
-               thread_add_timer(zebrad.master, lm_zclient_connect, zclient,
+               thread_add_timer(zrouter.master, lm_zclient_connect, zclient,
                                 CONNECTION_DELAY, &zclient->t_connect);
                return -1;
        }
@@ -318,7 +319,7 @@ static void lm_zclient_init(char *lm_zserv_path)
                                 lm_zserv_path);
 
        /* Set default values. */
-       zclient = zclient_new(zebrad.master, &zclient_options_default);
+       zclient = zclient_new(zrouter.master, &zclient_options_default);
        zclient->privs = &zserv_privs;
        zclient->sock = -1;
        zclient->t_connect = NULL;
index b54c36c109eaea698141dc73e224aefe9b862d0b..c605050c57fe37ae2e70665573bfebc0cd974c49 100644 (file)
 
 #define ZEBRA_PTM_SUPPORT
 
-/* Zebra instance */
-struct zebra_t zebrad = {
-       .rtm_table_default = 0,
-       .packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS,
-};
-
 /* process id. */
 pid_t pid;
 
@@ -156,10 +150,10 @@ static void sigint(void)
 
        zebra_dplane_pre_finish();
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, ln, nn, client))
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, ln, nn, client))
                zserv_close_client(client);
 
-       list_delete_all_node(zebrad.client_list);
+       list_delete_all_node(zrouter.client_list);
        zebra_ptm_finish();
 
        if (retain_mode)
@@ -168,8 +162,8 @@ static void sigint(void)
                        if (zvrf)
                                SET_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN);
                }
-       if (zebrad.lsp_process_q)
-               work_queue_free_and_null(&zebrad.lsp_process_q);
+       if (zrouter.lsp_process_q)
+               work_queue_free_and_null(&zrouter.lsp_process_q);
        vrf_terminate();
 
        ns_walk_func(zebra_ns_early_shutdown);
@@ -179,7 +173,7 @@ static void sigint(void)
        prefix_list_reset();
        route_map_finish();
 
-       list_delete(&zebrad.client_list);
+       list_delete(&zrouter.client_list);
 
        /* Indicate that all new dplane work has been enqueued. When that
         * work is complete, the dataplane will enqueue an event
@@ -202,9 +196,6 @@ int zebra_finalize(struct thread *dummy)
        /* Stop dplane thread and finish any cleanup */
        zebra_dplane_shutdown();
 
-       work_queue_free_and_null(&zebrad.ribq);
-       meta_queue_free(zebrad.mq);
-
        zebra_router_terminate();
 
        frr_fini();
@@ -391,7 +382,7 @@ int main(int argc, char **argv)
                }
        }
 
-       zebrad.master = frr_init();
+       zrouter.master = frr_init();
 
        /* Initialize pthread library */
        frr_pthread_init();
@@ -479,7 +470,7 @@ int main(int argc, char **argv)
 #endif /* HANDLE_NETLINK_FUZZING */
 
 
-       frr_run(zebrad.master);
+       frr_run(zrouter.master);
 
        /* Not reached... */
        return 0;
index 2c5350fcebe53076f19918590ea41648ee6082ac..f98a4c02c320d8779e89cfb66199b87fdcd3efdd 100644 (file)
@@ -33,7 +33,7 @@
 #include "srcdest_table.h"
 
 #include "zebra/rib.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/zebra_ns.h"
 #include "zebra/zebra_vrf.h"
 #include "zebra/zebra_routemap.h"
@@ -173,7 +173,7 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p,
                return;
        }
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                send_redistribute = 0;
 
                if (is_default_prefix(p)
@@ -246,7 +246,7 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
                return;
        }
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                if ((is_default_prefix(p)
                     && vrf_bitmap_check(client->redist_default[afi],
                                         re->vrf_id))
@@ -405,12 +405,12 @@ void zebra_interface_up_update(struct interface *ifp)
                           ifp->name, ifp->vrf_id);
 
        if (ifp->ptm_status || !ifp->ptm_enable) {
-               for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
-                       if (vrf_bitmap_check(client->ifinfo, ifp->vrf_id)) {
-                               zsend_interface_update(ZEBRA_INTERFACE_UP,
-                                                      client, ifp);
-                               zsend_interface_link_params(client, ifp);
-                       }
+               for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode,
+                                      client)) {
+                       zsend_interface_update(ZEBRA_INTERFACE_UP,
+                                              client, ifp);
+                       zsend_interface_link_params(client, ifp);
+               }
        }
 }
 
@@ -424,7 +424,7 @@ void zebra_interface_down_update(struct interface *ifp)
                zlog_debug("MESSAGE: ZEBRA_INTERFACE_DOWN %s(%u)",
                           ifp->name, ifp->vrf_id);
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp);
        }
 }
@@ -439,12 +439,11 @@ void zebra_interface_add_update(struct interface *ifp)
                zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s(%u)", ifp->name,
                           ifp->vrf_id);
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
-               if (vrf_bitmap_check(client->ifinfo, ifp->vrf_id)) {
-                       client->ifadd_cnt++;
-                       zsend_interface_add(client, ifp);
-                       zsend_interface_link_params(client, ifp);
-               }
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
+               client->ifadd_cnt++;
+               zsend_interface_add(client, ifp);
+               zsend_interface_link_params(client, ifp);
+       }
 }
 
 void zebra_interface_delete_update(struct interface *ifp)
@@ -456,7 +455,7 @@ void zebra_interface_delete_update(struct interface *ifp)
                zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s(%u)",
                           ifp->name, ifp->vrf_id);
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                client->ifdel_cnt++;
                zsend_interface_delete(client, ifp);
        }
@@ -488,7 +487,7 @@ void zebra_interface_address_add_update(struct interface *ifp,
 
        router_id_add_address(ifc);
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
                if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) {
                        client->connected_rt_add_cnt++;
                        zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD,
@@ -517,7 +516,7 @@ void zebra_interface_address_delete_update(struct interface *ifp,
 
        router_id_del_address(ifc);
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
                if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) {
                        client->connected_rt_del_cnt++;
                        zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_DELETE,
@@ -538,7 +537,7 @@ void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id)
                        "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u",
                        ifp->name, ifp->vrf_id, new_vrf_id);
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                /* Need to delete if the client is not interested in the new
                 * VRF. */
                zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp);
@@ -561,7 +560,7 @@ void zebra_interface_vrf_update_add(struct interface *ifp, vrf_id_t old_vrf_id)
                        "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u",
                        ifp->name, old_vrf_id, ifp->vrf_id);
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                /* Need to add if the client is interested in the new VRF. */
                client->ifadd_cnt++;
                zsend_interface_add(client, ifp);
@@ -613,7 +612,7 @@ int zebra_add_import_table_entry(struct route_node *rn, struct route_entry *re,
        newre->flags = re->flags;
        newre->metric = re->metric;
        newre->mtu = re->mtu;
-       newre->table = zebrad.rtm_table_default;
+       newre->table = zrouter.rtm_table_default;
        newre->nexthop_num = 0;
        newre->uptime = time(NULL);
        newre->instance = re->table;
@@ -634,7 +633,7 @@ int zebra_del_import_table_entry(struct route_node *rn, struct route_entry *re)
 
        rib_delete(afi, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE, re->table,
                   re->flags, &p, NULL, re->ng.nexthop,
-                  zebrad.rtm_table_default, re->metric, re->distance, false);
+                  zrouter.rtm_table_default, re->metric, re->distance, false);
 
        return 0;
 }
@@ -649,7 +648,7 @@ int zebra_import_table(afi_t afi, uint32_t table_id, uint32_t distance,
 
        if (!is_zebra_valid_kernel_table(table_id)
            || ((table_id == RT_TABLE_MAIN)
-               || (table_id == zebrad.rtm_table_default)))
+               || (table_id == zrouter.rtm_table_default)))
                return (-1);
 
        if (afi >= AFI_MAX)
@@ -812,7 +811,6 @@ void zebra_interface_parameters_update(struct interface *ifp)
                zlog_debug("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s(%u)",
                           ifp->name, ifp->vrf_id);
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
-               if (vrf_bitmap_check(client->ifinfo, ifp->vrf_id))
-                       zsend_interface_link_params(client, ifp);
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
+               zsend_interface_link_params(client, ifp);
 }
index c500f79a6c2c0a275ebbf48ef6798dfad96e8fbd..569ffbab411f80fd0bcf0ace9680a09e63993d87 100644 (file)
 #include "rib.h"
 #include "vrf.h"
 
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/zapi_msg.h"
 #include "zebra/zebra_vrf.h"
 #include "zebra/router-id.h"
 #include "zebra/redistribute.h"
 
-/* master zebra server structure */
-extern struct zebra_t zebrad;
-
 static struct connected *router_id_find_node(struct list *l,
                                             struct connected *ifc)
 {
@@ -114,7 +111,7 @@ static void router_id_set(struct prefix *p, vrf_id_t vrf_id)
 
        router_id_get(&p2, vrf_id);
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client))
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client))
                zsend_router_id_update(client, &p2, vrf_id);
 }
 
@@ -145,7 +142,7 @@ void router_id_add_address(struct connected *ifc)
        if (prefix_same(&before, &after))
                return;
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client))
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client))
                zsend_router_id_update(client, &after, zvrf_id(zvrf));
 }
 
@@ -177,7 +174,7 @@ void router_id_del_address(struct connected *ifc)
        if (prefix_same(&before, &after))
                return;
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client))
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client))
                zsend_router_id_update(client, &after, zvrf_id(zvrf));
 }
 
index 0b14a3ef36e6d82bada50e7f145b45632e0de713..4080b0ccb287e0fbec1439d1b10841f0c803558e 100644 (file)
@@ -32,7 +32,7 @@
 #include "zebra/zebra_dplane.h"
 
 /*
- * Update or delete a route or LSP from the kernel,
+ * Update or delete a route, LSP, or pseudowire from the kernel,
  * using info from a dataplane context.
  */
 extern enum zebra_dplane_result kernel_route_update(
@@ -41,6 +41,8 @@ extern enum zebra_dplane_result kernel_route_update(
 extern enum zebra_dplane_result kernel_lsp_update(
        struct zebra_dplane_ctx *ctx);
 
+enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx);
+
 extern int kernel_address_add_ipv4(struct interface *, struct connected *);
 extern int kernel_address_delete_ipv4(struct interface *, struct connected *);
 extern int kernel_address_add_ipv6(struct interface *, struct connected *);
@@ -67,6 +69,8 @@ extern int kernel_del_mac(struct interface *ifp, vlanid_t vid,
 extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
                            struct ethaddr *mac, uint8_t flags);
 extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip);
+extern int kernel_upd_neigh(struct interface *ifp, struct ipaddr *ip,
+                           struct ethaddr *mac, uint8_t flags, uint16_t state);
 
 /*
  * Southbound Initialization routines to get initial starting
index f69df1da896a2e3ca9b822210347b2e824add471..3868412b20bb074c81628f7315faed09153e2eef 100644 (file)
@@ -1140,8 +1140,7 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
        if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
                addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
 
-       if (nexthop->type == NEXTHOP_TYPE_IFINDEX
-           || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
+       if (nexthop->type == NEXTHOP_TYPE_IFINDEX) {
                if (cmd == RTM_NEWROUTE) {
                        if (nexthop->rmap_src.ipv4.s_addr)
                                addattr_l(nlmsg, req_size, RTA_PREFSRC,
@@ -1157,23 +1156,6 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
                                "nexthop via if %u(%u)",
                                routedesc, nexthop->ifindex, nexthop->vrf_id);
        }
-
-       if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
-               if (cmd == RTM_NEWROUTE) {
-                       if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
-                               addattr_l(nlmsg, req_size, RTA_PREFSRC,
-                                         &nexthop->rmap_src.ipv6, bytelen);
-                       else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6))
-                               addattr_l(nlmsg, req_size, RTA_PREFSRC,
-                                         &nexthop->src.ipv6, bytelen);
-               }
-
-               if (IS_ZEBRA_DEBUG_KERNEL)
-                       zlog_debug(
-                               "netlink_route_multipath() (%s): "
-                               "nexthop via if %u(%u)",
-                               routedesc, nexthop->ifindex, nexthop->vrf_id);
-       }
 }
 
 /* This function takes a nexthop as argument and
@@ -1345,8 +1327,7 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
                rtnh->rtnh_ifindex = nexthop->ifindex;
 
        /* ifindex */
-       if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
-           || nexthop->type == NEXTHOP_TYPE_IFINDEX) {
+       if (nexthop->type == NEXTHOP_TYPE_IFINDEX) {
                if (nexthop->rmap_src.ipv4.s_addr)
                        *src = &nexthop->rmap_src;
                else if (nexthop->src.ipv4.s_addr)
@@ -2720,12 +2701,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
                addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
 
        if (IS_ZEBRA_DEBUG_KERNEL)
-               zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x",
+               zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x state 0x%x",
                           nl_msg_type_to_str(cmd),
                           nl_family_to_str(req.ndm.ndm_family), ifp->name,
                           ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)),
                           mac ? prefix_mac2str(mac, buf2, sizeof(buf2))
-                              : "null", flags);
+                              : "null", flags, state);
 
        return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
                            0);
@@ -2756,6 +2737,13 @@ int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
        return netlink_neigh_update2(ifp, ip, NULL, 0, 0, RTM_DELNEIGH);
 }
 
+int kernel_upd_neigh(struct interface *ifp, struct ipaddr *ip,
+                    struct ethaddr *mac, uint8_t flags, uint16_t state)
+{
+       return netlink_neigh_update2(ifp, ip, mac, flags,
+                                    state, RTM_NEWNEIGH);
+}
+
 /*
  * MPLS label forwarding table change via netlink interface, using dataplane
  * context information.
index a22f6395c97ea719ea52a180a32a598b3b711ecb..86edc6fb5e9b9600a87a9b9617555afcf4db7dd6 100644 (file)
@@ -1698,9 +1698,9 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
 
        switch (event) {
        case RTADV_START:
-               thread_add_read(zebrad.master, rtadv_read, zns, val,
+               thread_add_read(zrouter.master, rtadv_read, zns, val,
                                &rtadv->ra_read);
-               thread_add_event(zebrad.master, rtadv_timer, zns, 0,
+               thread_add_event(zrouter.master, rtadv_timer, zns, 0,
                                 &rtadv->ra_timer);
                break;
        case RTADV_STOP:
@@ -1714,15 +1714,15 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
                }
                break;
        case RTADV_TIMER:
-               thread_add_timer(zebrad.master, rtadv_timer, zns, val,
+               thread_add_timer(zrouter.master, rtadv_timer, zns, val,
                                 &rtadv->ra_timer);
                break;
        case RTADV_TIMER_MSEC:
-               thread_add_timer_msec(zebrad.master, rtadv_timer, zns, val,
+               thread_add_timer_msec(zrouter.master, rtadv_timer, zns, val,
                                      &rtadv->ra_timer);
                break;
        case RTADV_READ:
-               thread_add_read(zebrad.master, rtadv_read, zns, val,
+               thread_add_read(zrouter.master, rtadv_read, zns, val,
                                &rtadv->ra_read);
                break;
        default:
index daa7946bc0923697783ef687c9d893aaa4d19080..1e36d020a3235a1dc942f6be5d2ac617305871f1 100644 (file)
@@ -95,6 +95,9 @@ zebra_zebra_SOURCES = \
        zebra/zebra_errors.c \
        # end
 
+zebra/debug_clippy.c: $(CLIPPY_DEPS)
+zebra/debug.$(OBJEXT): zebra/debug_clippy.c
+
 zebra/zebra_mlag_clippy.c: $(CLIPPY_DEPS)
 zebra/zebra_mlag.$(OBJEXT): zebra/zebra_mlag_clippy.c
 
index 951a411f252ea440f15e771f7dc7312b8e14b675..9b91289decb20f34c8d4a9005f721c1b75f0f9fc 100644 (file)
@@ -42,6 +42,7 @@
 #include "lib/libfrr.h"
 #include "lib/sockopt.h"
 
+#include "zebra/zebra_router.h"
 #include "zebra/rib.h"
 #include "zebra/zebra_memory.h"
 #include "zebra/zebra_ns.h"
@@ -208,12 +209,6 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp)
 {
        struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
 
-       /* Check this client need interface information. */
-       if (!vrf_bitmap_check(client->ifinfo, ifp->vrf_id)) {
-               stream_free(s);
-               return 0;
-       }
-
        if (!ifp->link_params) {
                stream_free(s);
                return 0;
@@ -365,7 +360,7 @@ static void zebra_interface_nbr_address_add_update(struct interface *ifp,
                        p->prefixlen, ifc->ifp->name);
        }
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
                zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
                                            client, ifp, ifc);
 }
@@ -389,7 +384,7 @@ static void zebra_interface_nbr_address_delete_update(struct interface *ifp,
                        p->prefixlen, ifc->ifp->name);
        }
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
                zsend_interface_nbr_address(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE,
                                            client, ifp, ifc);
 }
@@ -768,7 +763,7 @@ void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
                zlog_debug("%s: Notifying %u", __PRETTY_FUNCTION__,
                           rule->rule.unique);
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
                if (rule->sock == client->sock)
                        break;
        }
@@ -804,7 +799,7 @@ void zsend_ipset_notify_owner(struct zebra_pbr_ipset *ipset,
                zlog_debug("%s: Notifying %u", __PRETTY_FUNCTION__,
                           ipset->unique);
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
                if (ipset->sock == client->sock)
                        break;
        }
@@ -834,7 +829,7 @@ void zsend_ipset_entry_notify_owner(struct zebra_pbr_ipset_entry *ipset,
                zlog_debug("%s: Notifying %u", __PRETTY_FUNCTION__,
                           ipset->unique);
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
                if (ipset->sock == client->sock)
                        break;
        }
@@ -864,7 +859,7 @@ void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable,
                zlog_debug("%s: Notifying %u", __PRETTY_FUNCTION__,
                           iptable->unique);
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
                if (iptable->sock == client->sock)
                        break;
        }
@@ -1316,9 +1311,6 @@ static void zread_interface_add(ZAPI_HANDLER_ARGS)
        struct vrf *vrf;
        struct interface *ifp;
 
-       /* Interface information is needed. */
-       vrf_bitmap_set(client->ifinfo, zvrf_id(zvrf));
-
        RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
                FOR_ALL_INTERFACES (vrf, ifp) {
                        /* Skip pseudo interface. */
@@ -1335,7 +1327,6 @@ static void zread_interface_add(ZAPI_HANDLER_ARGS)
 /* Unregister zebra server interface information. */
 static void zread_interface_delete(ZAPI_HANDLER_ARGS)
 {
-       vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf));
 }
 
 void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
@@ -1674,6 +1665,18 @@ static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf)
        zserv_send_message(client, s);
 }
 
+void zsend_capabilities_all_clients(void)
+{
+       struct listnode *node, *nnode;
+       struct zebra_vrf *zvrf;
+       struct zserv *client;
+
+       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
+               zsend_capabilities(client, zvrf);
+       }
+}
+
 /* Tie up route-type and client->sock */
 static void zread_hello(ZAPI_HANDLER_ARGS)
 {
@@ -1718,7 +1721,6 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
                        vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf));
                vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
        }
-       vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf));
        vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf));
 }
 
@@ -2455,6 +2457,7 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
        [ZEBRA_FEC_REGISTER] = zread_fec_register,
        [ZEBRA_FEC_UNREGISTER] = zread_fec_unregister,
        [ZEBRA_ADVERTISE_DEFAULT_GW] = zebra_vxlan_advertise_gw_macip,
+       [ZEBRA_ADVERTISE_SVI_MACIP] = zebra_vxlan_advertise_svi_macip,
        [ZEBRA_ADVERTISE_SUBNET] = zebra_vxlan_advertise_subnet,
        [ZEBRA_ADVERTISE_ALL_VNI] = zebra_vxlan_advertise_all_vni,
        [ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add,
index 11b469e14478745d1a5da743a661c12f7e281a6b..b770b8e8810c1fab0028c4080ac60deb7c07ead4 100644 (file)
@@ -84,3 +84,5 @@ extern void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable,
                                       enum zapi_iptable_notify_owner note);
 extern void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
                                   const unsigned int nexthop_num);
+
+extern void zsend_capabilities_all_clients(void);
index 6fbad2f71ee72747ababe2ee9660ae18f805b99d..928169a86267914e930b58b0d51cfbf5fa178b17 100644 (file)
@@ -26,7 +26,7 @@
 #include "lib/zebra.h"
 #include "zebra/zebra_router.h"
 #include "zebra/zebra_memory.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/zebra_dplane.h"
 #include "zebra/rt.h"
 #include "zebra/debug.h"
@@ -101,6 +101,23 @@ struct dplane_route_info {
 
 };
 
+/*
+ * Pseudowire info for the dataplane
+ */
+struct dplane_pw_info {
+       char ifname[IF_NAMESIZE];
+       ifindex_t ifindex;
+       int type;
+       int af;
+       int status;
+       uint32_t flags;
+       union g_addr nexthop;
+       mpls_label_t local_label;
+       mpls_label_t remote_label;
+
+       union pw_protocol_fields fields;
+};
+
 /*
  * The context block used to exchange info about route updates across
  * the boundary between the zebra main context (and pthread) and the
@@ -136,6 +153,7 @@ struct zebra_dplane_ctx {
        union {
                struct dplane_route_info rinfo;
                zebra_lsp_t lsp;
+               struct dplane_pw_info pw;
        } u;
 
        /* Namespace info, used especially for netlink kernel communication */
@@ -237,10 +255,11 @@ static struct zebra_dplane_globals {
        _Atomic uint32_t dg_other_errors;
 
        _Atomic uint32_t dg_lsps_in;
-       _Atomic uint32_t dg_lsps_queued;
-       _Atomic uint32_t dg_lsps_queued_max;
        _Atomic uint32_t dg_lsp_errors;
 
+       _Atomic uint32_t dg_pws_in;
+       _Atomic uint32_t dg_pw_errors;
+
        _Atomic uint32_t dg_update_yields;
 
        /* Dataplane pthread */
@@ -276,6 +295,8 @@ static void dplane_info_from_zns(struct zebra_dplane_info *ns_info,
                                 struct zebra_ns *zns);
 static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp,
                                                    enum dplane_op_e op);
+static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
+                                                  enum dplane_op_e op);
 
 /*
  * Public APIs
@@ -363,6 +384,8 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
                break;
        }
 
+       case DPLANE_OP_PW_INSTALL:
+       case DPLANE_OP_PW_UNINSTALL:
        case DPLANE_OP_NONE:
                break;
        }
@@ -490,6 +513,13 @@ const char *dplane_op2str(enum dplane_op_e op)
                ret = "LSP_DELETE";
                break;
 
+       case DPLANE_OP_PW_INSTALL:
+               ret = "PW_INSTALL";
+               break;
+       case DPLANE_OP_PW_UNINSTALL:
+               ret = "PW_UNINSTALL";
+               break;
+
        };
 
        return ret;
@@ -735,6 +765,71 @@ uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx)
        return ctx->u.lsp.num_ecmp;
 }
 
+const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.pw.ifname;
+}
+
+mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.pw.local_label;
+}
+
+mpls_label_t dplane_ctx_get_pw_remote_label(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.pw.remote_label;
+}
+
+int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.pw.type;
+}
+
+int dplane_ctx_get_pw_af(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.pw.af;
+}
+
+uint32_t dplane_ctx_get_pw_flags(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.pw.flags;
+}
+
+int dplane_ctx_get_pw_status(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.pw.status;
+}
+
+const union g_addr *dplane_ctx_get_pw_nexthop(
+       const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return &(ctx->u.pw.nexthop);
+}
+
+const union pw_protocol_fields *dplane_ctx_get_pw_proto(
+       const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return &(ctx->u.pw.fields);
+}
+
 /*
  * End of dplane context accessors
  */
@@ -937,6 +1032,47 @@ static int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx,
        return ret;
 }
 
+/*
+ * Capture information for an LSP update in a dplane context.
+ */
+static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
+                             enum dplane_op_e op,
+                             struct zebra_pw *pw)
+{
+       int ret = AOK;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+               zlog_debug("init dplane ctx %s: pw '%s', loc %u, rem %u",
+                          dplane_op2str(op), pw->ifname, pw->local_label,
+                          pw->remote_label);
+
+       ctx->zd_op = op;
+       ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+
+       /* Capture namespace info: no netlink support as of 12/18,
+        * but just in case...
+        */
+       dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), false);
+
+       memset(&ctx->u.pw, 0, sizeof(ctx->u.pw));
+
+       /* This name appears to be c-string, so we use string copy. */
+       strlcpy(ctx->u.pw.ifname, pw->ifname, sizeof(ctx->u.pw.ifname));
+       ctx->zd_vrf_id = pw->vrf_id;
+       ctx->u.pw.ifindex = pw->ifindex;
+       ctx->u.pw.type = pw->type;
+       ctx->u.pw.af = pw->af;
+       ctx->u.pw.local_label = pw->local_label;
+       ctx->u.pw.remote_label = pw->remote_label;
+       ctx->u.pw.flags = pw->flags;
+
+       ctx->u.pw.nexthop = pw->nexthop;
+
+       ctx->u.pw.fields = pw->data;
+
+       return ret;
+}
+
 /*
  * Enqueue a new route update,
  * and ensure an event is active for the dataplane pthread.
@@ -1140,6 +1276,22 @@ enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp)
        return ret;
 }
 
+/*
+ * Enqueue pseudowire install for the dataplane.
+ */
+enum zebra_dplane_result dplane_pw_install(struct zebra_pw *pw)
+{
+       return pw_update_internal(pw, DPLANE_OP_PW_INSTALL);
+}
+
+/*
+ * Enqueue pseudowire un-install for the dataplane.
+ */
+enum zebra_dplane_result dplane_pw_uninstall(struct zebra_pw *pw)
+{
+       return pw_update_internal(pw, DPLANE_OP_PW_UNINSTALL);
+}
+
 /*
  * Common internal LSP update utility
  */
@@ -1180,6 +1332,45 @@ done:
        return result;
 }
 
+/*
+ * Internal, common handler for pseudowire updates.
+ */
+static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
+                                                  enum dplane_op_e op)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       int ret;
+       struct zebra_dplane_ctx *ctx = NULL;
+
+       ctx = dplane_ctx_alloc();
+       if (ctx == NULL) {
+               ret = ENOMEM;
+               goto done;
+       }
+
+       ret = dplane_ctx_pw_init(ctx, op, pw);
+       if (ret != AOK)
+               goto done;
+
+       ret = dplane_route_enqueue(ctx);
+
+done:
+       /* Update counter */
+       atomic_fetch_add_explicit(&zdplane_info.dg_pws_in, 1,
+                                 memory_order_relaxed);
+
+       if (ret == AOK)
+               result = ZEBRA_DPLANE_REQUEST_QUEUED;
+       else {
+               atomic_fetch_add_explicit(&zdplane_info.dg_pw_errors, 1,
+                                         memory_order_relaxed);
+               if (ctx)
+                       dplane_ctx_free(&ctx);
+       }
+
+       return result;
+}
+
 /*
  * Handler for 'show dplane'
  */
@@ -1511,6 +1702,32 @@ kernel_dplane_lsp_update(struct zebra_dplane_ctx *ctx)
        return res;
 }
 
+/*
+ * Handler for kernel pseudowire updates
+ */
+static enum zebra_dplane_result
+kernel_dplane_pw_update(struct zebra_dplane_ctx *ctx)
+{
+       enum zebra_dplane_result res;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+               zlog_debug("Dplane pw %s: op %s af %d loc: %u rem: %u",
+                          dplane_ctx_get_pw_ifname(ctx),
+                          dplane_op2str(ctx->zd_op),
+                          dplane_ctx_get_pw_af(ctx),
+                          dplane_ctx_get_pw_local_label(ctx),
+                          dplane_ctx_get_pw_remote_label(ctx));
+
+       res = kernel_pw_update(ctx);
+
+       if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+               atomic_fetch_add_explicit(
+                       &zdplane_info.dg_pw_errors, 1,
+                       memory_order_relaxed);
+
+       return res;
+}
+
 /*
  * Handler for kernel route updates
  */
@@ -1577,6 +1794,11 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
                        res = kernel_dplane_lsp_update(ctx);
                        break;
 
+               case DPLANE_OP_PW_INSTALL:
+               case DPLANE_OP_PW_UNINSTALL:
+                       res = kernel_dplane_pw_update(ctx);
+                       break;
+
                default:
                        atomic_fetch_add_explicit(
                                &zdplane_info.dg_other_errors, 1,
@@ -1802,7 +2024,7 @@ static int dplane_check_shutdown_status(struct thread *event)
                /* We appear to be done - schedule a final callback event
                 * for the zebra main pthread.
                 */
-               thread_add_event(zebrad.master, zebra_finalize, NULL, 0, NULL);
+               thread_add_event(zrouter.master, zebra_finalize, NULL, 0, NULL);
        }
 
        return 0;
@@ -2052,7 +2274,7 @@ void zebra_dplane_shutdown(void)
 /*
  * Initialize the dataplane module during startup, internal/private version
  */
-static void zebra_dplane_init_internal(struct zebra_t *zebra)
+static void zebra_dplane_init_internal(void)
 {
        memset(&zdplane_info, 0, sizeof(zdplane_info));
 
@@ -2101,6 +2323,6 @@ void zebra_dplane_start(void)
  */
 void zebra_dplane_init(int (*results_fp)(struct dplane_ctx_q *))
 {
-       zebra_dplane_init_internal(&zebrad);
+       zebra_dplane_init_internal();
        zdplane_info.dg_results_cb = results_fp;
 }
index 562a8499a23c2ecfa0522936697d4cc44062c9c7..81226961e85d97c6e95157576f409b222c6994df 100644 (file)
@@ -105,7 +105,11 @@ enum dplane_op_e {
        /* LSP update */
        DPLANE_OP_LSP_INSTALL,
        DPLANE_OP_LSP_UPDATE,
-       DPLANE_OP_LSP_DELETE
+       DPLANE_OP_LSP_DELETE,
+
+       /* Pseudowire update */
+       DPLANE_OP_PW_INSTALL,
+       DPLANE_OP_PW_UNINSTALL,
 };
 
 /*
@@ -203,6 +207,19 @@ zebra_nhlfe_t *dplane_ctx_get_nhlfe(struct zebra_dplane_ctx *ctx);
 zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx);
 uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx);
 
+/* Accessors for pseudowire information */
+const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx);
+mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx);
+mpls_label_t dplane_ctx_get_pw_remote_label(const struct zebra_dplane_ctx *ctx);
+int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx);
+int dplane_ctx_get_pw_af(const struct zebra_dplane_ctx *ctx);
+uint32_t dplane_ctx_get_pw_flags(const struct zebra_dplane_ctx *ctx);
+int dplane_ctx_get_pw_status(const struct zebra_dplane_ctx *ctx);
+const union g_addr *dplane_ctx_get_pw_nexthop(
+       const struct zebra_dplane_ctx *ctx);
+const union pw_protocol_fields *dplane_ctx_get_pw_proto(
+       const struct zebra_dplane_ctx *ctx);
+
 /* Namespace info - esp. for netlink communication */
 const struct zebra_dplane_info *dplane_ctx_get_ns(
        const struct zebra_dplane_ctx *ctx);
@@ -232,6 +249,12 @@ enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp);
 enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp);
 enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp);
 
+/*
+ * Enqueue pseudowire operations for the dataplane.
+ */
+enum zebra_dplane_result dplane_pw_install(struct zebra_pw *pw);
+enum zebra_dplane_result dplane_pw_uninstall(struct zebra_pw *pw);
+
 /* Retrieve the limit on the number of pending, unprocessed updates. */
 uint32_t dplane_get_in_queue_limit(void);
 
index 35be07c024e60679d6d40db4e89ac4fd1b42f773..5012cc2a49477d95283e195d56cffcbd4061687b 100644 (file)
 #include "hook.h"
 
 #include "zebra/zebra_mlag.h"
+#include "zebra/zebra_router.h"
+#include "zebra/zapi_msg.h"
+#include "zebra/debug.h"
 
 #ifndef VTYSH_EXTRACT_PL
 #include "zebra/zebra_mlag_clippy.c"
 #endif
 
-enum mlag_role role = MLAG_ROLE_NONE;
-
 enum mlag_role zebra_mlag_get_role(void)
 {
-       return role;
+       return zrouter.mlag_info.role;
 }
 
 DEFUN_HIDDEN (show_mlag,
@@ -47,7 +48,7 @@ DEFUN_HIDDEN (show_mlag,
        char buf[80];
 
        vty_out(vty, "MLag is configured to: %s\n",
-               mlag_role2str(role, buf, sizeof(buf)));
+               mlag_role2str(zrouter.mlag_info.role, buf, sizeof(buf)));
 
        return CMD_SUCCESS;
 }
@@ -62,12 +63,23 @@ DEFPY_HIDDEN (test_mlag,
              "Mlag is setup to be primary\n"
              "Mlag is setup to be the secondary\n")
 {
+       enum mlag_role orig = zrouter.mlag_info.role;
+       char buf1[80], buf2[80];
+
        if (none)
-               role = MLAG_ROLE_NONE;
+               zrouter.mlag_info.role = MLAG_ROLE_NONE;
        if (primary)
-               role = MLAG_ROLE_PRIMARY;
+               zrouter.mlag_info.role = MLAG_ROLE_PRIMARY;
        if (secondary)
-               role = MLAG_ROLE_SECONDARY;
+               zrouter.mlag_info.role = MLAG_ROLE_SECONDARY;
+
+       if (IS_ZEBRA_DEBUG_MLAG)
+               zlog_debug("Test: Changing role from %s to %s",
+                          mlag_role2str(orig, buf1, sizeof(buf1)),
+                          mlag_role2str(orig, buf2, sizeof(buf2)));
+
+       if (orig != zrouter.mlag_info.role)
+               zsend_capabilities_all_clients();
 
        return CMD_SUCCESS;
 }
index c255c68866794d509d8e71ca4830aa286a81cc6b..0aac7d7b1253befcbf02ac59270ded3de5a7d1f5 100644 (file)
@@ -40,6 +40,7 @@
 #include "zebra/rt.h"
 #include "zebra/interface.h"
 #include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/redistribute.h"
 #include "zebra/debug.h"
 #include "zebra/zebra_memory.h"
@@ -56,9 +57,6 @@ DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE_IFNAME, "MPLS static nexthop ifname")
 
 int mpls_enabled;
 
-/* Default rtm_table for all clients */
-extern struct zebra_t zebrad;
-
 /* static function declarations */
 
 static void fec_evaluate(struct zebra_vrf *zvrf);
@@ -126,7 +124,6 @@ static zebra_snhlfe_t *snhlfe_add(zebra_slsp_t *slsp,
 static int snhlfe_del(zebra_snhlfe_t *snhlfe);
 static int snhlfe_del_all(zebra_slsp_t *slsp);
 static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size);
-static int mpls_processq_init(struct zebra_t *zebra);
 
 
 /* Static functions */
@@ -1074,13 +1071,13 @@ static int lsp_processq_add(zebra_lsp_t *lsp)
        if (CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED))
                return 0;
 
-       if (zebrad.lsp_process_q == NULL) {
+       if (zrouter.lsp_process_q == NULL) {
                flog_err(EC_ZEBRA_WQ_NONEXISTENT,
                         "%s: work_queue does not exist!", __func__);
                return -1;
        }
 
-       work_queue_add(zebrad.lsp_process_q, lsp);
+       work_queue_add(zrouter.lsp_process_q, lsp);
        SET_FLAG(lsp->flags, LSP_FLAG_SCHEDULED);
        return 0;
 }
@@ -1714,21 +1711,21 @@ static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size)
 /*
  * Initialize work queue for processing changed LSPs.
  */
-static int mpls_processq_init(struct zebra_t *zebra)
+static int mpls_processq_init(void)
 {
-       zebra->lsp_process_q = work_queue_new(zebra->master, "LSP processing");
-       if (!zebra->lsp_process_q) {
+       zrouter.lsp_process_q = work_queue_new(zrouter.master, "LSP processing");
+       if (!zrouter.lsp_process_q) {
                flog_err(EC_ZEBRA_WQ_NONEXISTENT,
                         "%s: could not initialise work queue!", __func__);
                return -1;
        }
 
-       zebra->lsp_process_q->spec.workfunc = &lsp_process;
-       zebra->lsp_process_q->spec.del_item_data = &lsp_processq_del;
-       zebra->lsp_process_q->spec.errorfunc = NULL;
-       zebra->lsp_process_q->spec.completion_func = &lsp_processq_complete;
-       zebra->lsp_process_q->spec.max_retries = 0;
-       zebra->lsp_process_q->spec.hold = 10;
+       zrouter.lsp_process_q->spec.workfunc = &lsp_process;
+       zrouter.lsp_process_q->spec.del_item_data = &lsp_processq_del;
+       zrouter.lsp_process_q->spec.errorfunc = NULL;
+       zrouter.lsp_process_q->spec.completion_func = &lsp_processq_complete;
+       zrouter.lsp_process_q->spec.max_retries = 0;
+       zrouter.lsp_process_q->spec.hold = 10;
 
        return 0;
 }
@@ -3062,7 +3059,7 @@ void zebra_mpls_init(void)
                return;
        }
 
-       if (!mpls_processq_init(&zebrad))
+       if (!mpls_processq_init())
                mpls_enabled = 1;
 
        hook_register(zserv_client_close, zebra_mpls_cleanup_fecs_for_client);
index d8b5ef4ce1b09fba3c749e1822d0ad9df7dfd414..a9233530dc9c16968bffa25f07f6fda3381d4cc4 100644 (file)
@@ -61,6 +61,16 @@ done:
                ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
 }
 
+/*
+ * Pseudowire update api - not supported by netlink as of 12/18,
+ * but note that the default has been to report 'success' for pw updates
+ * on unsupported platforms.
+ */
+enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx)
+{
+       return ZEBRA_DPLANE_REQUEST_SUCCESS;
+}
+
 int mpls_kernel_init(void)
 {
        struct stat st;
index 409432c4fbb9d24b30afc54bd8126242efb001f4..2cc3f3b69dc5ab72b7d195bcc92410dc273dcd96 100644 (file)
@@ -29,6 +29,15 @@ int mpls_kernel_init(void)
        return -1;
 };
 
+/*
+ * Pseudowire update api - note that the default has been
+ * to report 'success' for pw updates on unsupported platforms.
+ */
+enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx)
+{
+       return ZEBRA_DPLANE_REQUEST_SUCCESS;
+}
+
 enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
 {
        return ZEBRA_DPLANE_REQUEST_FAILURE;
index da76c6ebf9249cc3fbfcffdf75aae1b2070e9511..72c8f73522116c41965231cb784fd661c93b4baa 100644 (file)
@@ -314,16 +314,17 @@ enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
                ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
 }
 
-static int kmpw_install(struct zebra_pw *pw)
+static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx)
 {
        struct ifreq ifr;
        struct ifmpwreq imr;
        struct sockaddr_storage ss;
        struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss;
        struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss;
+       const union g_addr *gaddr;
 
        memset(&imr, 0, sizeof(imr));
-       switch (pw->type) {
+       switch (dplane_ctx_get_pw_type(ctx)) {
        case PW_TYPE_ETHERNET:
                imr.imr_type = IMR_TYPE_ETHERNET;
                break;
@@ -332,67 +333,91 @@ static int kmpw_install(struct zebra_pw *pw)
                break;
        default:
                zlog_debug("%s: unhandled pseudowire type (%#X)", __func__,
-                          pw->type);
-               return -1;
+                          dplane_ctx_get_pw_type(ctx));
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
        }
 
-       if (pw->flags & F_PSEUDOWIRE_CWORD)
+       if (dplane_ctx_get_pw_flags(ctx) & F_PSEUDOWIRE_CWORD)
                imr.imr_flags |= IMR_FLAG_CONTROLWORD;
 
        /* pseudowire nexthop */
        memset(&ss, 0, sizeof(ss));
-       switch (pw->af) {
+       gaddr = dplane_ctx_get_pw_nexthop(ctx);
+       switch (dplane_ctx_get_pw_af(ctx)) {
        case AF_INET:
                sa_in->sin_family = AF_INET;
                sa_in->sin_len = sizeof(struct sockaddr_in);
-               sa_in->sin_addr = pw->nexthop.ipv4;
+               sa_in->sin_addr = gaddr->ipv4;
                break;
        case AF_INET6:
                sa_in6->sin6_family = AF_INET6;
                sa_in6->sin6_len = sizeof(struct sockaddr_in6);
-               sa_in6->sin6_addr = pw->nexthop.ipv6;
+               sa_in6->sin6_addr = gaddr->ipv6;
                break;
        default:
                zlog_debug("%s: unhandled pseudowire address-family (%u)",
-                          __func__, pw->af);
-               return -1;
+                          __func__, dplane_ctx_get_pw_af(ctx));
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
        }
        memcpy(&imr.imr_nexthop, (struct sockaddr *)&ss,
               sizeof(imr.imr_nexthop));
 
        /* pseudowire local/remote labels */
-       imr.imr_lshim.shim_label = pw->local_label;
-       imr.imr_rshim.shim_label = pw->remote_label;
+       imr.imr_lshim.shim_label = dplane_ctx_get_pw_local_label(ctx);
+       imr.imr_rshim.shim_label = dplane_ctx_get_pw_remote_label(ctx);
 
        /* ioctl */
        memset(&ifr, 0, sizeof(ifr));
-       strlcpy(ifr.ifr_name, pw->ifname, sizeof(ifr.ifr_name));
+       strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx),
+               sizeof(ifr.ifr_name));
        ifr.ifr_data = (caddr_t)&imr;
        if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
                flog_err_sys(EC_LIB_SYSTEM_CALL, "ioctl SIOCSETMPWCFG: %s",
                             safe_strerror(errno));
-               return -1;
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
        }
 
-       return 0;
+       return ZEBRA_DPLANE_REQUEST_SUCCESS;
 }
 
-static int kmpw_uninstall(struct zebra_pw *pw)
+static enum zebra_dplane_result kmpw_uninstall(struct zebra_dplane_ctx *ctx)
 {
        struct ifreq ifr;
        struct ifmpwreq imr;
 
        memset(&ifr, 0, sizeof(ifr));
        memset(&imr, 0, sizeof(imr));
-       strlcpy(ifr.ifr_name, pw->ifname, sizeof(ifr.ifr_name));
+       strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx),
+               sizeof(ifr.ifr_name));
        ifr.ifr_data = (caddr_t)&imr;
        if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
                flog_err_sys(EC_LIB_SYSTEM_CALL, "ioctl SIOCSETMPWCFG: %s",
                             safe_strerror(errno));
-               return -1;
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
        }
 
-       return 0;
+       return ZEBRA_DPLANE_REQUEST_SUCCESS;
+}
+
+/*
+ * Pseudowire update api for openbsd.
+ */
+enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+
+       switch (dplane_ctx_get_op(ctx)) {
+       case DPLANE_OP_PW_INSTALL:
+               result = kmpw_install(ctx);
+               break;
+       case DPLANE_OP_PW_UNINSTALL:
+               result = kmpw_uninstall(ctx);
+               break;
+       default:
+               break;
+       };
+
+       return result;
 }
 
 #define MAX_RTSOCK_BUF 128 * 1024
@@ -431,10 +456,6 @@ int mpls_kernel_init(void)
 
        kr_state.rtseq = 1;
 
-       /* register hook to install/uninstall pseudowires */
-       hook_register(pw_install, kmpw_install);
-       hook_register(pw_uninstall, kmpw_uninstall);
-
        return 0;
 }
 
index ef31fcf45d3bbc9891cebaaf30cc663be1051cd0..476638591bec231726b9be673e84d302718b8f5a 100644 (file)
@@ -36,7 +36,7 @@
 #include "memory.h"
 #include "lib_errors.h"
 
-#include "zserv.h"
+#include "zebra_router.h"
 #include "zebra_memory.h"
 #endif /* defined(HAVE_NETLINK) */
 
@@ -121,7 +121,7 @@ static int zebra_ns_continue_read(struct zebra_netns_info *zns_info,
                XFREE(MTYPE_NETNS_MISC, zns_info);
                return 0;
        }
-       thread_add_timer_msec(zebrad.master, zebra_ns_ready_read,
+       thread_add_timer_msec(zrouter.master, zebra_ns_ready_read,
                              (void *)zns_info, ZEBRA_NS_POLLING_INTERVAL_MSEC,
                              NULL);
        return 0;
@@ -242,7 +242,7 @@ static int zebra_ns_notify_read(struct thread *t)
        ssize_t len;
 
        zebra_netns_notify_current = thread_add_read(
-               zebrad.master, zebra_ns_notify_read, NULL, fd_monitor, NULL);
+               zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL);
        len = read(fd_monitor, buf, sizeof(buf));
        if (len < 0) {
                flog_err_sys(EC_ZEBRA_NS_NOTIFY_READ,
@@ -284,7 +284,7 @@ static int zebra_ns_notify_read(struct thread *t)
                                    sizeof(struct zebra_netns_info));
                netnsinfo->retries = ZEBRA_NS_POLLING_MAX_RETRIES;
                netnsinfo->netnspath = netnspath;
-               thread_add_timer_msec(zebrad.master, zebra_ns_ready_read,
+               thread_add_timer_msec(zrouter.master, zebra_ns_ready_read,
                                      (void *)netnsinfo, 0, NULL);
        }
        return 0;
@@ -355,7 +355,7 @@ void zebra_ns_notify_init(void)
                             safe_strerror(errno));
        }
        zebra_netns_notify_current = thread_add_read(
-               zebrad.master, zebra_ns_notify_read, NULL, fd_monitor, NULL);
+               zrouter.master, zebra_ns_notify_read, NULL, fd_monitor, NULL);
 }
 
 void zebra_ns_notify_close(void)
index e4a4adba05b19f1e0b97f166d14a4b7104980f8a..1e942d6433f9f8642a9704994ad498f6ed6e30bd 100644 (file)
@@ -41,7 +41,7 @@
 #include "zebra/zebra_errors.h"
 #include "zebra/zebra_ptm.h"
 #include "zebra/zebra_ptm_redistribute.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra_vrf.h"
 
 /*
@@ -187,12 +187,12 @@ static int zebra_ptm_flush_messages(struct thread *thread)
                ptm_cb.ptm_sock = -1;
                zebra_ptm_reset_status(0);
                ptm_cb.t_timer = NULL;
-               thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
+               thread_add_timer(zrouter.master, zebra_ptm_connect, NULL,
                                 ptm_cb.reconnect_time, &ptm_cb.t_timer);
                return (-1);
        case BUFFER_PENDING:
                ptm_cb.t_write = NULL;
-               thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL,
+               thread_add_write(zrouter.master, zebra_ptm_flush_messages, NULL,
                                 ptm_cb.ptm_sock, &ptm_cb.t_write);
                break;
        case BUFFER_EMPTY:
@@ -213,14 +213,14 @@ static int zebra_ptm_send_message(char *data, int size)
                ptm_cb.ptm_sock = -1;
                zebra_ptm_reset_status(0);
                ptm_cb.t_timer = NULL;
-               thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
+               thread_add_timer(zrouter.master, zebra_ptm_connect, NULL,
                                 ptm_cb.reconnect_time, &ptm_cb.t_timer);
                return -1;
        case BUFFER_EMPTY:
                THREAD_OFF(ptm_cb.t_write);
                break;
        case BUFFER_PENDING:
-               thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL,
+               thread_add_write(zrouter.master, zebra_ptm_flush_messages, NULL,
                                 ptm_cb.ptm_sock, &ptm_cb.t_write);
                break;
        }
@@ -240,7 +240,7 @@ int zebra_ptm_connect(struct thread *t)
        if (ptm_cb.ptm_sock != -1) {
                if (init) {
                        ptm_cb.t_read = NULL;
-                       thread_add_read(zebrad.master, zebra_ptm_sock_read,
+                       thread_add_read(zrouter.master, zebra_ptm_sock_read,
                                        NULL, ptm_cb.ptm_sock, &ptm_cb.t_read);
                        zebra_bfd_peer_replay_req();
                }
@@ -252,7 +252,7 @@ int zebra_ptm_connect(struct thread *t)
                        ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_MAX;
 
                ptm_cb.t_timer = NULL;
-               thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
+               thread_add_timer(zrouter.master, zebra_ptm_connect, NULL,
                                 ptm_cb.reconnect_time, &ptm_cb.t_timer);
        } else if (ptm_cb.reconnect_time >= ZEBRA_PTM_RECONNECT_TIME_MAX) {
                ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL;
@@ -657,14 +657,14 @@ int zebra_ptm_sock_read(struct thread *thread)
                ptm_cb.ptm_sock = -1;
                zebra_ptm_reset_status(0);
                ptm_cb.t_timer = NULL;
-               thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
+               thread_add_timer(zrouter.master, zebra_ptm_connect, NULL,
                                 ptm_cb.reconnect_time,
                                 &ptm_cb.t_timer);
                return (-1);
        }
 
        ptm_cb.t_read = NULL;
-       thread_add_read(zebrad.master, zebra_ptm_sock_read, NULL,
+       thread_add_read(zrouter.master, zebra_ptm_sock_read, NULL,
                        ptm_cb.ptm_sock, &ptm_cb.t_read);
 
        return 0;
@@ -700,7 +700,7 @@ void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS)
 
        if (ptm_cb.ptm_sock == -1) {
                ptm_cb.t_timer = NULL;
-               thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
+               thread_add_timer(zrouter.master, zebra_ptm_connect, NULL,
                                 ptm_cb.reconnect_time, &ptm_cb.t_timer);
                return;
        }
@@ -854,7 +854,7 @@ void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS)
 
        if (ptm_cb.ptm_sock == -1) {
                ptm_cb.t_timer = NULL;
-               thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
+               thread_add_timer(zrouter.master, zebra_ptm_connect, NULL,
                                 ptm_cb.reconnect_time, &ptm_cb.t_timer);
                return;
        }
@@ -981,7 +981,7 @@ void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS)
 
        if (ptm_cb.ptm_sock == -1) {
                ptm_cb.t_timer = NULL;
-               thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
+               thread_add_timer(zrouter.master, zebra_ptm_connect, NULL,
                                 ptm_cb.reconnect_time, &ptm_cb.t_timer);
                return;
        }
@@ -1039,7 +1039,7 @@ int zebra_ptm_bfd_client_deregister(struct zserv *client)
 
        if (ptm_cb.ptm_sock == -1) {
                ptm_cb.t_timer = NULL;
-               thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
+               thread_add_timer(zrouter.master, zebra_ptm_connect, NULL,
                                 ptm_cb.reconnect_time, &ptm_cb.t_timer);
                return 0;
        }
@@ -1276,7 +1276,7 @@ static void zebra_ptm_send_bfdd(struct stream *msg)
        }
 
        /* Send message to all running BFDd daemons. */
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
                if (client->proto != ZEBRA_ROUTE_BFD)
                        continue;
 
@@ -1308,7 +1308,7 @@ static void zebra_ptm_send_clients(struct stream *msg)
        }
 
        /* Send message to all running client daemons. */
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
                if (!IS_BFD_ENABLED_PROTOCOL(client->proto))
                        continue;
 
index 3acbe3bf2c85182fc1dc4aafe76530d693d07f73..01d5114b9fbf7b21d4fb75d08dffbaed25a59724 100644 (file)
@@ -22,7 +22,7 @@
 #include "prefix.h"
 #include "vty.h"
 #include "stream.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/zapi_msg.h"
 #include "zebra/zebra_ptm.h"
 #include "zebra/zebra_ptm_redistribute.h"
@@ -36,10 +36,6 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client,
        int blen;
        struct stream *s;
 
-       /* Check this client need interface information. */
-       if (!vrf_bitmap_check(client->ifinfo, ifp->vrf_id))
-               return 0;
-
        s = stream_new(ZEBRA_MAX_PACKET_SIZ);
 
        zclient_create_header(s, cmd, vrf_id);
@@ -76,7 +72,7 @@ void zebra_interface_bfd_update(struct interface *ifp, struct prefix *dp,
        struct listnode *node, *nnode;
        struct zserv *client;
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                if (!IS_BFD_ENABLED_PROTOCOL(client->proto))
                        continue;
 
@@ -106,7 +102,7 @@ void zebra_bfd_peer_replay_req(void)
        struct listnode *node, *nnode;
        struct zserv *client;
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                if (!IS_BFD_ENABLED_PROTOCOL(client->proto))
                        continue;
 
index fb9a40fe3d857e8d4325031c6eecff2d1be223ec..006c1da02bd1b5732e070c3c44b3e82062136e20 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "zebra/debug.h"
 #include "zebra/rib.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/zapi_msg.h"
 #include "zebra/zebra_rnh.h"
 #include "zebra/zebra_vrf.h"
@@ -42,8 +42,6 @@ DEFINE_HOOK(pw_uninstall, (struct zebra_pw * pw), (pw))
 
 #define MPLS_NO_LABEL MPLS_INVALID_LABEL
 
-extern struct zebra_t zebrad;
-
 static int zebra_pw_enabled(struct zebra_pw *);
 static void zebra_pw_install(struct zebra_pw *);
 static void zebra_pw_uninstall(struct zebra_pw *);
@@ -98,9 +96,10 @@ void zebra_pw_del(struct zebra_vrf *zvrf, struct zebra_pw *pw)
        zebra_deregister_rnh_pseudowire(pw->vrf_id, pw);
 
        /* uninstall */
-       if (pw->status == PW_STATUS_UP)
+       if (pw->status == PW_STATUS_UP) {
                hook_call(pw_uninstall, pw);
-       else if (pw->install_retry_timer)
+               dplane_pw_uninstall(pw);
+       } else if (pw->install_retry_timer)
                THREAD_TIMER_OFF(pw->install_retry_timer);
 
        /* unlink and release memory */
@@ -171,7 +170,8 @@ static void zebra_pw_install(struct zebra_pw *pw)
                           pw->vrf_id, pw->ifname,
                           zebra_route_string(pw->protocol));
 
-       if (hook_call(pw_install, pw)) {
+       hook_call(pw_install, pw);
+       if (dplane_pw_install(pw) == ZEBRA_DPLANE_REQUEST_FAILURE) {
                zebra_pw_install_failure(pw);
                return;
        }
@@ -192,6 +192,7 @@ static void zebra_pw_uninstall(struct zebra_pw *pw)
 
        /* ignore any possible error */
        hook_call(pw_uninstall, pw);
+       dplane_pw_uninstall(pw);
 
        if (zebra_pw_enabled(pw))
                zebra_pw_update_status(pw, PW_STATUS_DOWN);
@@ -213,7 +214,7 @@ void zebra_pw_install_failure(struct zebra_pw *pw)
 
        /* schedule to retry later */
        THREAD_TIMER_OFF(pw->install_retry_timer);
-       thread_add_timer(zebrad.master, zebra_pw_install_retry, pw,
+       thread_add_timer(zrouter.master, zebra_pw_install_retry, pw,
                         PW_INSTALL_RETRY_INTERVAL, &pw->install_retry_timer);
 
        zebra_pw_update_status(pw, PW_STATUS_DOWN);
index e6e0a22c214ae7b1bb512d3525af6f1d7d893113..9692fb4d40dd8fb6ff746dfe59bebabee17ee634 100644 (file)
@@ -62,8 +62,8 @@ RB_PROTOTYPE(zebra_static_pw_head, zebra_pw, static_pw_entry, zebra_pw_compare);
 DECLARE_HOOK(pw_install, (struct zebra_pw * pw), (pw))
 DECLARE_HOOK(pw_uninstall, (struct zebra_pw * pw), (pw))
 
-struct zebra_pw *zebra_pw_add(struct zebra_vrf *, const char *, uint8_t,
-                             struct zserv *);
+struct zebra_pw *zebra_pw_add(struct zebra_vrf *zvrf, const char *ifname,
+                             uint8_t protocol, struct zserv *client);
 void zebra_pw_del(struct zebra_vrf *, struct zebra_pw *);
 void zebra_pw_change(struct zebra_pw *, ifindex_t, int, int, union g_addr *,
                     uint32_t, uint32_t, uint8_t, union pw_protocol_fields *);
index 3a8ec0249ac30215c7853086c496936c9dd7d62c..dcc5a7acb00ee0d70c82a0097ca107bba8550a4b 100644 (file)
@@ -163,7 +163,7 @@ int is_zebra_valid_kernel_table(uint32_t table_id)
 int is_zebra_main_routing_table(uint32_t table_id)
 {
        if ((table_id == RT_TABLE_MAIN)
-           || (table_id == zebrad.rtm_table_default))
+           || (table_id == zrouter.rtm_table_default))
                return 1;
        return 0;
 }
@@ -608,6 +608,9 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
                                if (!CHECK_FLAG(match->status,
                                                ROUTE_ENTRY_INSTALLED))
                                        continue;
+                               if (CHECK_FLAG(newhop->flags,
+                                              NEXTHOP_FLAG_RECURSIVE))
+                                       continue;
 
                                if (set) {
                                        SET_FLAG(nexthop->flags,
@@ -2152,14 +2155,6 @@ static void do_nht_processing(void)
        }
 }
 
-/*
- * All meta queues have been processed. Trigger next-hop evaluation.
- */
-static void meta_queue_process_complete(struct work_queue *dummy)
-{
-       do_nht_processing();
-}
-
 /* Dispatch the meta queue by picking, processing and unlocking the next RN from
  * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and
  * data
@@ -2180,8 +2175,8 @@ static wq_item_status meta_queue_process(struct work_queue *dummy, void *data)
                                   queue_len, queue_limit);
 
                /* Ensure that the meta-queue is actually enqueued */
-               if (work_queue_empty(zebrad.ribq))
-                       work_queue_add(zebrad.ribq, zebrad.mq);
+               if (work_queue_empty(zrouter.ribq))
+                       work_queue_add(zrouter.ribq, zrouter.mq);
 
                return WQ_QUEUE_BLOCKED;
        }
@@ -2270,7 +2265,7 @@ void rib_queue_add(struct route_node *rn)
                return;
        }
 
-       if (zebrad.ribq == NULL) {
+       if (zrouter.ribq == NULL) {
                flog_err(EC_ZEBRA_WQ_NONEXISTENT,
                         "%s: work_queue does not exist!", __func__);
                return;
@@ -2284,10 +2279,10 @@ void rib_queue_add(struct route_node *rn)
         * holder, if necessary, then push the work into it in any case.
         * This semantics was introduced after 0.99.9 release.
         */
-       if (work_queue_empty(zebrad.ribq))
-               work_queue_add(zebrad.ribq, zebrad.mq);
+       if (work_queue_empty(zrouter.ribq))
+               work_queue_add(zrouter.ribq, zrouter.mq);
 
-       rib_meta_queue_add(zebrad.mq, rn);
+       rib_meta_queue_add(zrouter.mq, rn);
 
        return;
 }
@@ -2321,27 +2316,25 @@ void meta_queue_free(struct meta_queue *mq)
 }
 
 /* initialise zebra rib work queue */
-static void rib_queue_init(struct zebra_t *zebra)
+static void rib_queue_init(void)
 {
-       assert(zebra);
-
-       if (!(zebra->ribq =
-                     work_queue_new(zebra->master, "route_node processing"))) {
+       if (!(zrouter.ribq = work_queue_new(zrouter.master,
+                                           "route_node processing"))) {
                flog_err(EC_ZEBRA_WQ_NONEXISTENT,
                         "%s: could not initialise work queue!", __func__);
                return;
        }
 
        /* fill in the work queue spec */
-       zebra->ribq->spec.workfunc = &meta_queue_process;
-       zebra->ribq->spec.errorfunc = NULL;
-       zebra->ribq->spec.completion_func = &meta_queue_process_complete;
+       zrouter.ribq->spec.workfunc = &meta_queue_process;
+       zrouter.ribq->spec.errorfunc = NULL;
+       zrouter.ribq->spec.completion_func = NULL;
        /* XXX: TODO: These should be runtime configurable via vty */
-       zebra->ribq->spec.max_retries = 3;
-       zebra->ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
-       zebra->ribq->spec.retry = ZEBRA_RIB_PROCESS_RETRY_TIME;
+       zrouter.ribq->spec.max_retries = 3;
+       zrouter.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
+       zrouter.ribq->spec.retry = ZEBRA_RIB_PROCESS_RETRY_TIME;
 
-       if (!(zebra->mq = meta_queue_new())) {
+       if (!(zrouter.mq = meta_queue_new())) {
                flog_err(EC_ZEBRA_WQ_NONEXISTENT,
                         "%s: could not initialise meta queue!", __func__);
                return;
@@ -3235,6 +3228,34 @@ void rib_close_table(struct route_table *table)
        }
 }
 
+/*
+ * Handler for async dataplane results after a pseudowire installation
+ */
+static int handle_pw_result(struct zebra_dplane_ctx *ctx)
+{
+       int ret = 0;
+       struct zebra_pw *pw;
+       struct zebra_vrf *vrf;
+
+       /* The pseudowire code assumes success - we act on an error
+        * result for installation attempts here.
+        */
+       if (dplane_ctx_get_op(ctx) != DPLANE_OP_PW_INSTALL)
+               goto done;
+
+       if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) {
+               vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
+               pw = zebra_pw_find(vrf, dplane_ctx_get_pw_ifname(ctx));
+               if (pw)
+                       zebra_pw_install_failure(pw);
+       }
+
+done:
+
+       return ret;
+}
+
+
 /*
  * Handle results from the dataplane system. Dequeue update context
  * structs, dispatch to appropriate internal handlers.
@@ -3246,8 +3267,6 @@ static int rib_process_dplane_results(struct thread *thread)
 
        /* Dequeue a list of completed updates with one lock/unlock cycle */
 
-       /* TODO -- dequeue a list with one lock/unlock cycle? */
-
        do {
                TAILQ_INIT(&ctxlist);
 
@@ -3280,6 +3299,11 @@ static int rib_process_dplane_results(struct thread *thread)
                                zebra_mpls_lsp_dplane_result(ctx);
                                break;
 
+                       case DPLANE_OP_PW_INSTALL:
+                       case DPLANE_OP_PW_UNINSTALL:
+                               handle_pw_result(ctx);
+                               break;
+
                        default:
                                /* Don't expect this: just return the struct? */
                                dplane_ctx_fini(&ctx);
@@ -3313,7 +3337,7 @@ static int rib_dplane_results(struct dplane_ctx_q *ctxlist)
        pthread_mutex_unlock(&dplane_mutex);
 
        /* Ensure event is signalled to zebra main pthread */
-       thread_add_event(zebrad.master, rib_process_dplane_results, NULL, 0,
+       thread_add_event(zrouter.master, rib_process_dplane_results, NULL, 0,
                         &t_dplane);
 
        return 0;
@@ -3322,7 +3346,7 @@ static int rib_dplane_results(struct dplane_ctx_q *ctxlist)
 /* Routing information base initialize. */
 void rib_init(void)
 {
-       rib_queue_init(&zebrad);
+       rib_queue_init();
 
        /* Init dataplane, and register for results */
        pthread_mutex_init(&dplane_mutex, NULL);
index 6d52e5f9e6a08b04280ab9012954d32e768a1798..7d72583dd8b3420c769fb9cbc6de185a495fda56 100644 (file)
@@ -33,7 +33,7 @@
 #include "vrf.h"
 #include "frrstr.h"
 
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/redistribute.h"
 #include "zebra/debug.h"
 #include "zebra/zebra_rnh.h"
@@ -327,10 +327,11 @@ static int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap,
 
                XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype));
        }
-
+       route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype));
        PROTO_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
        PROTO_RM_MAP(zvrf, afi, rtype) =
                route_map_lookup_by_name(PROTO_RM_NAME(zvrf, afi, rtype));
+       route_map_counter_increment(PROTO_RM_MAP(zvrf, afi, rtype));
 
        if (PROTO_RM_MAP(zvrf, afi, rtype)) {
 
@@ -356,6 +357,8 @@ static int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap,
                return CMD_SUCCESS;
 
        if (!rmap || strcmp(rmap, PROTO_RM_NAME(zvrf, afi, rtype)) == 0) {
+
+               route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype));
                if (PROTO_RM_MAP(zvrf, afi, rtype)) {
                        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                                zlog_debug(
@@ -383,10 +386,11 @@ static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
 
                XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
        }
-
+       route_map_counter_decrement(NHT_RM_MAP(zvrf, afi, rtype));
        NHT_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
        NHT_RM_MAP(zvrf, afi, rtype) =
                route_map_lookup_by_name(NHT_RM_NAME(zvrf, afi, rtype));
+       route_map_counter_increment(NHT_RM_MAP(zvrf, afi, rtype));
 
        if (NHT_RM_MAP(zvrf, afi, rtype))
                zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL);
@@ -402,6 +406,7 @@ static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
                return CMD_SUCCESS;
 
        if (!rmap || strcmp(rmap, NHT_RM_NAME(zvrf, afi, rtype)) == 0) {
+               route_map_counter_decrement(NHT_RM_MAP(zvrf, afi, rtype));
                if (NHT_RM_MAP(zvrf, afi, rtype)) {
                        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                                zlog_debug(
@@ -1459,6 +1464,7 @@ static void zebra_rib_table_rm_update(const char *rmap)
        char *rmap_name;
        char afi_ip = 0;
        char afi_ipv6 = 0;
+       struct route_map *old = NULL;
 
        RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
                zvrf = vrf->info;
@@ -1473,8 +1479,19 @@ static void zebra_rib_table_rm_update(const char *rmap)
                                                __func__, rmap,
                                                zebra_route_string(i));
 
+                               old = PROTO_RM_MAP(zvrf, AFI_IP, i);
+
                                PROTO_RM_MAP(zvrf, AFI_IP, i) =
                                        route_map_lookup_by_name(rmap_name);
+                               /* old is NULL. i.e Route map creation event.
+                                * So update applied_counter.
+                                * If Old is not NULL, i.e It may be routemap
+                                * updation or deletion.
+                                * So no need to update the counter.
+                                */
+                               if (!old)
+                                       route_map_counter_increment(
+                                               PROTO_RM_MAP(zvrf, AFI_IP, i));
                                /* There is single rib table for all protocols
                                 */
                                if (afi_ip == 0) {
@@ -1497,8 +1514,13 @@ static void zebra_rib_table_rm_update(const char *rmap)
                                                __func__, rmap,
                                                zebra_route_string(i));
 
+                               old = PROTO_RM_MAP(zvrf, AFI_IP6, i);
+
                                PROTO_RM_MAP(zvrf, AFI_IP6, i) =
                                        route_map_lookup_by_name(rmap_name);
+                               if (!old)
+                                       route_map_counter_increment(
+                                               PROTO_RM_MAP(zvrf, AFI_IP6, i));
                                /* There is single rib table for all protocols
                                 */
                                if (afi_ipv6 == 0) {
@@ -1530,6 +1552,7 @@ static void zebra_nht_rm_update(const char *rmap)
        char *rmap_name;
        char afi_ip = 0;
        char afi_ipv6 = 0;
+       struct route_map *old = NULL;
 
        RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
                zvrf = vrf->info;
@@ -1544,8 +1567,13 @@ static void zebra_nht_rm_update(const char *rmap)
                                                __func__, rmap,
                                                zebra_route_string(i));
 
+                               old = NHT_RM_MAP(zvrf, AFI_IP, i);
+
                                NHT_RM_MAP(zvrf, AFI_IP, i) =
                                        route_map_lookup_by_name(rmap_name);
+                               if (!old)
+                                       route_map_counter_increment(
+                                               NHT_RM_MAP(zvrf, AFI_IP, i));
                                /* There is single rib table for all protocols
                                 */
                                if (afi_ip == 0) {
@@ -1570,8 +1598,13 @@ static void zebra_nht_rm_update(const char *rmap)
                                                __func__, rmap,
                                                zebra_route_string(i));
 
+                               old = NHT_RM_MAP(zvrf, AFI_IP6, i);
+
                                NHT_RM_MAP(zvrf, AFI_IP6, i) =
                                        route_map_lookup_by_name(rmap_name);
+                               if (!old)
+                                       route_map_counter_increment(
+                                               NHT_RM_MAP(zvrf, AFI_IP6, i));
                                /* There is single rib table for all protocols
                                 */
                                if (afi_ipv6 == 0) {
@@ -1745,7 +1778,7 @@ static void zebra_route_map_mark_update(const char *rmap_name)
        /* rmap_update_timer of 0 means don't do route updates */
        if (zebra_rmap_update_timer && !zebra_t_rmap_update) {
                zebra_t_rmap_update = NULL;
-               thread_add_timer(zebrad.master, zebra_route_map_update_timer,
+               thread_add_timer(zrouter.master, zebra_route_map_update_timer,
                                 NULL, zebra_rmap_update_timer,
                                 &zebra_t_rmap_update);
        }
index 3e94d6bca892dfc6ec7a401a37c3c488eae8e422..c3b861c2424b0f16a93c9f90f15bb12bb31ce4ae 100644 (file)
@@ -188,6 +188,9 @@ void zebra_router_terminate(void)
                zebra_router_free_table(zrt);
        }
 
+       work_queue_free_and_null(&zrouter.ribq);
+       meta_queue_free(zrouter.mq);
+
        zebra_vxlan_disable();
        zebra_mlag_terminate();
 
@@ -206,6 +209,9 @@ void zebra_router_init(void)
 {
        zrouter.sequence_num = 0;
 
+       zrouter.rtm_table_default = 0;
+       zrouter.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS;
+
        zebra_vxlan_init();
        zebra_mlag_init();
 
index f63dcd984ebcadba91cf7e2bf91e9c1d0a5cbd56..fb28495917ab9990cebc06be458598cb0c3a7cfb 100644 (file)
@@ -22,6 +22,8 @@
 #ifndef __ZEBRA_ROUTER_H__
 #define __ZEBRA_ROUTER_H__
 
+#include "lib/mlag.h"
+
 #include "zebra/zebra_ns.h"
 
 /*
@@ -44,7 +46,24 @@ RB_HEAD(zebra_router_table_head, zebra_router_table);
 RB_PROTOTYPE(zebra_router_table_head, zebra_router_table,
             zebra_router_table_entry, zebra_router_table_entry_compare)
 
+struct zebra_mlag_info {
+       /* Role this zebra router is playing */
+       enum mlag_role role;
+
+       /* The peerlink being used for mlag */
+       char *peerlink;
+       ifindex_t peerlink_ifindex;
+
+       /* The system mac being used */
+       struct ethaddr mac;
+};
+
 struct zebra_router {
+       /* Thread master */
+       struct thread_master *master;
+
+       /* Lists of clients who have connected to us */
+       struct list *client_list;
 
        struct zebra_router_table_head tables;
 
@@ -65,6 +84,26 @@ struct zebra_router {
 
        /* A sequence number used for tracking routes */
        _Atomic uint32_t sequence_num;
+
+       /* The default table used for this router */
+       uint32_t rtm_table_default;
+
+       /* rib work queue */
+#define ZEBRA_RIB_PROCESS_HOLD_TIME 10
+#define ZEBRA_RIB_PROCESS_RETRY_TIME 1
+       struct work_queue *ribq;
+
+       /* Meta Queue Information */
+       struct meta_queue *mq;
+
+       /* LSP work queue */
+       struct work_queue *lsp_process_q;
+
+#define ZEBRA_ZAPI_PACKETS_TO_PROCESS 1000
+       _Atomic uint32_t packets_to_process;
+
+       /* Mlag information for the router */
+       struct zebra_mlag_info mlag_info;
 };
 
 extern struct zebra_router zrouter;
index f1458cb138b1eabc92161befbe79fe02b57e453a..d18305495bc33bc1b59ce27aa7b102b8cf6e64cc 100644 (file)
@@ -42,8 +42,6 @@
 #include "zebra/zebra_netns_notify.h"
 #include "zebra/zebra_routemap.h"
 
-extern struct zebra_t zebrad;
-
 static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
                                   safi_t safi);
 static void zebra_rnhtable_node_cleanup(struct route_table *table,
@@ -58,7 +56,7 @@ static void zebra_vrf_add_update(struct zebra_vrf *zvrf)
        if (IS_ZEBRA_DEBUG_EVENT)
                zlog_debug("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name(zvrf));
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
                zsend_vrf_add(client, zvrf);
 }
 
@@ -70,7 +68,7 @@ static void zebra_vrf_delete_update(struct zebra_vrf *zvrf)
        if (IS_ZEBRA_DEBUG_EVENT)
                zlog_debug("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name(zvrf));
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client))
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client))
                zsend_vrf_delete(client, zvrf);
 }
 
@@ -189,13 +187,13 @@ static int zebra_vrf_disable(struct vrf *vrf)
                struct route_node *rnode;
                rib_dest_t *dest;
 
-               for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode,
+               for (ALL_LIST_ELEMENTS(zrouter.mq->subq[i], lnode, nnode,
                                       rnode)) {
                        dest = rib_dest_from_rnode(rnode);
                        if (dest && rib_dest_vrf(dest) == zvrf) {
                                route_unlock_node(rnode);
-                               list_delete_node(zebrad.mq->subq[i], lnode);
-                               zebrad.mq->size--;
+                               list_delete_node(zrouter.mq->subq[i], lnode);
+                               zrouter.mq->size--;
                        }
                }
        }
@@ -241,13 +239,13 @@ static int zebra_vrf_delete(struct vrf *vrf)
                struct route_node *rnode;
                rib_dest_t *dest;
 
-               for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode,
+               for (ALL_LIST_ELEMENTS(zrouter.mq->subq[i], lnode, nnode,
                                       rnode)) {
                        dest = rib_dest_from_rnode(rnode);
                        if (dest && rib_dest_vrf(dest) == zvrf) {
                                route_unlock_node(rnode);
-                               list_delete_node(zebrad.mq->subq[i], lnode);
-                               zebrad.mq->size--;
+                               list_delete_node(zrouter.mq->subq[i], lnode);
+                               zrouter.mq->size--;
                        }
                }
        }
@@ -326,14 +324,14 @@ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi,
 
        if (vrf_id == VRF_DEFAULT) {
                if (table_id == RT_TABLE_MAIN
-                   || table_id == zebrad.rtm_table_default)
+                   || table_id == zrouter.rtm_table_default)
                        table = zebra_vrf_table(afi, safi, vrf_id);
                else
                        table = zebra_vrf_other_route_table(afi, table_id,
                                                            vrf_id);
        } else if (vrf_is_backend_netns()) {
                if (table_id == RT_TABLE_MAIN
-                   || table_id == zebrad.rtm_table_default)
+                   || table_id == zrouter.rtm_table_default)
                        table = zebra_vrf_table(afi, safi, vrf_id);
                else
                        table = zebra_vrf_other_route_table(afi, table_id,
@@ -439,9 +437,9 @@ struct route_table *zebra_vrf_other_route_table(afi_t afi, uint32_t table_id,
                return NULL;
 
        if ((table_id != RT_TABLE_MAIN)
-           && (table_id != zebrad.rtm_table_default)) {
+           && (table_id != zrouter.rtm_table_default)) {
                if (zvrf->table_id == RT_TABLE_MAIN ||
-                   zvrf->table_id == zebrad.rtm_table_default) {
+                   zvrf->table_id == zrouter.rtm_table_default) {
                        /* this VRF use default table
                         * so in all cases, it does not use specific table
                         * so it is possible to configure tables in this VRF
index 2473299d1763e06db5b90c54185533ba85b38530..e35101d83313d6ba6a92c2df525cb505fd812bfc 100644 (file)
@@ -122,6 +122,8 @@ struct zebra_vrf {
         */
        int advertise_gw_macip;
 
+       int advertise_svi_macip;
+
        /* l3-vni info */
        vni_t l3vni;
 
index 14288d7bc4b3714880863e17c9f8db7800bd206c..537820f7ea71dd8ec2f3633438d682c240242b06 100644 (file)
@@ -164,7 +164,8 @@ DEFUN (show_ip_rpf_addr,
 static char re_status_output_char(struct route_entry *re, struct nexthop *nhop)
 {
        if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
-               if (!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE))
+               if (!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE) &&
+                   !CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE))
                        return '*';
                else
                        return ' ';
@@ -174,7 +175,7 @@ static char re_status_output_char(struct route_entry *re, struct nexthop *nhop)
                if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
                        return 'q';
 
-               return 'f';
+               return 'r';
        }
 
        if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
@@ -2456,7 +2457,7 @@ DEFUN_HIDDEN (zebra_packet_process,
 {
        uint32_t packets = strtoul(argv[2]->arg, NULL, 10);
 
-       atomic_store_explicit(&zebrad.packets_to_process, packets,
+       atomic_store_explicit(&zrouter.packets_to_process, packets,
                              memory_order_relaxed);
 
        return CMD_SUCCESS;
@@ -2470,7 +2471,7 @@ DEFUN_HIDDEN (no_zebra_packet_process,
              "Zapi Protocol\n"
              "Number of packets to process before relinquishing thread\n")
 {
-       atomic_store_explicit(&zebrad.packets_to_process,
+       atomic_store_explicit(&zrouter.packets_to_process,
                              ZEBRA_ZAPI_PACKETS_TO_PROCESS,
                              memory_order_relaxed);
 
@@ -2485,7 +2486,7 @@ DEFUN_HIDDEN (zebra_workqueue_timer,
              "Time in milliseconds\n")
 {
        uint32_t timer = strtoul(argv[2]->arg, NULL, 10);
-       zebrad.ribq->spec.hold = timer;
+       zrouter.ribq->spec.hold = timer;
 
        return CMD_SUCCESS;
 }
@@ -2498,7 +2499,7 @@ DEFUN_HIDDEN (no_zebra_workqueue_timer,
              "Work Queue\n"
              "Time in milliseconds\n")
 {
-       zebrad.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
+       zrouter.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
 
        return CMD_SUCCESS;
 }
@@ -2548,12 +2549,12 @@ static int config_write_protocol(struct vty *vty)
        if (zebra_rnh_ipv6_default_route)
                vty_out(vty, "ipv6 nht resolve-via-default\n");
 
-       if (zebrad.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
-               vty_out(vty, "zebra work-queue %u\n", zebrad.ribq->spec.hold);
+       if (zrouter.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
+               vty_out(vty, "zebra work-queue %u\n", zrouter.ribq->spec.hold);
 
-       if (zebrad.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
+       if (zrouter.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
                vty_out(vty, "zebra zapi-packets %u\n",
-                       zebrad.packets_to_process);
+                       zrouter.packets_to_process);
 
        enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
 
@@ -2581,7 +2582,7 @@ DEFUN (show_table,
        SHOW_STR
        "default routing table to use for all clients\n")
 {
-       vty_out(vty, "table %d\n", zebrad.rtm_table_default);
+       vty_out(vty, "table %d\n", zrouter.rtm_table_default);
        return CMD_SUCCESS;
 }
 
@@ -2591,7 +2592,7 @@ DEFUN (config_table,
        "Configure target kernel routing table\n"
        "TABLE integer\n")
 {
-       zebrad.rtm_table_default = strtol(argv[1]->arg, (char **)0, 10);
+       zrouter.rtm_table_default = strtol(argv[1]->arg, (char **)0, 10);
        return CMD_SUCCESS;
 }
 
@@ -2602,7 +2603,7 @@ DEFUN (no_config_table,
        "Configure target kernel routing table\n"
        "TABLE integer\n")
 {
-       zebrad.rtm_table_default = 0;
+       zrouter.rtm_table_default = 0;
        return CMD_SUCCESS;
 }
 #endif
@@ -2850,8 +2851,8 @@ DEFUN (zebra_show_routing_tables_summary,
 /* Table configuration write function. */
 static int config_write_table(struct vty *vty)
 {
-       if (zebrad.rtm_table_default)
-               vty_out(vty, "table %d\n", zebrad.rtm_table_default);
+       if (zrouter.rtm_table_default)
+               vty_out(vty, "table %d\n", zrouter.rtm_table_default);
        return 0;
 }
 
index 49af4a9205c7971c2ac1b61b52028d7e3f4caca7..560cd89abd781dde7fbaa1d3890d6855c232df92 100644 (file)
@@ -50,7 +50,7 @@
 #include "zebra/zebra_vrf.h"
 #include "zebra/zebra_vxlan.h"
 #include "zebra/zebra_vxlan_private.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 
 DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
 DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash");
@@ -100,6 +100,7 @@ static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
                                         uint8_t flags, int state);
 static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
 static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
+static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n);
 static zebra_vni_t *zvni_from_svi(struct interface *ifp,
                                  struct interface *br_if);
 static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if);
@@ -179,6 +180,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
                             struct ipaddr *ip);
 struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp);
 static int advertise_gw_macip_enabled(zebra_vni_t *zvni);
+static int advertise_svi_macip_enabled(zebra_vni_t *zvni);
 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
                                               zebra_mac_t *old_zmac,
                                               zebra_mac_t *new_zmac,
@@ -332,6 +334,20 @@ static int advertise_gw_macip_enabled(zebra_vni_t *zvni)
        return 0;
 }
 
+static int advertise_svi_macip_enabled(zebra_vni_t *zvni)
+{
+       struct zebra_vrf *zvrf;
+
+       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       if (zvrf && zvrf->advertise_svi_macip)
+               return 1;
+
+       if (zvni && zvni->advertise_svi_macip)
+               return 1;
+
+       return 0;
+}
+
 /* As part Duplicate Address Detection (DAD) for IP mobility
  * MAC binding changes, ensure to inherit duplicate flag
  * from MAC.
@@ -510,7 +526,7 @@ static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
                                                       sizeof(buf)),
                                        mac->flags, zvrf->dad_freeze_time);
 
-                       thread_add_timer(zebrad.master,
+                       thread_add_timer(zrouter.master,
                                         zebra_vxlan_dad_mac_auto_recovery_exp,
                                         mac, zvrf->dad_freeze_time,
                                         &mac->dad_mac_auto_recovery_timer);
@@ -643,7 +659,7 @@ static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf,
                                   ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
                                   nbr->flags, zvrf->dad_freeze_time);
 
-                       thread_add_timer(zebrad.master,
+                       thread_add_timer(zrouter.master,
                                zebra_vxlan_dad_ip_auto_recovery_exp,
                                nbr, zvrf->dad_freeze_time,
                                &nbr->dad_ip_auto_recovery_timer);
@@ -2404,6 +2420,18 @@ static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t *zvni,
        /* NOTE: Currently a NO-OP. */
 }
 
+static void zvni_probe_neigh_on_mac_add(zebra_vni_t *zvni, zebra_mac_t *zmac)
+{
+       zebra_neigh_t *nbr = NULL;
+       struct listnode *node = NULL;
+
+       for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, nbr)) {
+               if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL) &&
+                   IS_ZEBRA_NEIGH_INACTIVE(nbr))
+                       zvni_neigh_probe(zvni, nbr);
+       }
+}
+
 /*
  * Inform BGP about local neighbor addition.
  */
@@ -2500,6 +2528,32 @@ static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n)
        return kernel_del_neigh(vlan_if, &n->ip);
 }
 
+/*
+ * Probe neighbor from the kernel.
+ */
+static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n)
+{
+       struct zebra_if *zif;
+       struct zebra_l2info_vxlan *vxl;
+       struct interface *vlan_if;
+
+       zif = zvni->vxlan_if->info;
+       if (!zif)
+               return -1;
+       vxl = &zif->l2info.vxl;
+
+       vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
+       if (!vlan_if)
+               return -1;
+
+#ifdef GNU_LINUX
+       return kernel_upd_neigh(vlan_if, &n->ip, &n->emac,
+                               0, NUD_PROBE);
+#else
+       return 0;
+#endif
+}
+
 /*
  * Install neighbor hash entry - called upon access VLAN change.
  */
@@ -2835,10 +2889,48 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
        /* Add primary SVI MAC-IP */
        zvni_add_macip_for_intf(vlan_if, zvni);
 
-       /* Add VRR MAC-IP - if any*/
-       vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
-       if (vrr_if)
-               zvni_add_macip_for_intf(vrr_if, zvni);
+       if (advertise_gw_macip_enabled(zvni)) {
+               /* Add VRR MAC-IP - if any*/
+               vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
+               if (vrr_if)
+                       zvni_add_macip_for_intf(vrr_if, zvni);
+       }
+
+       return;
+}
+
+static void zvni_svi_macip_del_for_vni_hash(struct hash_backet *backet,
+                                          void *ctxt)
+{
+       zebra_vni_t *zvni = NULL;
+       struct zebra_if *zif = NULL;
+       struct zebra_l2info_vxlan zl2_info;
+       struct interface *vlan_if = NULL;
+       struct interface *ifp;
+
+       /* Add primary SVI MAC*/
+       zvni = (zebra_vni_t *)backet->data;
+       if (!zvni)
+               return;
+
+       ifp = zvni->vxlan_if;
+       if (!ifp)
+               return;
+       zif = ifp->info;
+
+       /* If down or not mapped to a bridge, we're done. */
+       if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+               return;
+
+       zl2_info = zif->l2info.vxl;
+
+       vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
+                                 zif->brslave_info.br_if);
+       if (!vlan_if)
+               return;
+
+       /* Del primary MAC-IP */
+       zvni_del_macip_for_intf(vlan_if, zvni);
 
        return;
 }
@@ -5329,6 +5421,8 @@ static void process_remote_macip_add(vni_t vni,
                        zvni_neigh_install(zvni, n);
        }
 
+       zvni_probe_neigh_on_mac_add(zvni, mac);
+
        /* Update seq number. */
        n->rem_seq = seq;
 }
@@ -6868,6 +6962,8 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
                vty_out(vty, "L3 VNIs: %u\n", num_l3vnis);
                vty_out(vty, "Advertise gateway mac-ip: %s\n",
                        zvrf->advertise_gw_macip ? "Yes" : "No");
+               vty_out(vty, "Advertise svi mac-ip: %s\n",
+                       zvrf->advertise_svi_macip ? "Yes" : "No");
                vty_out(vty, "Duplicate address detection: %s\n",
                        zvrf->dup_addr_detect ? "Enable" : "Disable");
                vty_out(vty, "  Detection max-moves %u, time %d\n",
@@ -7029,6 +7125,7 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
        zebra_vni_t *zvni = NULL;
        zebra_mac_t *zmac = NULL;
        zebra_l3vni_t *zl3vni = NULL;
+       struct zebra_vrf *zvrf;
 
        /* check if this is a remote neigh entry corresponding to remote
         * next-hop
@@ -7081,9 +7178,23 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
                return 0;
        }
 
+       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
+       if (!zvrf) {
+               zlog_debug("%s: VNI %u vrf lookup failed.",
+                                  __PRETTY_FUNCTION__, zvni->vni);
+               return -1;
+       }
+
+       /* In case of feeze action, if local neigh is in duplicate state,
+        * Mark the Neigh as inactive before sending delete request to BGPd,
+        * If BGPd has remote entry, it will re-install
+        */
+       if (zvrf->dad_freeze &&
+           CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
+           ZEBRA_NEIGH_SET_INACTIVE(n);
+
        /* Remove neighbor from BGP. */
-       zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
-                       0, n->state);
+       zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0, n->state);
 
        /* Delete this neighbor entry. */
        zvni_neigh_del(zvni, n);
@@ -8655,6 +8766,102 @@ stream_failure:
        return;
 }
 
+/*
+ * Handle message from client to enable/disable advertisement of svi macip
+ * routes
+ */
+void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
+{
+       struct stream *s;
+       int advertise;
+       vni_t vni = 0;
+       zebra_vni_t *zvni = NULL;
+       struct interface *ifp = NULL;
+
+       if (zvrf_id(zvrf) != VRF_DEFAULT) {
+               zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
+                          zvrf_id(zvrf));
+               return;
+       }
+
+       s = msg;
+       STREAM_GETC(s, advertise);
+       STREAM_GETL(s, vni);
+
+       if (!vni) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug("EVPN gateway macip Adv %s, currently %s",
+                                  advertise ? "enabled" : "disabled",
+                                  advertise_gw_macip_enabled(NULL)
+                                          ? "enabled"
+                                          : "disabled");
+
+               if (zvrf->advertise_svi_macip == advertise)
+                       return;
+
+
+               if (advertise) {
+                       zvrf->advertise_svi_macip = advertise;
+                       hash_iterate(zvrf->vni_table,
+                                    zvni_gw_macip_add_for_vni_hash, NULL);
+               } else {
+                       hash_iterate(zvrf->vni_table,
+                                    zvni_svi_macip_del_for_vni_hash, NULL);
+                       zvrf->advertise_svi_macip = advertise;
+               }
+
+       } else {
+               struct zebra_if *zif = NULL;
+               struct zebra_l2info_vxlan zl2_info;
+               struct interface *vlan_if = NULL;
+
+               zvni = zvni_lookup(vni);
+               if (!zvni)
+                       return;
+
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug(
+                               "EVPN SVI macip Adv %s on VNI %d , currently %s",
+                               advertise ? "enabled" : "disabled", vni,
+                               advertise_svi_macip_enabled(zvni)
+                                       ? "enabled"
+                                       : "disabled");
+
+               if (zvni->advertise_svi_macip == advertise)
+                       return;
+
+               ifp = zvni->vxlan_if;
+               if (!ifp)
+                       return;
+
+               zif = ifp->info;
+
+               /* If down or not mapped to a bridge, we're done. */
+               if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+                       return;
+
+               zl2_info = zif->l2info.vxl;
+
+               vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
+                                         zif->brslave_info.br_if);
+               if (!vlan_if)
+                       return;
+
+               if (advertise) {
+                       zvni->advertise_svi_macip = advertise;
+                       /* Add primary SVI MAC-IP */
+                       zvni_add_macip_for_intf(vlan_if, zvni);
+               } else {
+                       /* Del primary MAC-IP */
+                       zvni_del_macip_for_intf(vlan_if, zvni);
+                       zvni->advertise_svi_macip = advertise;
+               }
+       }
+
+stream_failure:
+       return;
+}
+
 /*
  * Handle message from client to enable/disable advertisement of g/w macip
  * routes
index c25e7357edd532e793ae41e3995d2a9197cc901f..2cf21ff90b649c0a2997e54513f0a97e05347294 100644 (file)
@@ -68,6 +68,7 @@ extern void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS);
index cae0d62bb307910e890ff8a324c1658a1e98c9b8..c36d156359f305d965108169864d5346e62204b1 100644 (file)
@@ -70,6 +70,9 @@ struct zebra_vni_t_ {
        /* Flag for advertising gw macip */
        uint8_t advertise_gw_macip;
 
+       /* Flag for advertising svi macip */
+       uint8_t advertise_svi_macip;
+
        /* Flag for advertising gw macip */
        uint8_t advertise_subnet;
 
index 766dd54fb3467249c370e3312f71c286e346faf8..6532491cefe5821c3a774108cdb4f349bfcf1b05 100644 (file)
 #include "zebra/zapi_msg.h"       /* for zserv_handle_commands */
 #include "zebra/zebra_vrf.h"      /* for zebra_vrf_lookup_by_id, zvrf */
 #include "zebra/zserv.h"          /* for zserv */
+#include "zebra/zebra_router.h"
 #include "zebra/zebra_errors.h"   /* for error messages */
 /* clang-format on */
 
 /* privileges */
 extern struct zebra_privs_t zserv_privs;
 
+/* The listener socket for clients connecting to us */
+static int zsock;
+
 /*
  * Client thread events.
  *
@@ -312,7 +316,7 @@ static int zserv_read(struct thread *thread)
        uint32_t p2p;
        struct zmsghdr hdr;
 
-       p2p_orig = atomic_load_explicit(&zebrad.packets_to_process,
+       p2p_orig = atomic_load_explicit(&zrouter.packets_to_process,
                                        memory_order_relaxed);
        cache = stream_fifo_new();
        p2p = p2p_orig;
@@ -401,8 +405,10 @@ static int zserv_read(struct thread *thread)
                }
 
                /* Debug packet information. */
-               if (IS_ZEBRA_DEBUG_EVENT)
-                       zlog_debug("zebra message comes from socket [%d]",
+               if (IS_ZEBRA_DEBUG_PACKET)
+                       zlog_debug("zebra message[%s:%u:%u] comes from socket [%d]",
+                                  zserv_command_string(hdr.command),
+                                  hdr.vrf_id, hdr.length,
                                   sock);
 
                if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
@@ -438,7 +444,8 @@ static int zserv_read(struct thread *thread)
        }
 
        if (IS_ZEBRA_DEBUG_PACKET)
-               zlog_debug("Read %d packets", p2p_orig - p2p);
+               zlog_debug("Read %d packets from client: %s", p2p_orig - p2p,
+                          zebra_route_string(client->proto));
 
        /* Reschedule ourselves */
        zserv_client_event(client, ZSERV_CLIENT_READ);
@@ -481,9 +488,9 @@ static void zserv_client_event(struct zserv *client,
  * with the message is executed. This proceeds until there are no more messages,
  * an error occurs, or the processing limit is reached.
  *
- * The client's I/O thread can push at most zebrad.packets_to_process messages
+ * The client's I/O thread can push at most zrouter.packets_to_process messages
  * onto the input buffer before notifying us there are packets to read. As long
- * as we always process zebrad.packets_to_process messages here, then we can
+ * as we always process zrouter.packets_to_process messages here, then we can
  * rely on the read thread to handle queuing this task enough times to process
  * everything on the input queue.
  */
@@ -492,7 +499,7 @@ static int zserv_process_messages(struct thread *thread)
        struct zserv *client = THREAD_ARG(thread);
        struct stream *msg;
        struct stream_fifo *cache = stream_fifo_new();
-       uint32_t p2p = zebrad.packets_to_process;
+       uint32_t p2p = zrouter.packets_to_process;
        bool need_resched = false;
 
        pthread_mutex_lock(&client->ibuf_mtx);
@@ -622,7 +629,6 @@ static void zserv_client_free(struct zserv *client)
 
                vrf_bitmap_free(client->redist_default[afi]);
        }
-       vrf_bitmap_free(client->ifinfo);
        vrf_bitmap_free(client->ridinfo);
 
        XFREE(MTYPE_TMP, client);
@@ -637,7 +643,7 @@ void zserv_close_client(struct zserv *client)
                zlog_debug("Closing client '%s'",
                           zebra_route_string(client->proto));
 
-       thread_cancel_event(zebrad.master, client);
+       thread_cancel_event(zrouter.master, client);
        THREAD_OFF(client->t_cleanup);
        THREAD_OFF(client->t_process);
 
@@ -646,7 +652,7 @@ void zserv_close_client(struct zserv *client)
        client->pthread = NULL;
 
        /* remove from client list */
-       listnode_delete(zebrad.client_list, client);
+       listnode_delete(zrouter.client_list, client);
 
        /* delete client */
        zserv_client_free(client);
@@ -695,7 +701,7 @@ static struct zserv *zserv_client_create(int sock)
        client->wb = buffer_new(0);
 
        /* Set table number. */
-       client->rtm_table = zebrad.rtm_table_default;
+       client->rtm_table = zrouter.rtm_table_default;
 
        atomic_store_explicit(&client->connect_time, (uint32_t) monotime(NULL),
                              memory_order_relaxed);
@@ -706,14 +712,13 @@ static struct zserv *zserv_client_create(int sock)
                        client->redist[afi][i] = vrf_bitmap_init();
                client->redist_default[afi] = vrf_bitmap_init();
        }
-       client->ifinfo = vrf_bitmap_init();
        client->ridinfo = vrf_bitmap_init();
 
        /* by default, it's not a synchronous client */
        client->is_synchronous = 0;
 
        /* Add this client to linked list. */
-       listnode_add(zebrad.client_list, client);
+       listnode_add(zrouter.client_list, client);
 
        struct frr_pthread_attr zclient_pthr_attrs = {
                .start = frr_pthread_attr_default.start,
@@ -783,16 +788,16 @@ void zserv_start(char *path)
        old_mask = umask(0077);
 
        /* Make UNIX domain socket. */
-       zebrad.sock = socket(sa.ss_family, SOCK_STREAM, 0);
-       if (zebrad.sock < 0) {
+       zsock = socket(sa.ss_family, SOCK_STREAM, 0);
+       if (zsock < 0) {
                flog_err_sys(EC_LIB_SOCKET, "Can't create zserv socket: %s",
                             safe_strerror(errno));
                return;
        }
 
        if (sa.ss_family != AF_UNIX) {
-               sockopt_reuseaddr(zebrad.sock);
-               sockopt_reuseport(zebrad.sock);
+               sockopt_reuseaddr(zsock);
+               sockopt_reuseport(zsock);
        } else {
                struct sockaddr_un *suna = (struct sockaddr_un *)&sa;
                if (suna->sun_path[0])
@@ -800,28 +805,28 @@ void zserv_start(char *path)
        }
 
        frr_elevate_privs(&zserv_privs) {
-               setsockopt_so_recvbuf(zebrad.sock, 1048576);
-               setsockopt_so_sendbuf(zebrad.sock, 1048576);
+               setsockopt_so_recvbuf(zsock, 1048576);
+               setsockopt_so_sendbuf(zsock, 1048576);
        }
 
        frr_elevate_privs((sa.ss_family != AF_UNIX) ? &zserv_privs : NULL) {
-               ret = bind(zebrad.sock, (struct sockaddr *)&sa, sa_len);
+               ret = bind(zsock, (struct sockaddr *)&sa, sa_len);
        }
        if (ret < 0) {
                flog_err_sys(EC_LIB_SOCKET, "Can't bind zserv socket on %s: %s",
                             path, safe_strerror(errno));
-               close(zebrad.sock);
-               zebrad.sock = -1;
+               close(zsock);
+               zsock = -1;
                return;
        }
 
-       ret = listen(zebrad.sock, 5);
+       ret = listen(zsock, 5);
        if (ret < 0) {
                flog_err_sys(EC_LIB_SOCKET,
                             "Can't listen to zserv socket %s: %s", path,
                             safe_strerror(errno));
-               close(zebrad.sock);
-               zebrad.sock = -1;
+               close(zsock);
+               zsock = -1;
                return;
        }
 
@@ -834,15 +839,15 @@ void zserv_event(struct zserv *client, enum zserv_event event)
 {
        switch (event) {
        case ZSERV_ACCEPT:
-               thread_add_read(zebrad.master, zserv_accept, NULL, zebrad.sock,
+               thread_add_read(zrouter.master, zserv_accept, NULL, zsock,
                                NULL);
                break;
        case ZSERV_PROCESS_MESSAGES:
-               thread_add_event(zebrad.master, zserv_process_messages, client,
+               thread_add_event(zrouter.master, zserv_process_messages, client,
                                 0, &client->t_process);
                break;
        case ZSERV_HANDLE_CLIENT_FAIL:
-               thread_add_event(zebrad.master, zserv_handle_client_fail,
+               thread_add_event(zrouter.master, zserv_handle_client_fail,
                                 client, 0, &client->t_cleanup);
        }
 }
@@ -1002,7 +1007,7 @@ struct zserv *zserv_find_client(uint8_t proto, unsigned short instance)
        struct listnode *node, *nnode;
        struct zserv *client;
 
-       for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
+       for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
                if (client->proto == proto && client->instance == instance)
                        return client;
        }
@@ -1021,7 +1026,7 @@ DEFUN (show_zebra_client,
        struct listnode *node;
        struct zserv *client;
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client))
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client))
                zebra_show_client_detail(vty, client);
 
        return CMD_SUCCESS;
@@ -1044,7 +1049,7 @@ DEFUN (show_zebra_client_summary,
        vty_out(vty,
                "--------------------------------------------------------------------------------\n");
 
-       for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client))
+       for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client))
                zebra_show_client_brief(vty, client);
 
        vty_out(vty, "Routes column shows (added+updated)/deleted\n");
@@ -1067,10 +1072,10 @@ void zserv_read_file(char *input)
 void zserv_init(void)
 {
        /* Client list init. */
-       zebrad.client_list = list_new();
+       zrouter.client_list = list_new();
 
        /* Misc init. */
-       zebrad.sock = -1;
+       zsock = -1;
 
        install_element(ENABLE_NODE, &show_zebra_client_cmd);
        install_element(ENABLE_NODE, &show_zebra_client_summary_cmd);
index 041485cdc252e27f44a059df09accfb017d86390..ac016e65f3e19563b394fd6723e0bd46cafe0c59 100644 (file)
@@ -89,9 +89,6 @@ struct zserv {
        /* Redistribute default route flag. */
        vrf_bitmap_t redist_default[AFI_MAX];
 
-       /* Interface information. */
-       vrf_bitmap_t ifinfo;
-
        /* Router-id information. */
        vrf_bitmap_t ridinfo;
 
@@ -173,31 +170,6 @@ struct zserv {
 DECLARE_HOOK(zserv_client_connect, (struct zserv *client), (client));
 DECLARE_KOOH(zserv_client_close, (struct zserv *client), (client));
 
-/* Zebra instance */
-struct zebra_t {
-       /* Thread master */
-       struct thread_master *master;
-       struct list *client_list;
-
-       /* Socket */
-       int sock;
-
-       /* default table */
-       uint32_t rtm_table_default;
-
-/* rib work queue */
-#define ZEBRA_RIB_PROCESS_HOLD_TIME 10
-#define ZEBRA_RIB_PROCESS_RETRY_TIME 1
-       struct work_queue *ribq;
-       struct meta_queue *mq;
-
-       /* LSP work queue */
-       struct work_queue *lsp_process_q;
-
-#define ZEBRA_ZAPI_PACKETS_TO_PROCESS 1000
-       _Atomic uint32_t packets_to_process;
-};
-extern struct zebra_t zebrad;
 extern unsigned int multipath_num;
 
 /*