]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #1078 from dwalton76/ospfd-network-cmd-warning
authorRenato Westphal <renato@openbsd.org>
Thu, 31 Aug 2017 16:23:25 +0000 (13:23 -0300)
committerGitHub <noreply@github.com>
Thu, 31 Aug 2017 16:23:25 +0000 (13:23 -0300)
*: return CMD_WARNING if command was already configured

134 files changed:
babeld/babel_interface.c
babeld/kernel.c
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_evpn_private.h
bgpd/bgp_evpn_vty.c
bgpd/bgp_evpn_vty.h
bgpd/bgp_memory.c
bgpd/bgp_memory.h
bgpd/bgp_nexthop.c
bgpd/bgp_nexthop.h
bgpd/bgp_nht.c
bgpd/bgp_nht.h
bgpd/bgp_open.c
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_routemap.c
bgpd/bgp_vty.c
bgpd/bgp_vty.h
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.c
bgpd/bgpd.h
bgpd/rfapi/bgp_rfapi_cfg.c
bgpd/rfapi/rfapi_import.c
configure.ac
debian/frr.install
doc/Makefile.am
doc/bgpd.texi
doc/frr-args.8.in [new file with mode: 0644]
doc/main.texi
eigrpd/eigrp_dump.c
eigrpd/eigrp_hello.c
eigrpd/eigrp_interface.c
eigrpd/eigrp_packet.c
eigrpd/eigrp_routemap.c
eigrpd/eigrp_topology.c
eigrpd/eigrp_update.c
eigrpd/eigrp_vty.c
isisd/isis_circuit.c
isisd/isis_dynhn.c
isisd/isis_lsp.c
isisd/isis_misc.c
isisd/isis_misc.h
isisd/isis_spf.c
isisd/isisd.c
lib/command.c
lib/command.h
lib/frr_zmq.c [new file with mode: 0644]
lib/frr_zmq.h [new file with mode: 0644]
lib/grammar_sandbox_main.c
lib/libfrr.c
lib/libfrr.h
lib/nexthop.c
lib/nexthop.h
lib/routemap.c
lib/routemap.h
lib/sockunion.h
lib/subdir.am
lib/vty.c
lib/vty.h
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_route.c
nhrpd/nhrp_vty.c
ospf6d/ospf6_area.c
ospf6d/ospf6_asbr.c
ospf6d/ospf6_interface.c
ospf6d/ospf6_top.c
ospf6d/ospf6_zebra.c
ospfd/ospf_te.c
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_cmd.c
pimd/pim_instance.c
pimd/pim_mroute.c
pimd/pim_msdp_socket.c
pimd/pim_rp.c
pimd/pim_sock.c
pimd/pim_sock.h
pimd/pim_ssm.c
pimd/pim_upstream.c
pimd/pim_vty.c
pimd/pim_zebra.c
pimd/test_igmpv3_join.c
redhat/frr.spec.in
ripd/rip_interface.c
ripd/ripd.c
ripngd/ripng_interface.c
ripngd/ripngd.c
tests/.gitignore
tests/Makefile.am
tests/lib/cli/test_commands.py
tests/lib/test_zmq.c [new file with mode: 0644]
tests/lib/test_zmq.py [new file with mode: 0644]
tests/lib/test_zmq.refout [new file with mode: 0644]
vtysh/vtysh.c
vtysh/vtysh.h
vtysh/vtysh_config.c
vtysh/vtysh_main.c
zebra/connected.c
zebra/connected.h
zebra/if_ioctl.c
zebra/if_ioctl_solaris.c
zebra/if_netlink.c
zebra/interface.c
zebra/interface.h
zebra/ioctl.c
zebra/irdp_packet.c
zebra/kernel_socket.c
zebra/kernel_socket.h
zebra/redistribute.c
zebra/rib.h
zebra/rt_netlink.c
zebra/rt_socket.c
zebra/rtadv.c
zebra/rtread_getmsg.c
zebra/zebra_fpm_netlink.c
zebra/zebra_fpm_protobuf.c
zebra/zebra_l2.c
zebra/zebra_mpls.c
zebra/zebra_mroute.c
zebra/zebra_ptm.c
zebra/zebra_pw.c
zebra/zebra_rib.c
zebra/zebra_routemap.c
zebra/zebra_static.c
zebra/zebra_static.h
zebra/zebra_vrf.c
zebra/zebra_vty.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan_private.h
zebra/zserv.c

index bf560b82943a085e75eac4dc880c0ef65a7c6f4b..4419160cd70bf567256d8fc35adf6d34dc1f6015 100644 (file)
@@ -1321,7 +1321,7 @@ interface_config_write (struct vty *vty)
     int write = 0;
 
     for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, ifp)) {
-        vty_out (vty, "interface %s\n",ifp->name);
+        vty_frame (vty, "interface %s\n",ifp->name);
         if (ifp->desc)
             vty_out (vty, " description %s\n",ifp->desc);
         babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
@@ -1377,7 +1377,7 @@ interface_config_write (struct vty *vty)
                 write++;
             }
         }
-        vty_out (vty, "!\n");
+        vty_endframe (vty, "!\n");
         write++;
     }
     return write;
index 394d7b1e816e3af4192485da0961b4f0b2aef499..3343ca2e9538a3acba11a10a72d6be72df0ad0f7 100644 (file)
@@ -169,7 +169,7 @@ zebra_route(int add, int family, const unsigned char *pref, unsigned short plen,
     api.prefix = quagga_prefix;
 
     if(metric >= KERNEL_INFINITY) {
-        api.flags = ZEBRA_FLAG_REJECT;
+       zapi_route_set_blackhole(&api, BLACKHOLE_REJECT);
     } else {
         SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
         api.nexthop_num = 1;
index 0560dc46f961db6864c77465abc979c815e462a6..8c3a1b337b7184c8623d92ed0dfb3dd6c44c3b76 100644 (file)
@@ -45,6 +45,8 @@
 #include "bgpd/bgp_encap_types.h"
 #include "bgpd/bgp_debug.h"
 #include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_nexthop.h"
 
 /*
  * Definitions and external declarations.
@@ -1199,6 +1201,13 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn,
                return 0;
        }
 
+       /* Update the tunnel-ip hash */
+       bgp_tip_del(bgp, &vpn->originator_ip);
+       bgp_tip_add(bgp, &originator_ip);
+
+       /* filter routes as martian nexthop db has changed */
+       bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
+
        /* Need to withdraw type-3 route as the originator IP is part
         * of the key.
         */
@@ -2042,7 +2051,7 @@ static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p,
        /* Prefix contains RD, ESI, EthTag, IP length, IP, GWIP and VNI */
        stream_putc(s, 8 + 10 + 4 + 1 + len + 3);
        stream_put(s, prd->val, 8);
-       if (attr && attr)
+       if (attr)
                stream_put(s, &(attr->evpn_overlay.eth_s_id), 10);
        else
                stream_put(s, &temp, 10);
@@ -2052,7 +2061,7 @@ static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p,
                stream_put_ipv4(s, p_evpn_p->ip.ipaddr_v4.s_addr);
        else
                stream_put(s, &p_evpn_p->ip.ipaddr_v6, 16);
-       if (attr && attr) {
+       if (attr) {
                if (IS_IPADDR_V4(&p_evpn_p->ip))
                        stream_put_ipv4(s,
                                        attr->evpn_overlay.gw_ip.ipv4.s_addr);
@@ -2178,6 +2187,71 @@ char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len)
        return buf;
 }
 
+/*
+ * Function to convert evpn route to json format.
+ * NOTE: We don't use prefix2str as the output here is a bit different.
+ */
+void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json)
+{
+       char buf1[ETHER_ADDR_STRLEN];
+       char buf2[PREFIX2STR_BUFFER];
+
+       if (!json)
+               return;
+
+       if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
+               json_object_int_add(json, "routeType", p->prefix.route_type);
+               json_object_int_add(json, "ethTag", 0);
+               json_object_int_add(json, "ipLen",
+                                   IS_EVPN_PREFIX_IPADDR_V4(p)
+                                           ? IPV4_MAX_BITLEN
+                                           : IPV6_MAX_BITLEN);
+               json_object_string_add(json, "ip",
+                                      inet_ntoa(p->prefix.ip.ipaddr_v4));
+       } else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
+               if (IS_EVPN_PREFIX_IPADDR_NONE(p)) {
+                       json_object_int_add(json, "routeType",
+                                           p->prefix.route_type);
+                       json_object_int_add(
+                               json, "esi",
+                               0); /* TODO: we don't support esi yet */
+                       json_object_int_add(json, "ethTag", 0);
+                       json_object_int_add(json, "macLen", 8 * ETH_ALEN);
+                       json_object_string_add(json, "mac",
+                                              prefix_mac2str(&p->prefix.mac,
+                                                             buf1,
+                                                             sizeof(buf1)));
+               } else {
+                       u_char family;
+
+                       family = IS_EVPN_PREFIX_IPADDR_V4(p) ? AF_INET
+                                                            : AF_INET6;
+
+                       json_object_int_add(json, "routeType",
+                                           p->prefix.route_type);
+                       json_object_int_add(
+                               json, "esi",
+                               0); /* TODO: we don't support esi yet */
+                       json_object_int_add(json, "ethTag", 0);
+                       json_object_int_add(json, "macLen", 8 * ETH_ALEN);
+                       json_object_string_add(json, "mac",
+                                              prefix_mac2str(&p->prefix.mac,
+                                                             buf1,
+                                                             sizeof(buf1)));
+                       json_object_int_add(json, "ipLen",
+                                           IS_EVPN_PREFIX_IPADDR_V4(p)
+                                                   ? IPV4_MAX_BITLEN
+                                                   : IPV6_MAX_BITLEN);
+                       json_object_string_add(
+                               json, "ip",
+                               inet_ntop(family, &p->prefix.ip.ip.addr, buf2,
+                                         PREFIX2STR_BUFFER));
+               }
+       } else {
+               /* Currently, this is to cater to other AF_ETHERNET code. */
+       }
+}
+
 /*
  * Function to convert evpn route to string.
  * NOTE: We don't use prefix2str as the output here is a bit different.
@@ -2562,6 +2636,71 @@ int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
        return install_uninstall_evpn_route(bgp, afi, safi, p, ri, 0);
 }
 
+/* filter routes which have martian next hops */
+int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp)
+{
+       afi_t afi;
+       safi_t safi;
+       struct bgp_node *rd_rn, *rn;
+       struct bgp_table *table;
+       struct bgp_info *ri;
+
+       afi = AFI_L2VPN;
+       safi = SAFI_EVPN;
+
+       /* Walk entire global routing table and evaluate routes which could be
+        * imported into this VPN. Note that we cannot just look at the routes
+        * for the VNI's RD -
+        * remote routes applicable for this VNI could have any RD.
+        */
+       /* EVPN routes are a 2-level table. */
+       for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
+            rd_rn = bgp_route_next(rd_rn)) {
+               table = (struct bgp_table *)(rd_rn->info);
+               if (!table)
+                       continue;
+
+               for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
+
+                       for (ri = rn->info; ri; ri = ri->next) {
+
+                               /* Consider "valid" remote routes applicable for
+                                * this VNI. */
+                               if (!(ri->type == ZEBRA_ROUTE_BGP
+                                     && ri->sub_type == BGP_ROUTE_NORMAL))
+                                       continue;
+
+                               if (bgp_nexthop_self(bgp, ri->attr->nexthop)) {
+
+                                       char attr_str[BUFSIZ];
+                                       char pbuf[PREFIX_STRLEN];
+
+                                       bgp_dump_attr(ri->attr, attr_str,
+                                                     BUFSIZ);
+
+                                       if (bgp_debug_update(ri->peer, &rn->p,
+                                                            NULL, 1))
+                                               zlog_debug(
+                                                       "%u: prefix %s with attr %s - DENIED due to martian or self nexthop",
+                                                       bgp->vrf_id,
+                                                       prefix2str(
+                                                               &rn->p, pbuf,
+                                                               sizeof(pbuf)),
+                                                       attr_str);
+
+                                       bgp_evpn_unimport_route(bgp, afi, safi,
+                                                               &rn->p, ri);
+
+                                       bgp_rib_remove(rn, ri, ri->peer, afi,
+                                                      safi);
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Handle del of a local MACIP.
  */
@@ -2657,6 +2796,11 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
         */
        delete_routes_for_vni(bgp, vpn);
 
+       /*
+        * tunnel is no longer active, del tunnel ip address from tip_hash
+        */
+       bgp_tip_del(bgp, &vpn->originator_ip);
+
        /* Clear "live" flag and see if hash needs to be freed. */
        UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE);
        if (!is_vni_configured(vpn))
@@ -2704,13 +2848,19 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
                }
        }
 
-       /* if the VNI is live already, there is nothibng more to do */
+       /* if the VNI is live already, there is nothing more to do */
        if (is_vni_live(vpn))
                return 0;
 
        /* Mark as "live" */
        SET_FLAG(vpn->flags, VNI_FLAG_LIVE);
 
+       /* tunnel is now active, add tunnel-ip to db */
+       bgp_tip_add(bgp, &originator_ip);
+
+       /* filter routes as nexthop database has changed */
+       bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
+
        /* Create EVPN type-3 route and schedule for processing. */
        build_evpn_type3_prefix(&p, vpn->originator_ip);
        if (update_evpn_route(bgp, vpn, &p, 0)) {
@@ -2725,6 +2875,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
         */
        install_routes_for_vni(bgp, vpn);
 
+       /* If we are advertising gateway mac-ip
+          It needs to be conveyed again to zebra */
+       bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip, vpn->vni);
+
        return 0;
 }
 
index e9b7857212cd79db3979b0fe612a7bc4dc0c4752..985f41f58675c1ea084bbcca4086fae38e91cb1a 100644 (file)
@@ -28,6 +28,7 @@
 extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw);
 extern char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len);
 extern char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len);
+extern void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json);
 extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
                                   struct prefix_rd *prd, mpls_label_t *label,
                                   struct attr *attr, int addpath_encode,
@@ -38,6 +39,7 @@ extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi,
                                 struct prefix *p, struct bgp_info *ri);
 extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
                                   struct prefix *p, struct bgp_info *ri);
+extern int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp);
 extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
                                    struct ethaddr *mac, struct ipaddr *ip);
 extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
index 9dc459cd4e3c1ff88c6233fa492f2693f9427534..a58f73f4bc924a767d21dabcc440ab421188b9e5 100644 (file)
@@ -28,6 +28,8 @@
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_ecommunity.h"
 
+#define RT_ADDRSTRLEN 28
+
 /* EVPN prefix lengths. */
 #define EVPN_TYPE_2_ROUTE_PREFIXLEN      224
 #define EVPN_TYPE_3_ROUTE_PREFIXLEN      224
index 948c7f50f24162cf5b408cb3a7384336a00a152a..2410f30ddfa65d62e59e1cdeb10e82e0b0858c22 100644 (file)
@@ -38,6 +38,7 @@
 #define SHOW_DISPLAY_STANDARD 0
 #define SHOW_DISPLAY_TAGS 1
 #define SHOW_DISPLAY_OVERLAY 2
+#define VNI_STR_LEN 32
 
 /*
  * Context for VNI hash walk - used by callbacks.
@@ -46,15 +47,12 @@ struct vni_walk_ctx {
        struct bgp *bgp;
        struct vty *vty;
        struct in_addr vtep_ip;
-};
-
-struct evpn_config_write {
-       int write;
-       struct vty *vty;
+       json_object *json;
 };
 
 #if defined(HAVE_CUMULUS)
-static void display_import_rt(struct vty *vty, struct irt_node *irt)
+static void display_import_rt(struct vty *vty, struct irt_node *irt,
+                             json_object *json)
 {
        u_char *pnt;
        u_char type, sub_type;
@@ -68,7 +66,14 @@ static void display_import_rt(struct vty *vty, struct irt_node *irt)
        } eip;
        struct listnode *node, *nnode;
        struct bgpevpn *tmp_vpn;
+       json_object *json_rt = NULL;
+       json_object *json_vnis = NULL;
+       char rt_buf[RT_ADDRSTRLEN];
 
+       if (json) {
+               json_rt = json_object_new_object();
+               json_vnis = json_object_new_array();
+       }
 
        /* TODO: This needs to go into a function */
 
@@ -88,7 +93,13 @@ static void display_import_rt(struct vty *vty, struct irt_node *irt)
                eas.val |= (*pnt++ << 8);
                eas.val |= (*pnt++);
 
-               vty_out(vty, "Route-target: %u:%u", eas.as, eas.val);
+               snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
+
+               if (json)
+                       json_object_string_add(json_rt, "rt", rt_buf);
+               else
+                       vty_out(vty, "Route-target: %s", rt_buf);
+
                break;
 
        case ECOMMUNITY_ENCODE_IP:
@@ -97,7 +108,14 @@ static void display_import_rt(struct vty *vty, struct irt_node *irt)
                eip.val = (*pnt++ << 8);
                eip.val |= (*pnt++);
 
-               vty_out(vty, "Route-target: %s:%u", inet_ntoa(eip.ip), eip.val);
+               snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
+                        eip.val);
+
+               if (json)
+                       json_object_string_add(json_rt, "rt", rt_buf);
+               else
+                       vty_out(vty, "Route-target: %s", rt_buf);
+
                break;
 
        case ECOMMUNITY_ENCODE_AS4:
@@ -109,65 +127,102 @@ static void display_import_rt(struct vty *vty, struct irt_node *irt)
                eas.val = (*pnt++ << 8);
                eas.val |= (*pnt++);
 
-               vty_out(vty, "Route-target: %u:%u", eas.as, eas.val);
+               snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
+
+               if (json)
+                       json_object_string_add(json_rt, "rt", rt_buf);
+               else
+                       vty_out(vty, "Route-target: %s", rt_buf);
+
                break;
 
        default:
                return;
        }
 
-       vty_out(vty, "\n");
-       vty_out(vty, "List of VNIs importing routes with this route-target:\n");
+       if (!json) {
+               vty_out(vty,
+                       "\nList of VNIs importing routes with this route-target:\n");
+       }
+
+       for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
+               if (json)
+                       json_object_array_add(
+                               json_vnis, json_object_new_int64(tmp_vpn->vni));
+               else
+                       vty_out(vty, "  %u\n", tmp_vpn->vni);
+       }
 
-       for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn))
-               vty_out(vty, "  %u\n", tmp_vpn->vni);
+       if (json) {
+               json_object_object_add(json_rt, "vnis", json_vnis);
+               json_object_object_add(json, rt_buf, json_rt);
+       }
 }
 
-static void show_import_rt_entry(struct hash_backet *backet, struct vty *vty)
+static void show_import_rt_entry(struct hash_backet *backet, void *args[])
 {
+       json_object *json = NULL;
+       struct vty *vty = NULL;
        struct irt_node *irt = (struct irt_node *)backet->data;
-       display_import_rt(vty, irt);
+
+       vty = args[0];
+       json = args[1];
+
+       display_import_rt(vty, irt, json);
+
+       return;
 }
 
 static void bgp_evpn_show_route_rd_header(struct vty *vty,
-                                         struct bgp_node *rd_rn)
+                                         struct bgp_node *rd_rn,
+                                         json_object *json)
 {
        u_int16_t type;
        struct rd_as rd_as;
        struct rd_ip rd_ip;
        u_char *pnt;
+       char rd_str[RD_ADDRSTRLEN];
 
        pnt = rd_rn->p.u.val;
 
        /* Decode RD type. */
        type = decode_rd_type(pnt);
 
+       if (json)
+               return;
+
        vty_out(vty, "Route Distinguisher: ");
 
        switch (type) {
        case RD_TYPE_AS:
                decode_rd_as(pnt + 2, &rd_as);
-               vty_out(vty, "%u:%d", rd_as.as, rd_as.val);
+               snprintf(rd_str, RD_ADDRSTRLEN, "%u:%d", rd_as.as, rd_as.val);
                break;
 
        case RD_TYPE_IP:
                decode_rd_ip(pnt + 2, &rd_ip);
-               vty_out(vty, "%s:%d", inet_ntoa(rd_ip.ip), rd_ip.val);
+               snprintf(rd_str, RD_ADDRSTRLEN, "%s:%d", inet_ntoa(rd_ip.ip),
+                        rd_ip.val);
                break;
 
        default:
-               vty_out(vty, "Unknown RD type");
+               snprintf(rd_str, RD_ADDRSTRLEN, "Unknown RD type");
                break;
        }
 
-       vty_out(vty, "\n");
+       vty_out(vty, "%s\n", rd_str);
 }
 
-static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp)
+static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
+                                      json_object *json)
 {
        char ri_header[] =
                "   Network          Next Hop            Metric LocPrf Weight Path\n";
 
+       if (json)
+               return;
+
+
        vty_out(vty, "BGP table version is 0, local router ID is %s\n",
                inet_ntoa(bgp->router_id));
        vty_out(vty,
@@ -180,43 +235,83 @@ static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp)
        vty_out(vty, "%s", ri_header);
 }
 
-static void display_vni(struct vty *vty, struct bgpevpn *vpn)
+static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
 {
        char buf1[INET6_ADDRSTRLEN];
        char *ecom_str;
        struct listnode *node, *nnode;
        struct ecommunity *ecom;
+       json_object *json_import_rtl;
+       json_object *json_export_rtl;
+
+       if (json) {
+               json_import_rtl = json_object_new_array();
+               json_export_rtl = json_object_new_array();
+               json_object_int_add(json, "vni", vpn->vni);
+               json_object_string_add(json, "kernelFlag",
+                                      is_vni_live(vpn) ? "Yes" : "No");
+               json_object_string_add(
+                       json, "rd",
+                       prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
+               json_object_string_add(json, "originatorIp",
+                                      inet_ntoa(vpn->originator_ip));
+               json_object_string_add(json, "advertiseGatewayMacip",
+                                      vpn->advertise_gw_macip ? "Yes" : "No");
+       } else {
+               vty_out(vty, "VNI: %d", vpn->vni);
+               if (is_vni_live(vpn))
+                       vty_out(vty, " (known to the kernel)");
+               vty_out(vty, "\n");
 
-       vty_out(vty, "VNI: %d", vpn->vni);
-       if (is_vni_live(vpn))
-               vty_out(vty, " (known to the kernel)");
-       vty_out(vty, "\n");
+               vty_out(vty, "  RD: %s\n",
+                       prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
+               vty_out(vty, "  Originator IP: %s\n",
+                       inet_ntoa(vpn->originator_ip));
+               vty_out(vty, "  Advertise-gw-macip : %s\n",
+                       vpn->advertise_gw_macip ? "Yes" : "No");
+       }
 
-       vty_out(vty, "  RD: %s\n",
-               prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
-       vty_out(vty, "  Originator IP: %s\n", inet_ntoa(vpn->originator_ip));
-       vty_out(vty, "  Advertise-gw-macip : %s\n",
-               vpn->advertise_gw_macip ? "Yes" : "No");
+       if (!json)
+               vty_out(vty, "  Import Route Target:\n");
 
-       vty_out(vty, "  Import Route Target:\n");
        for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
                ecom_str = ecommunity_ecom2str(ecom,
                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
-               vty_out(vty, "    %s\n", ecom_str);
+
+               if (json)
+                       json_object_array_add(json_import_rtl,
+                                             json_object_new_string(ecom_str));
+               else
+                       vty_out(vty, "    %s\n", ecom_str);
+
                XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
        }
 
-       vty_out(vty, "  Export Route Target:\n");
+       if (json)
+               json_object_object_add(json, "importRts", json_import_rtl);
+       else
+               vty_out(vty, "  Export Route Target:\n");
+
        for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
                ecom_str = ecommunity_ecom2str(ecom,
                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
-               vty_out(vty, "    %s\n", ecom_str);
+
+               if (json)
+                       json_object_array_add(json_export_rtl,
+                                             json_object_new_string(ecom_str));
+               else
+                       vty_out(vty, "    %s\n", ecom_str);
+
                XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
        }
+
+       if (json)
+               json_object_object_add(json, "exportRts", json_export_rtl);
 }
 
 static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
-                           struct vty *vty, struct in_addr vtep_ip)
+                           struct vty *vty, struct in_addr vtep_ip,
+                           json_object *json)
 {
        struct bgp_node *rn;
        struct bgp_info *ri;
@@ -228,41 +323,79 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
        for (rn = bgp_table_top(vpn->route_table); rn;
             rn = bgp_route_next(rn)) {
                struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
+               int add_prefix_to_json = 0;
+               char prefix_str[BUFSIZ];
+               json_object *json_paths = NULL;
+               json_object *json_prefix = NULL;
+
+               bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
+                                  sizeof(prefix_str));
 
                if (type && evp->prefix.route_type != type)
                        continue;
 
+               if (json)
+                       json_prefix = json_object_new_object();
+
                if (rn->info) {
                        /* Overall header/legend displayed once. */
                        if (header) {
-                               bgp_evpn_show_route_header(vty, bgp);
+                               bgp_evpn_show_route_header(vty, bgp, json);
                                header = 0;
                        }
 
                        prefix_cnt++;
                }
 
+               if (json)
+                       json_paths = json_object_new_array();
+
                /* For EVPN, the prefix is displayed for each path (to fit in
                 * with code that already exists).
                 */
                for (ri = rn->info; ri; ri = ri->next) {
+                       json_object *json_path = NULL;
+
                        if (vtep_ip.s_addr
                            && !IPV4_ADDR_SAME(&(vtep_ip),
                                               &(ri->attr->nexthop)))
                                continue;
 
+                       if (json)
+                               json_path = json_object_new_array();
+
+                       route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, json_path);
+
+                       if (json)
+                               json_object_array_add(json_paths, json_path);
+
                        path_cnt++;
-                       route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, NULL);
+                       add_prefix_to_json = 1;
+               }
+
+               if (json && add_prefix_to_json) {
+                       json_object_string_add(json_prefix, "prefix",
+                                              prefix_str);
+                       json_object_int_add(json_prefix, "prefixLen",
+                                           rn->p.prefixlen);
+                       json_object_object_add(json_prefix, "paths",
+                                              json_paths);
+                       json_object_object_add(json, prefix_str, json_prefix);
                }
        }
 
-       if (prefix_cnt == 0)
-               vty_out(vty, "No EVPN prefixes %sexist for this VNI\n",
-                       type ? "(of requested type) " : "");
-       else
-               vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
-                       prefix_cnt, path_cnt,
-                       type ? " (of requested type)" : "");
+       if (json) {
+               json_object_int_add(json, "numPrefix", prefix_cnt);
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               if (prefix_cnt == 0)
+                       vty_out(vty, "No EVPN prefixes %sexist for this VNI",
+                               type ? "(of requested type) " : "");
+               else
+                       vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s",
+                               prefix_cnt, path_cnt,
+                               type ? " (of requested type)" : "");
+       }
 }
 
 static void show_vni_routes_hash(struct hash_backet *backet, void *arg)
@@ -270,13 +403,31 @@ static void show_vni_routes_hash(struct hash_backet *backet, void *arg)
        struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
        struct vni_walk_ctx *wctx = arg;
        struct vty *vty = wctx->vty;
+       json_object *json = wctx->json;
+       json_object *json_vni = NULL;
+       char vni_str[VNI_STR_LEN];
+
+       snprintf(vni_str, VNI_STR_LEN, "%d", vpn->vni);
+       if (json) {
+               json_vni = json_object_new_object();
+               json_object_int_add(json_vni, "vni", vpn->vni);
+       } else {
+               vty_out(vty, "\nVNI: %d\n\n", vpn->vni);
+       }
 
-       vty_out(vty, "\nVNI: %d\n\n", vpn->vni);
-       show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip);
+       show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip, json_vni);
+
+       if (json)
+               json_object_object_add(json, vni_str, json_vni);
 }
 
-static void show_vni_entry(struct hash_backet *backet, struct vty *vty)
+static void show_vni_entry(struct hash_backet *backet, void *args[])
 {
+       struct vty *vty;
+       json_object *json;
+       json_object *json_vni;
+       json_object *json_import_rtl;
+       json_object *json_export_rtl;
        struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
        char buf1[10];
        char buf2[INET6_ADDRSTRLEN];
@@ -285,42 +436,92 @@ static void show_vni_entry(struct hash_backet *backet, struct vty *vty)
        struct listnode *node, *nnode;
        struct ecommunity *ecom;
 
+       vty = args[0];
+       json = args[1];
+
+       if (json) {
+               json_vni = json_object_new_object();
+               json_import_rtl = json_object_new_array();
+               json_export_rtl = json_object_new_array();
+       }
+
        buf1[0] = '\0';
        if (is_vni_live(vpn))
                sprintf(buf1, "*");
 
-       vty_out(vty, "%-1s %-10u %-15s %-21s", buf1, vpn->vni,
-               inet_ntoa(vpn->originator_ip),
-               prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
+       if (json) {
+               json_object_int_add(json_vni, "vni", vpn->vni);
+               json_object_string_add(json_vni, "inKernel",
+                                      is_vni_live(vpn) ? "True" : "False");
+               json_object_string_add(json_vni, "originatorIp",
+                                      inet_ntoa(vpn->originator_ip));
+               json_object_string_add(
+                       json_vni, "rd",
+                       prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
+       } else {
+               vty_out(vty, "%-1s %-10u %-15s %-21s", buf1, vpn->vni,
+                       inet_ntoa(vpn->originator_ip),
+                       prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
+       }
 
        for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
                ecom_str = ecommunity_ecom2str(ecom,
                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
 
-               if (listcount(vpn->import_rtl) > 1)
-                       sprintf(rt_buf, "%s, ...", ecom_str);
-               else
-                       sprintf(rt_buf, "%s", ecom_str);
-               vty_out(vty, " %-25s", rt_buf);
+               if (json) {
+                       json_object_array_add(json_import_rtl,
+                                             json_object_new_string(ecom_str));
+               } else {
+                       if (listcount(vpn->import_rtl) > 1)
+                               sprintf(rt_buf, "%s, ...", ecom_str);
+                       else
+                               sprintf(rt_buf, "%s", ecom_str);
+                       vty_out(vty, " %-25s", rt_buf);
+               }
 
                XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
-               break;
+
+               /* If there are multiple import RTs we break here and show only
+                * one */
+               if (!json)
+                       break;
        }
 
+       if (json)
+               json_object_object_add(json_vni, "importRTs", json_import_rtl);
+
        for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
                ecom_str = ecommunity_ecom2str(ecom,
                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
 
-               if (listcount(vpn->export_rtl) > 1)
-                       sprintf(rt_buf, "%s, ...", ecom_str);
-               else
-                       sprintf(rt_buf, "%s", ecom_str);
-               vty_out(vty, " %-25s", rt_buf);
+               if (json) {
+                       json_object_array_add(json_export_rtl,
+                                             json_object_new_string(ecom_str));
+               } else {
+                       if (listcount(vpn->export_rtl) > 1)
+                               sprintf(rt_buf, "%s, ...", ecom_str);
+                       else
+                               sprintf(rt_buf, "%s", ecom_str);
+                       vty_out(vty, " %-25s", rt_buf);
+               }
 
                XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
-               break;
+
+               /* If there are multiple export RTs we break here and show only
+                * one */
+               if (!json)
+                       break;
+       }
+
+       if (json) {
+               char vni_str[VNI_STR_LEN];
+
+               json_object_object_add(json_vni, "exportRTs", json_export_rtl);
+               snprintf(vni_str, VNI_STR_LEN, "%u", vpn->vni);
+               json_object_object_add(json, vni_str, json_vni);
+       } else {
+               vty_out(vty, "\n");
        }
-       vty_out(vty, "\n");
 }
 #endif /* HAVE_CUMULUS */
 
@@ -380,155 +581,139 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
                        continue;
 
-               if ((table = rn->info) != NULL) {
-                       rd_header = 1;
-
-                       for (rm = bgp_table_top(table); rm;
-                            rm = bgp_route_next(rm))
-                               for (ri = rm->info; ri; ri = ri->next) {
-                                       total_count++;
-                                       if (type == bgp_show_type_neighbor) {
-                                               union sockunion *su =
-                                                       output_arg;
-
-                                               if (ri->peer->su_remote == NULL
-                                                   || !sockunion_same(
-                                                              ri->peer->su_remote,
-                                                              su))
-                                                       continue;
-                                       }
-                                       if (header == 0) {
-                                               if (use_json) {
-                                                       if (option
-                                                           == SHOW_DISPLAY_TAGS) {
-                                                               json_object_int_add(
-                                                                       json,
-                                                                       "bgpTableVersion",
-                                                                       0);
-                                                               json_object_string_add(
-                                                                       json,
-                                                                       "bgpLocalRouterId",
-                                                                       inet_ntoa(
-                                                                               bgp->router_id));
-                                                               json_object_object_add(
-                                                                       json,
-                                                                       "bgpStatusCodes",
-                                                                       json_scode);
-                                                               json_object_object_add(
-                                                                       json,
-                                                                       "bgpOriginCodes",
-                                                                       json_ocode);
-                                                       }
-                                               } else {
-                                                       if (option
-                                                           == SHOW_DISPLAY_TAGS)
-                                                               vty_out(vty,
-                                                                       V4_HEADER_TAG);
-                                                       else if (
-                                                               option
-                                                               == SHOW_DISPLAY_OVERLAY)
-                                                               vty_out(vty,
-                                                                       V4_HEADER_OVERLAY);
-                                                       else {
-                                                               vty_out(vty,
-                                                                       "BGP table version is 0, local router ID is %s\n",
-                                                                       inet_ntoa(
-                                                                               bgp->router_id));
-                                                               vty_out(vty,
-                                                                       "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
-                                                               vty_out(vty,
-                                                                       "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
-                                                               vty_out(vty,
-                                                                       V4_HEADER);
-                                                       }
-                                               }
-                                               header = 0;
-                                       }
-                                       if (rd_header) {
-                                               u_int16_t type;
-                                               struct rd_as rd_as;
-                                               struct rd_ip rd_ip;
-                                               u_char *pnt;
+               if ((table = rn->info) == NULL)
+                       continue;
 
-                                               pnt = rn->p.u.val;
+               rd_header = 1;
 
-                                               /* Decode RD type. */
-                                               type = decode_rd_type(pnt);
-                                               /* Decode RD value. */
-                                               if (type == RD_TYPE_AS)
-                                                       decode_rd_as(pnt + 2,
-                                                                    &rd_as);
-                                               else if (type == RD_TYPE_AS4)
-                                                       decode_rd_as4(pnt + 2,
-                                                                     &rd_as);
-                                               else if (type == RD_TYPE_IP)
-                                                       decode_rd_ip(pnt + 2,
-                                                                    &rd_ip);
-                                               if (use_json) {
-                                                       char buffer[BUFSIZ];
-                                                       if (type == RD_TYPE_AS
-                                                           || type == RD_TYPE_AS4)
-                                                               sprintf(buffer,
-                                                                       "%u:%d",
-                                                                       rd_as.as,
-                                                                       rd_as.val);
-                                                       else if (type
-                                                                == RD_TYPE_IP)
-                                                               sprintf(buffer,
-                                                                       "%s:%d",
-                                                                       inet_ntoa(
-                                                                               rd_ip.ip),
-                                                                       rd_ip.val);
+               for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm))
+                       for (ri = rm->info; ri; ri = ri->next) {
+                               total_count++;
+                               if (type == bgp_show_type_neighbor) {
+                                       union sockunion *su = output_arg;
+
+                                       if (ri->peer->su_remote == NULL
+                                           || !sockunion_same(
+                                                      ri->peer->su_remote, su))
+                                               continue;
+                               }
+                               if (header == 0) {
+                                       if (use_json) {
+                                               if (option
+                                                   == SHOW_DISPLAY_TAGS) {
+                                                       json_object_int_add(
+                                                               json,
+                                                               "bgpTableVersion",
+                                                               0);
                                                        json_object_string_add(
-                                                               json_nroute,
-                                                               "routeDistinguisher",
-                                                               buffer);
-                                               } else {
+                                                               json,
+                                                               "bgpLocalRouterId",
+                                                               inet_ntoa(
+                                                                       bgp->router_id));
+                                                       json_object_object_add(
+                                                               json,
+                                                               "bgpStatusCodes",
+                                                               json_scode);
+                                                       json_object_object_add(
+                                                               json,
+                                                               "bgpOriginCodes",
+                                                               json_ocode);
+                                               }
+                                       } else {
+                                               if (option == SHOW_DISPLAY_TAGS)
+                                                       vty_out(vty,
+                                                               V4_HEADER_TAG);
+                                               else if (
+                                                       option
+                                                       == SHOW_DISPLAY_OVERLAY)
+                                                       vty_out(vty,
+                                                               V4_HEADER_OVERLAY);
+                                               else {
+                                                       vty_out(vty,
+                                                               "BGP table version is 0, local router ID is %s\n",
+                                                               inet_ntoa(
+                                                                       bgp->router_id));
                                                        vty_out(vty,
-                                                               "Route Distinguisher: ");
-                                                       if (type == RD_TYPE_AS)
-                                                               vty_out(vty,
-                                                                       "as2 %u:%d",
-                                                                       rd_as.as,
-                                                                       rd_as.val);
-                                                       else if (type
-                                                                == RD_TYPE_AS4)
-                                                               vty_out(vty,
-                                                                       "as4 %u:%d",
-                                                                       rd_as.as,
-                                                                       rd_as.val);
-                                                       else if (type
-                                                                == RD_TYPE_IP)
-                                                               vty_out(vty,
-                                                                       "ip %s:%d",
-                                                                       inet_ntoa(
-                                                                               rd_ip.ip),
-                                                                       rd_ip.val);
-                                                       vty_out(vty, "\n\n");
+                                                               "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
+                                                       vty_out(vty,
+                                                               "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
+                                                       vty_out(vty, V4_HEADER);
                                                }
-                                               rd_header = 0;
                                        }
-                                       if (use_json)
-                                               json_array =
-                                                       json_object_new_array();
-                                       else
-                                               json_array = NULL;
-                                       if (option == SHOW_DISPLAY_TAGS)
-                                               route_vty_out_tag(
-                                                       vty, &rm->p, ri, 0,
-                                                       SAFI_EVPN, json_array);
-                                       else if (option == SHOW_DISPLAY_OVERLAY)
-                                               route_vty_out_overlay(
-                                                       vty, &rm->p, ri, 0,
-                                                       json_array);
-                                       else
-                                               route_vty_out(vty, &rm->p, ri,
-                                                             0, SAFI_EVPN,
-                                                             json_array);
-                                       output_count++;
+                                       header = 0;
                                }
-                       /* XXX json */
-               }
+                               if (rd_header) {
+                                       u_int16_t type;
+                                       struct rd_as rd_as;
+                                       struct rd_ip rd_ip;
+                                       u_char *pnt;
+
+                                       pnt = rn->p.u.val;
+
+                                       /* Decode RD type. */
+                                       type = decode_rd_type(pnt);
+                                       /* Decode RD value. */
+                                       if (type == RD_TYPE_AS)
+                                               decode_rd_as(pnt + 2, &rd_as);
+                                       else if (type == RD_TYPE_AS4)
+                                               decode_rd_as4(pnt + 2, &rd_as);
+                                       else if (type == RD_TYPE_IP)
+                                               decode_rd_ip(pnt + 2, &rd_ip);
+                                       if (use_json) {
+                                               char buffer[BUFSIZ];
+                                               if (type == RD_TYPE_AS
+                                                   || type == RD_TYPE_AS4)
+                                                       sprintf(buffer, "%u:%d",
+                                                               rd_as.as,
+                                                               rd_as.val);
+                                               else if (type == RD_TYPE_IP)
+                                                       sprintf(buffer, "%s:%d",
+                                                               inet_ntoa(
+                                                                       rd_ip.ip),
+                                                               rd_ip.val);
+                                               json_object_string_add(
+                                                       json_nroute,
+                                                       "routeDistinguisher",
+                                                       buffer);
+                                       } else {
+                                               vty_out(vty,
+                                                       "Route Distinguisher: ");
+                                               if (type == RD_TYPE_AS)
+                                                       vty_out(vty,
+                                                               "as2 %u:%d",
+                                                               rd_as.as,
+                                                               rd_as.val);
+                                               else if (type == RD_TYPE_AS4)
+                                                       vty_out(vty,
+                                                               "as4 %u:%d",
+                                                               rd_as.as,
+                                                               rd_as.val);
+                                               else if (type == RD_TYPE_IP)
+                                                       vty_out(vty, "ip %s:%d",
+                                                               inet_ntoa(
+                                                                       rd_ip.ip),
+                                                               rd_ip.val);
+                                               vty_out(vty, "\n\n");
+                                       }
+                                       rd_header = 0;
+                               }
+                               if (use_json)
+                                       json_array = json_object_new_array();
+                               else
+                                       json_array = NULL;
+                               if (option == SHOW_DISPLAY_TAGS)
+                                       route_vty_out_tag(vty, &rm->p, ri, 0,
+                                                         SAFI_EVPN,
+                                                         json_array);
+                               else if (option == SHOW_DISPLAY_OVERLAY)
+                                       route_vty_out_overlay(vty, &rm->p, ri,
+                                                             0, json_array);
+                               else
+                                       route_vty_out(vty, &rm->p, ri, 0,
+                                                     SAFI_EVPN, json_array);
+                               output_count++;
+                       }
+               /* XXX json */
        }
        if (output_count == 0)
                vty_out(vty, "No prefixes displayed, %ld exist\n", total_count);
@@ -1281,19 +1466,25 @@ static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
 /*
  * Display import RT mapping to VNIs (vty handler)
  */
-static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp)
+static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
+                                json_object *json)
 {
+       void *args[2];
+
+       args[0] = vty;
+       args[1] = json;
+
        hash_iterate(
                bgp->import_rt_hash,
                (void (*)(struct hash_backet *, void *))show_import_rt_entry,
-               vty);
+               args);
 }
 
 /*
  * Display EVPN routes for all VNIs - vty handler.
  */
 static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
-                                    struct in_addr vtep_ip)
+                                    struct in_addr vtep_ip, json_object *json)
 {
        u_int32_t num_vnis;
        struct vni_walk_ctx wctx;
@@ -1305,6 +1496,7 @@ static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
        wctx.bgp = bgp;
        wctx.vty = vty;
        wctx.vtep_ip = vtep_ip;
+       wctx.json = json;
        hash_iterate(bgp->vnihash, (void (*)(struct hash_backet *,
                                             void *))show_vni_routes_hash,
                     &wctx);
@@ -1314,7 +1506,8 @@ static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
  * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
  */
 static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
-                                         vni_t vni, struct in_addr orig_ip)
+                                         vni_t vni, struct in_addr orig_ip,
+                                         json_object *json)
 {
        struct bgpevpn *vpn;
        struct prefix_evpn p;
@@ -1323,6 +1516,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
        u_int32_t path_cnt = 0;
        afi_t afi;
        safi_t safi;
+       json_object *json_paths = NULL;
 
        afi = AFI_L2VPN;
        safi = SAFI_EVPN;
@@ -1338,20 +1532,42 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
        build_evpn_type3_prefix(&p, orig_ip);
        rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
        if (!rn || !rn->info) {
-               vty_out(vty, "%% Network not in table\n");
+               if (!json)
+                       vty_out(vty, "%% Network not in table\n");
                return;
        }
 
+       if (json)
+               json_paths = json_object_new_array();
+
        /* Prefix and num paths displayed once per prefix. */
-       route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, NULL);
+       route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
 
        /* Display each path for this prefix. */
        for (ri = rn->info; ri; ri = ri->next) {
-               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, NULL);
+               json_object *json_path = NULL;
+
+               if (json)
+                       json_path = json_object_new_array();
+
+               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
+                                    json_path);
+
+               if (json)
+                       json_object_array_add(json_paths, json_path);
+
                path_cnt++;
        }
 
-       vty_out(vty, "\nDisplayed %u paths for requested prefix\n", path_cnt);
+       if (json) {
+               if (path_cnt)
+                       json_object_object_add(json, "paths", json_paths);
+
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
+                       path_cnt);
+       }
 }
 
 /*
@@ -1360,7 +1576,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
  */
 static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
                                      vni_t vni, struct ethaddr *mac,
-                                     struct ipaddr *ip)
+                                     struct ipaddr *ip, json_object *json)
 {
        struct bgpevpn *vpn;
        struct prefix_evpn p;
@@ -1369,6 +1585,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
        u_int32_t path_cnt = 0;
        afi_t afi;
        safi_t safi;
+       json_object *json_paths = NULL;
 
        afi = AFI_L2VPN;
        safi = SAFI_EVPN;
@@ -1376,7 +1593,8 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
        /* Locate VNI. */
        vpn = bgp_evpn_lookup_vni(bgp, vni);
        if (!vpn) {
-               vty_out(vty, "VNI not found\n");
+               if (!json)
+                       vty_out(vty, "VNI not found\n");
                return;
        }
 
@@ -1384,20 +1602,42 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
        build_evpn_type2_prefix(&p, mac, ip);
        rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
        if (!rn || !rn->info) {
-               vty_out(vty, "%% Network not in table\n");
+               if (!json)
+                       vty_out(vty, "%% Network not in table\n");
                return;
        }
 
+       if (json)
+               json_paths = json_object_new_array();
+
        /* Prefix and num paths displayed once per prefix. */
-       route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, NULL);
+       route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
 
        /* Display each path for this prefix. */
        for (ri = rn->info; ri; ri = ri->next) {
-               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, NULL);
+               json_object *json_path = NULL;
+
+               if (json)
+                       json_path = json_object_new_array();
+
+               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
+                                    json_path);
+
+               if (json)
+                       json_object_array_add(json_paths, json_path);
+
                path_cnt++;
        }
 
-       vty_out(vty, "\nDisplayed %u paths for requested prefix\n", path_cnt);
+       if (json) {
+               if (path_cnt)
+                       json_object_object_add(json, "paths", json_paths);
+
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
+                       path_cnt);
+       }
 }
 
 /*
@@ -1406,19 +1646,21 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
  * If the vtep_ip is non zero, only routes behind that vtep are shown
  */
 static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
-                                int type, struct in_addr vtep_ip)
+                                int type, struct in_addr vtep_ip,
+                                json_object *json)
 {
        struct bgpevpn *vpn;
 
        /* Locate VNI. */
        vpn = bgp_evpn_lookup_vni(bgp, vni);
        if (!vpn) {
-               vty_out(vty, "VNI not found\n");
+               if (!json)
+                       vty_out(vty, "VNI not found\n");
                return;
        }
 
        /* Walk this VNI's route table and display appropriate routes. */
-       show_vni_routes(bgp, vpn, type, vty, vtep_ip);
+       show_vni_routes(bgp, vpn, type, vty, vtep_ip, json);
 }
 
 /*
@@ -1428,7 +1670,7 @@ static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
  */
 static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
                                     struct prefix_rd *prd, struct ethaddr *mac,
-                                    struct ipaddr *ip)
+                                    struct ipaddr *ip, json_object *json)
 {
        struct prefix_evpn p;
        struct bgp_node *rn;
@@ -1436,6 +1678,8 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
        afi_t afi;
        safi_t safi;
        u_int32_t path_cnt = 0;
+       json_object *json_paths = NULL;
+       char prefix_str[BUFSIZ];
 
        afi = AFI_L2VPN;
        safi = SAFI_EVPN;
@@ -1445,20 +1689,44 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
        rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
                                 (struct prefix *)&p, prd);
        if (!rn || !rn->info) {
-               vty_out(vty, "%% Network not in table\n");
+               if (!json)
+                       vty_out(vty, "%% Network not in table\n");
                return;
        }
 
+       bgp_evpn_route2str((struct prefix_evpn *)&p, prefix_str,
+                          sizeof(prefix_str));
+
        /* Prefix and num paths displayed once per prefix. */
-       route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, NULL);
+       route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, json);
+
+       if (json)
+               json_paths = json_object_new_array();
 
        /* Display each path for this prefix. */
        for (ri = rn->info; ri; ri = ri->next) {
-               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, NULL);
+               json_object *json_path = NULL;
+
+               if (json)
+                       json_path = json_object_new_array();
+
+               route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
+                                    json_path);
+
+               if (json)
+                       json_object_array_add(json_paths, json_path);
+
                path_cnt++;
        }
 
-       vty_out(vty, "\nDisplayed %u paths for requested prefix\n", path_cnt);
+       if (json && path_cnt) {
+               if (path_cnt)
+                       json_object_object_add(json, prefix_str, json_paths);
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
+                       path_cnt);
+       }
 }
 
 /*
@@ -1466,7 +1734,8 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
  * If 'type' is non-zero, only routes matching that type are shown.
  */
 static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
-                              struct prefix_rd *prd, int type)
+                              struct prefix_rd *prd, int type,
+                              json_object *json)
 {
        struct bgp_node *rd_rn;
        struct bgp_table *table;
@@ -1476,28 +1745,49 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
        afi_t afi;
        safi_t safi;
        u_int32_t prefix_cnt, path_cnt;
+       char rd_str[RD_ADDRSTRLEN];
+       json_object *json_rd = NULL;
+       int add_rd_to_json = 0;
 
        afi = AFI_L2VPN;
        safi = SAFI_EVPN;
        prefix_cnt = path_cnt = 0;
 
+       prefix_rd2str((struct prefix_rd *)prd, rd_str, sizeof(rd_str));
+
        rd_rn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
        if (!rd_rn)
                return;
+
        table = (struct bgp_table *)rd_rn->info;
        if (table == NULL)
                return;
 
+       if (json) {
+               json_rd = json_object_new_object();
+               json_object_string_add(json_rd, "rd", rd_str);
+       }
+
        /* Display all prefixes with this RD. */
        for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
                struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
+               json_object *json_prefix = NULL;
+               json_object *json_paths = NULL;
+               char prefix_str[BUFSIZ];
+               int add_prefix_to_json = 0;
+
+               bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
+                                  sizeof(prefix_str));
 
                if (type && evp->prefix.route_type != type)
                        continue;
 
+               if (json)
+                       json_prefix = json_object_new_object();
+
                if (rn->info) {
                        /* RD header and legend - once overall. */
-                       if (rd_header) {
+                       if (rd_header && !json) {
                                vty_out(vty,
                                        "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
                                        "[MAC]\n");
@@ -1509,34 +1799,64 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
 
                        /* Prefix and num paths displayed once per prefix. */
                        route_vty_out_detail_header(vty, bgp, rn, prd, afi,
-                                                   safi, NULL);
+                                                   safi, json_prefix);
 
                        prefix_cnt++;
                }
 
+               if (json)
+                       json_paths = json_object_new_array();
+
                /* Display each path for this prefix. */
                for (ri = rn->info; ri; ri = ri->next) {
+                       json_object *json_path = NULL;
+
+                       if (json)
+                               json_path = json_object_new_array();
+
                        route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
-                                            NULL);
+                                            json_path);
+
+                       if (json)
+                               json_object_array_add(json_paths, json_path);
+
                        path_cnt++;
+                       add_prefix_to_json = 1;
+                       add_rd_to_json = 1;
+               }
+
+               if (json && add_prefix_to_json) {
+                       json_object_object_add(json_prefix, "paths",
+                                              json_paths);
+                       json_object_object_add(json_rd, prefix_str,
+                                              json_prefix);
                }
        }
 
-       if (prefix_cnt == 0)
-               vty_out(vty, "No prefixes exist with this RD%s\n",
-                       type ? " (of requested type)" : "");
-       else
-               vty_out(vty,
-                       "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
-                       prefix_cnt, path_cnt,
-                       type ? " (of requested type)" : "");
+       if (json && add_rd_to_json)
+               json_object_object_add(json, rd_str, json_rd);
+
+       if (json) {
+               json_object_int_add(json, "numPrefix", prefix_cnt);
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               if (prefix_cnt == 0)
+                       vty_out(vty, "No prefixes exist with this RD%s\n",
+                               type ? " (of requested type)" : "");
+               else
+                       vty_out(vty,
+                               "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
+                               prefix_cnt, path_cnt,
+                               type ? " (of requested type)" : "");
+       }
 }
 
 /*
  * Display BGP EVPN routing table - all routes (vty handler).
  * If 'type' is non-zero, only routes matching that type are shown.
  */
-static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type)
+static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
+                                json_object *json)
 {
        struct bgp_node *rd_rn;
        struct bgp_table *table;
@@ -1557,15 +1877,36 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type)
         */
        for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
             rd_rn = bgp_route_next(rd_rn)) {
+               char rd_str[RD_ADDRSTRLEN];
+               json_object *json_rd = NULL; /* contains routes for an RD */
+               int add_rd_to_json = 0;
+
                table = (struct bgp_table *)rd_rn->info;
                if (table == NULL)
                        continue;
 
+               prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
+                             sizeof(rd_str));
+
+               if (json) {
+                       json_rd = json_object_new_object();
+                       json_object_string_add(json_rd, "rd", rd_str);
+               }
+
                rd_header = 1;
 
                /* Display all prefixes for an RD */
                for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
+                       json_object *json_prefix =
+                               NULL; /* contains prefix under a RD */
+                       json_object *json_paths =
+                               NULL; /* array of paths under a prefix*/
                        struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
+                       char prefix_str[BUFSIZ];
+                       int add_prefix_to_json = 0;
+
+                       bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
+                                          prefix_str, sizeof(prefix_str));
 
                        if (type && evp->prefix.route_type != type)
                                continue;
@@ -1573,74 +1914,126 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type)
                        if (rn->info) {
                                /* Overall header/legend displayed once. */
                                if (header) {
-                                       bgp_evpn_show_route_header(vty, bgp);
+                                       bgp_evpn_show_route_header(vty, bgp,
+                                                                  json);
                                        header = 0;
                                }
 
                                /* RD header - per RD. */
                                if (rd_header) {
-                                       bgp_evpn_show_route_rd_header(vty,
-                                                                     rd_rn);
+                                       bgp_evpn_show_route_rd_header(
+                                               vty, rd_rn, json);
                                        rd_header = 0;
                                }
 
                                prefix_cnt++;
                        }
 
+                       if (json) {
+                               json_prefix = json_object_new_object();
+                               json_paths = json_object_new_array();
+                               json_object_string_add(json_prefix, "prefix",
+                                                      prefix_str);
+                               json_object_int_add(json_prefix, "prefixLen",
+                                                   rn->p.prefixlen);
+                       }
+
                        /* For EVPN, the prefix is displayed for each path (to
                         * fit in
                         * with code that already exists).
                         */
                        for (ri = rn->info; ri; ri = ri->next) {
+                               json_object *json_path = NULL;
                                path_cnt++;
+                               add_prefix_to_json = 1;
+                               add_rd_to_json = 1;
+
+                               if (json)
+                                       json_path = json_object_new_array();
+
                                route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN,
-                                             NULL);
+                                             json_path);
+
+                               if (json)
+                                       json_object_array_add(json_paths,
+                                                             json_path);
+                       }
+
+                       if (json && add_prefix_to_json) {
+                               json_object_object_add(json_prefix, "paths",
+                                                      json_paths);
+                               json_object_object_add(json_rd, prefix_str,
+                                                      json_prefix);
                        }
                }
+
+               if (json && add_rd_to_json)
+                       json_object_object_add(json, rd_str, json_rd);
        }
 
-       if (prefix_cnt == 0)
-               vty_out(vty, "No EVPN prefixes %sexist\n",
-                       type ? "(of requested type) " : "");
-       else
-               vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
-                       prefix_cnt, path_cnt,
-                       type ? " (of requested type)" : "");
+       if (json) {
+               json_object_int_add(json, "numPrefix", prefix_cnt);
+               json_object_int_add(json, "numPaths", path_cnt);
+       } else {
+               if (prefix_cnt == 0) {
+                       vty_out(vty, "No EVPN prefixes %sexist\n",
+                               type ? "(of requested type) " : "");
+               } else {
+                       vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
+                               prefix_cnt, path_cnt,
+                               type ? " (of requested type)" : "");
+               }
+       }
 }
 
 /*
  * Display specified VNI (vty handler)
  */
-static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni)
+static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
+                         json_object *json)
 {
        struct bgpevpn *vpn;
 
        vpn = bgp_evpn_lookup_vni(bgp, vni);
        if (!vpn) {
-               vty_out(vty, "VNI not found\n");
-               return;
+               if (json) {
+                       vty_out(vty, "{}\n");
+               } else {
+                       vty_out(vty, "VNI not found\n");
+                       return;
+               }
        }
 
-       display_vni(vty, vpn);
+       display_vni(vty, vpn, json);
 }
 
 /*
  * Display a VNI (upon user query).
  */
-static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp)
+static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
+                              json_object *json)
 {
        u_int32_t num_vnis;
+       void *args[2];
 
        num_vnis = hashcount(bgp->vnihash);
        if (!num_vnis)
                return;
-       vty_out(vty, "Number of VNIs: %u\n", num_vnis);
-       vty_out(vty, "Flags: * - Kernel \n");
-       vty_out(vty, "  %-10s %-15s %-21s %-25s %-25s\n", "VNI", "Orig IP",
-               "RD", "Import RT", "Export RT");
+
+       if (json) {
+               json_object_int_add(json, "numVnis", num_vnis);
+       } else {
+               vty_out(vty, "Number of VNIs: %u\n", num_vnis);
+               vty_out(vty, "Flags: * - Kernel\n");
+               vty_out(vty, "  %-10s %-15s %-21s %-25s %-25s\n", "VNI",
+                       "Orig IP", "RD", "Import RT", "Export RT");
+       }
+
+       args[0] = vty;
+       args[1] = json;
        hash_iterate(bgp->vnihash,
                     (void (*)(struct hash_backet *, void *))show_vni_entry,
-                    vty);
+                    args);
 }
 
 /*
@@ -1709,17 +2102,14 @@ static void evpn_unset_advertise_all_vni(struct bgp *bgp)
 }
 #endif /* HAVE_CUMULUS */
 
-static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write)
+static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
 {
        char buf1[INET6_ADDRSTRLEN];
-       afi_t afi = AFI_L2VPN;
-       safi_t safi = SAFI_EVPN;
        char *ecom_str;
        struct listnode *node, *nnode;
        struct ecommunity *ecom;
 
        if (is_vni_configured(vpn)) {
-               bgp_config_write_family_header(vty, afi, safi, write);
                vty_out(vty, "  vni %d\n", vpn->vni);
                if (is_rd_configured(vpn))
                        vty_out(vty, "   rd %s\n",
@@ -1755,10 +2145,10 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write)
 }
 
 static void write_vni_config_for_entry(struct hash_backet *backet,
-                                      struct evpn_config_write *cfg)
+                                      struct vty *vty)
 {
        struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
-       write_vni_config(cfg->vty, vpn, &cfg->write);
+       write_vni_config(vty, vpn);
 }
 
 #if defined(HAVE_CUMULUS)
@@ -1863,19 +2253,24 @@ DEFUN (no_bgp_evpn_advertise_all_vni,
 /*
  * Display VNI information - for all or a specific VNI
  */
-DEFUN (show_bgp_l2vpn_evpn_vni,
-       show_bgp_l2vpn_evpn_vni_cmd,
-       "show bgp l2vpn evpn vni [(1-16777215)]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "Show VNI\n"
-       "VNI number\n")
+DEFUN(show_bgp_l2vpn_evpn_vni,
+      show_bgp_l2vpn_evpn_vni_cmd,
+      "show bgp l2vpn evpn vni [(1-16777215)] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "Show VNI\n"
+      "VNI number\n"
+      JSON_STR)
 {
        struct bgp *bgp;
        vni_t vni;
        int idx = 0;
+       u_char uj = 0;
+       json_object *json = NULL;
+
+       uj = use_json(argc, argv);
 
        bgp = bgp_get_default();
        if (!bgp)
@@ -1884,18 +2279,46 @@ DEFUN (show_bgp_l2vpn_evpn_vni,
        if (!argv_find(argv, argc, "evpn", &idx))
                return CMD_WARNING;
 
-       if (argc == ((idx + 1) + 1)) {
-               vty_out(vty, "Advertise gateway macip flag: %s\n",
-                       bgp->advertise_gw_macip ? "Enabled" : "Disabled");
+       if (uj)
+               json = json_object_new_object();
 
-               /* Display all VNIs */
-               vty_out(vty, "Advertise All VNI flag: %s\n",
-                       bgp->advertise_all_vni ? "Enabled" : "Disabled");
-               evpn_show_all_vnis(vty, bgp);
+       if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
+               if (uj) {
+                       json_object_string_add(json, "advertiseGatewayMacip",
+                                              bgp->advertise_gw_macip
+                                                      ? "Enabled"
+                                                      : "Disabled");
+                       json_object_string_add(json, "advertiseAllVnis",
+                                              bgp->advertise_all_vni
+                                                      ? "Enabled"
+                                                      : "Disabled");
+               } else {
+                       vty_out(vty, "Advertise Gateway Macip: %s\n",
+                               bgp->advertise_gw_macip ? "Enabled"
+                                                       : "Disabled");
+
+                       /* Display all VNIs */
+                       vty_out(vty, "Advertise All VNI flag: %s\n",
+                               bgp->advertise_all_vni ? "Enabled"
+                                                      : "Disabled");
+               }
+
+               evpn_show_all_vnis(vty, bgp, json);
        } else {
+               int vni_idx = 0;
+
+               if (!argv_find(argv, argc, "vni", &vni_idx))
+                       return CMD_WARNING;
+
                /* Display specific VNI */
-               vni = strtoul(argv[argc - 1]->arg, NULL, 10);
-               evpn_show_vni(vty, bgp, vni);
+               vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
+               evpn_show_vni(vty, bgp, vni, json);
+       }
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
        }
 
        return CMD_SUCCESS;
@@ -1904,15 +2327,15 @@ DEFUN (show_bgp_l2vpn_evpn_vni,
 /*
  * Display EVPN neighbor summary.
  */
-DEFUN (show_bgp_l2vpn_evpn_summary,
-       show_bgp_l2vpn_evpn_summary_cmd,
-       "show bgp l2vpn evpn summary [json]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "Summary of BGP neighbor status\n"
-       JSON_STR)
+DEFUN(show_bgp_l2vpn_evpn_summary,
+      show_bgp_l2vpn_evpn_summary_cmd,
+      "show bgp l2vpn evpn summary [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "Summary of BGP neighbor status\n"
+      JSON_STR)
 {
        u_char uj = use_json(argc, argv);
        return bgp_show_summary_vty(vty, NULL, AFI_L2VPN, SAFI_EVPN, uj);
@@ -1921,176 +2344,238 @@ DEFUN (show_bgp_l2vpn_evpn_summary,
 /*
  * Display global EVPN routing table.
  */
-DEFUN (show_bgp_l2vpn_evpn_route,
-       show_bgp_l2vpn_evpn_route_cmd,
-       "show bgp l2vpn evpn route [type <macip|multicast>]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "Specify Route type\n"
-       "MAC-IP (Type-2) route\n"
-       "Multicast (Type-3) route\n")
+DEFUN(show_bgp_l2vpn_evpn_route,
+      show_bgp_l2vpn_evpn_route_cmd,
+      "show bgp l2vpn evpn route [type <macip|multicast>] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "Specify Route type\n"
+      "MAC-IP (Type-2) route\n"
+      "Multicast (Type-3) route\n"
+      JSON_STR)
 {
        struct bgp *bgp;
-       int idx = 0;
+       int type_idx;
        int type = 0;
+       u_char uj = 0;
+       json_object *json = NULL;
+
+       uj = use_json(argc, argv);
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
-       if (!argv_find(argv, argc, "evpn", &idx))
-               return CMD_WARNING;
+       if (uj)
+               json = json_object_new_object();
 
-       if (argc == ((idx + 1) + 3)) {
+       /* get the type */
+       if (argv_find(argv, argc, "type", &type_idx)) {
                /* Specific type is requested */
-               if (strncmp(argv[argc - 1]->arg, "ma", 2) == 0)
+               if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
                        type = BGP_EVPN_MAC_IP_ROUTE;
-               else if (strncmp(argv[argc - 1]->arg, "mu", 2) == 0)
+               else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
                        type = BGP_EVPN_IMET_ROUTE;
                else
                        return CMD_WARNING;
        }
 
-       evpn_show_all_routes(vty, bgp, type);
+       evpn_show_all_routes(vty, bgp, type, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display global EVPN routing table for specific RD.
  */
-DEFUN (show_bgp_l2vpn_evpn_route_rd,
-       show_bgp_l2vpn_evpn_route_rd_cmd,
-       "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "Route Distinguisher\n"
-       "ASN:XX or A.B.C.D:XX\n"
-       "Specify Route type\n"
-       "MAC-IP (Type-2) route\n"
-       "Multicast (Type-3) route\n")
+DEFUN(show_bgp_l2vpn_evpn_route_rd,
+      show_bgp_l2vpn_evpn_route_rd_cmd,
+      "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "Route Distinguisher\n"
+      "ASN:XX or A.B.C.D:XX\n"
+      "Specify Route type\n"
+      "MAC-IP (Type-2) route\n"
+      "Multicast (Type-3) route\n"
+      JSON_STR)
 {
        struct bgp *bgp;
        int ret;
        struct prefix_rd prd;
-       int idx = 0;
        int type = 0;
+       int rd_idx = 0;
+       int type_idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
-       if (!argv_find(argv, argc, "evpn", &idx))
-               return CMD_WARNING;
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
 
-       ret = str2prefix_rd(argv[idx + 3]->arg, &prd);
-       if (!ret) {
-               vty_out(vty, "%% Malformed Route Distinguisher\n");
-               return CMD_WARNING;
+       /* get the RD */
+       if (argv_find(argv, argc, "rd", &rd_idx)) {
+               ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
+
+               if (!ret) {
+                       vty_out(vty, "%% Malformed Route Distinguisher\n");
+                       return CMD_WARNING;
+               }
        }
 
-       if (argc == ((idx + 1) + 5)) {
+       /* get the type */
+       if (argv_find(argv, argc, "type", &type_idx)) {
                /* Specific type is requested */
-               if (strncmp(argv[argc - 1]->arg, "ma", 2) == 0)
+               if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
                        type = BGP_EVPN_MAC_IP_ROUTE;
-               else if (strncmp(argv[argc - 1]->arg, "mu", 2) == 0)
+               else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
                        type = BGP_EVPN_IMET_ROUTE;
                else
                        return CMD_WARNING;
        }
 
-       evpn_show_route_rd(vty, bgp, &prd, type);
+       evpn_show_route_rd(vty, bgp, &prd, type, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display global EVPN routing table for specific RD and MACIP.
  */
-DEFUN (show_bgp_l2vpn_evpn_route_rd_macip,
-       show_bgp_l2vpn_evpn_route_rd_macip_cmd,
-       "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "Route Distinguisher\n"
-       "ASN:XX or A.B.C.D:XX\n"
-       "MAC\n"
-       "MAC address (e.g., 00:e0:ec:20:12:62)\n"
-       "IP\n"
-       "IP address (IPv4 or IPv6)\n")
+DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
+      show_bgp_l2vpn_evpn_route_rd_macip_cmd,
+      "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "Route Distinguisher\n"
+      "ASN:XX or A.B.C.D:XX\n"
+      "MAC\n"
+      "MAC address (e.g., 00:e0:ec:20:12:62)\n"
+      "IP\n"
+      "IP address (IPv4 or IPv6)\n"
+      JSON_STR)
 {
        struct bgp *bgp;
        int ret;
        struct prefix_rd prd;
        struct ethaddr mac;
        struct ipaddr ip;
-       int idx = 0;
+       int rd_idx = 0;
+       int mac_idx = 0;
+       int ip_idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
+
+       memset(&mac, 0, sizeof(struct ethaddr));
+       memset(&ip, 0, sizeof(struct ipaddr));
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
-       if (!argv_find(argv, argc, "evpn", &idx))
-               return CMD_WARNING;
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
 
-       ret = str2prefix_rd(argv[idx + 3]->arg, &prd);
-       if (!ret) {
-               vty_out(vty, "%% Malformed Route Distinguisher\n");
-               return CMD_WARNING;
+       /* get the prd */
+       if (argv_find(argv, argc, "rd", &rd_idx)) {
+               ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
+               if (!ret) {
+                       vty_out(vty, "%% Malformed Route Distinguisher\n");
+                       return CMD_WARNING;
+               }
        }
-       if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
-               vty_out(vty, "%% Malformed MAC address\n");
-               return CMD_WARNING;
+
+       /* get the mac */
+       if (argv_find(argv, argc, "mac", &mac_idx)) {
+               if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
+                       vty_out(vty, "%% Malformed MAC address\n");
+                       return CMD_WARNING;
+               }
        }
-       memset(&ip, 0, sizeof(ip));
-       if (argc == (idx + 1 + 7) && argv[argc - 1]->arg != NULL) {
-               /* Specific MAC+IP requested */
-               if (str2ipaddr(argv[argc - 1]->arg, &ip) != 0) {
+
+       /* get the ip if specified */
+       if (argv_find(argv, argc, "ip", &ip_idx)) {
+               if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
                        vty_out(vty, "%% Malformed IP address\n");
                        return CMD_WARNING;
                }
        }
 
-       evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip);
+       evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display per-VNI EVPN routing table.
  */
-DEFUN (show_bgp_l2vpn_evpn_route_vni,
-       show_bgp_l2vpn_evpn_route_vni_cmd,
-       "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "VXLAN Network Identifier\n"
-       "VNI number\n"
-       "Specify Route type\n"
-       "MAC-IP (Type-2) route\n"
-       "Multicast (Type-3) route\n"
-       "Remote VTEP\n"
-       "Remote VTEP IP address\n")
+DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
+      "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "VXLAN Network Identifier\n"
+      "VNI number\n"
+      "Specify Route type\n"
+      "MAC-IP (Type-2) route\n"
+      "Multicast (Type-3) route\n"
+      "Remote VTEP\n"
+      "Remote VTEP IP address\n"
+      JSON_STR)
 {
        vni_t vni;
        struct bgp *bgp;
        struct in_addr vtep_ip;
        int type = 0;
        int idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
        if (!argv_find(argv, argc, "evpn", &idx))
                return CMD_WARNING;
 
@@ -2098,7 +2583,8 @@ DEFUN (show_bgp_l2vpn_evpn_route_vni,
 
        vni = strtoul(argv[idx + 3]->arg, NULL, 10);
 
-       if (argc == (idx + 1 + 5) && argv[idx + 4]->arg) {
+       if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
+           || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
                if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
                        if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
                                type = BGP_EVPN_MAC_IP_ROUTE;
@@ -2115,156 +2601,233 @@ DEFUN (show_bgp_l2vpn_evpn_route_vni,
                        return CMD_WARNING;
        }
 
-       evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip);
+       evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display per-VNI EVPN routing table for specific MACIP.
  */
-DEFUN (show_bgp_l2vpn_evpn_route_vni_macip,
-       show_bgp_l2vpn_evpn_route_vni_macip_cmd,
-       "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "VXLAN Network Identifier\n"
-       "VNI number\n"
-       "MAC\n"
-       "MAC address (e.g., 00:e0:ec:20:12:62)\n"
-       "IP\n"
-       "IP address (IPv4 or IPv6)\n")
+DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
+      show_bgp_l2vpn_evpn_route_vni_macip_cmd,
+      "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "VXLAN Network Identifier\n"
+      "VNI number\n"
+      "MAC\n"
+      "MAC address (e.g., 00:e0:ec:20:12:62)\n"
+      "IP\n"
+      "IP address (IPv4 or IPv6)\n"
+      JSON_STR)
 {
        vni_t vni;
        struct bgp *bgp;
        struct ethaddr mac;
        struct ipaddr ip;
        int idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
        if (!argv_find(argv, argc, "evpn", &idx))
                return CMD_WARNING;
 
+       /* get the VNI */
        vni = strtoul(argv[idx + 3]->arg, NULL, 10);
+
+       /* get the mac */
        if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
                vty_out(vty, "%% Malformed MAC address\n");
                return CMD_WARNING;
        }
+
+       /* get the ip */
        memset(&ip, 0, sizeof(ip));
-       if (argc == (idx + 1 + 7) && argv[idx + 7]->arg != NULL) {
+       if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
+           || (uj
+               && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
                if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
                        vty_out(vty, "%% Malformed IP address\n");
                        return CMD_WARNING;
                }
        }
 
-       evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip);
+       evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
  */
-DEFUN (show_bgp_l2vpn_evpn_route_vni_multicast,
-       show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
-       "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "VXLAN Network Identifier\n"
-       "VNI number\n"
-       "Multicast (Type-3) route\n"
-       "Originating Router IP address\n")
+DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
+      show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
+      "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "VXLAN Network Identifier\n"
+      "VNI number\n"
+      "Multicast (Type-3) route\n"
+      "Originating Router IP address\n"
+      JSON_STR)
 {
        vni_t vni;
        struct bgp *bgp;
        int ret;
        struct in_addr orig_ip;
        int idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
        if (!argv_find(argv, argc, "evpn", &idx))
                return CMD_WARNING;
 
+       /* get the VNI */
        vni = strtoul(argv[idx + 3]->arg, NULL, 10);
+
+       /* get the ip */
        ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
        if (!ret) {
                vty_out(vty, "%% Malformed Originating Router IP address\n");
                return CMD_WARNING;
        }
 
-       evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip);
+       evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display per-VNI EVPN routing table - for all VNIs.
  */
-DEFUN (show_bgp_l2vpn_evpn_route_vni_all,
-       show_bgp_l2vpn_evpn_route_vni_all_cmd,
-       "show bgp l2vpn evpn route vni all [vtep A.B.C.D]",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "EVPN route information\n"
-       "VXLAN Network Identifier\n"
-       "All VNIs\n"
-       "Remote VTEP\n"
-       "Remote VTEP IP address\n")
+DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
+      show_bgp_l2vpn_evpn_route_vni_all_cmd,
+      "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "EVPN route information\n"
+      "VXLAN Network Identifier\n"
+      "All VNIs\n"
+      "Remote VTEP\n"
+      "Remote VTEP IP address\n"
+      JSON_STR)
 {
        struct bgp *bgp;
        struct in_addr vtep_ip;
        int idx = 0;
+       int uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
+       /* check if we need json output */
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
        if (!argv_find(argv, argc, "evpn", &idx))
                return CMD_WARNING;
 
        vtep_ip.s_addr = 0;
-       if (argc == (idx + 1 + 5) && argv[idx + 5]->arg) {
+       if ((!uj && (argc == (idx + 1 + 5) && argv[idx + 5]->arg))
+           || (uj && (argc == (idx + 1 + 6) && argv[idx + 5]->arg))) {
                if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
                        vty_out(vty, "%% Malformed VTEP IP address\n");
                        return CMD_WARNING;
                }
        }
 
-       evpn_show_routes_vni_all(vty, bgp, vtep_ip);
+       evpn_show_routes_vni_all(vty, bgp, vtep_ip, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
 /*
  * Display EVPN import route-target hash table
  */
-DEFUN (show_bgp_l2vpn_evpn_import_rt,
-       show_bgp_l2vpn_evpn_import_rt_cmd,
-       "show bgp l2vpn evpn import-rt",
-       SHOW_STR
-       BGP_STR
-       L2VPN_HELP_STR
-       EVPN_HELP_STR
-       "Show import route target\n")
+DEFUN(show_bgp_l2vpn_evpn_import_rt,
+      show_bgp_l2vpn_evpn_import_rt_cmd,
+      "show bgp l2vpn evpn import-rt [json]",
+      SHOW_STR
+      BGP_STR
+      L2VPN_HELP_STR
+      EVPN_HELP_STR
+      "Show import route target\n"
+      JSON_STR)
 {
        struct bgp *bgp;
+       u_char uj = 0;
+       json_object *json = NULL;
 
        bgp = bgp_get_default();
        if (!bgp)
                return CMD_WARNING;
 
-       evpn_show_import_rts(vty, bgp);
+       uj = use_json(argc, argv);
+       if (uj)
+               json = json_object_new_object();
+
+       evpn_show_import_rts(vty, bgp, json);
+
+       if (uj) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+
        return CMD_SUCCESS;
 }
 
@@ -2741,29 +3304,19 @@ DEFUN (no_bgp_evpn_vni_rt_without_val,
  * Output EVPN configuration information.
  */
 void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
-                               safi_t safi, int *write)
+                               safi_t safi)
 {
-       struct evpn_config_write cfg;
-
-       if (bgp->vnihash) {
-               cfg.write = *write;
-               cfg.vty = vty;
+       if (bgp->vnihash)
                hash_iterate(bgp->vnihash,
                             (void (*)(struct hash_backet *,
                                       void *))write_vni_config_for_entry,
-                            &cfg);
-               *write = cfg.write;
-       }
+                            vty);
 
-       if (bgp->advertise_all_vni) {
-               bgp_config_write_family_header(vty, afi, safi, write);
+       if (bgp->advertise_all_vni)
                vty_out(vty, "  advertise-all-vni\n");
-       }
 
-       if (bgp->advertise_gw_macip) {
-               bgp_config_write_family_header(vty, afi, safi, write);
+       if (bgp->advertise_gw_macip)
                vty_out(vty, "  advertise-default-gw\n");
-       }
 }
 
 void bgp_ethernetvpn_init(void)
index 3bc24593f4982c6f0363f4bbb752861c1503b832..4d07f7d038ffb16c84bd37909137b7a4067b5f97 100644 (file)
@@ -22,7 +22,7 @@
 #define _FRR_BGP_EVPN_VTY_H
 
 extern void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp,
-                                      afi_t afi, safi_t safi, int *write);
+                                      afi_t afi, safi_t safi);
 extern void bgp_ethernetvpn_init(void);
 
 #define L2VPN_HELP_STR        "Layer 2 Virtual Private Network\n"
index 3df40fa87a1fcb5237a273033fc8d3c09ab4d64b..37054ce4258360d01af93b8a5266947da7ba31c2 100644 (file)
@@ -101,6 +101,7 @@ DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array")
 DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp")
 DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate")
 DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address")
+DEFINE_MTYPE(BGPD, TIP_ADDR, "BGP own tunnel-ip address")
 
 DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution")
 DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information")
index 152cfaeaf220cc5ed8efd146e22f350b5cdf7fdd..35b83a040153e003d8baaf62a0c5773914dc0d97 100644 (file)
@@ -97,6 +97,7 @@ DECLARE_MTYPE(BGP_DAMP_ARRAY)
 DECLARE_MTYPE(BGP_REGEXP)
 DECLARE_MTYPE(BGP_AGGREGATE)
 DECLARE_MTYPE(BGP_ADDR)
+DECLARE_MTYPE(TIP_ADDR)
 
 DECLARE_MTYPE(BGP_REDIST)
 DECLARE_MTYPE(BGP_FILTER_NAME)
index 63a84684bbdf9b4cd012aea57c19061d644e3caf..b7d7cd9fa308cd10de32ab2ef7009dbfba92b91b 100644 (file)
@@ -88,11 +88,86 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table)
                }
 }
 
-/* BGP own address structure */
-struct bgp_addr {
-       struct in_addr addr;
-       int refcnt;
-};
+static void *bgp_tip_hash_alloc(void *p)
+{
+       const struct in_addr *val = (const struct in_addr *)p;
+       struct tip_addr *addr;
+
+       addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
+       addr->refcnt = 0;
+       addr->addr.s_addr = val->s_addr;
+
+       return addr;
+}
+
+static void bgp_tip_hash_free(void *addr)
+{
+       XFREE(MTYPE_TIP_ADDR, addr);
+}
+
+static unsigned int bgp_tip_hash_key_make(void *p)
+{
+       const struct tip_addr *addr = p;
+
+       return jhash_1word(addr->addr.s_addr, 0);
+}
+
+static int bgp_tip_hash_cmp(const void *p1, const void *p2)
+{
+       const struct tip_addr *addr1 = p1;
+       const struct tip_addr *addr2 = p2;
+
+       return addr1->addr.s_addr == addr2->addr.s_addr;
+}
+
+void bgp_tip_hash_init(struct bgp *bgp)
+{
+       bgp->tip_hash =
+               hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp, NULL);
+}
+
+void bgp_tip_hash_destroy(struct bgp *bgp)
+{
+       if (bgp->tip_hash == NULL)
+               return;
+       hash_clean(bgp->tip_hash, bgp_tip_hash_free);
+       hash_free(bgp->tip_hash);
+       bgp->tip_hash = NULL;
+}
+
+void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
+{
+       struct tip_addr tmp;
+       struct tip_addr *addr;
+
+       tmp.addr = *tip;
+
+       addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
+       if (!addr)
+               return;
+
+       addr->refcnt++;
+}
+
+void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
+{
+       struct tip_addr tmp;
+       struct tip_addr *addr;
+
+       tmp.addr = *tip;
+
+       addr = hash_lookup(bgp->tip_hash, &tmp);
+       /* may have been deleted earlier by bgp_interface_down() */
+       if (addr == NULL)
+               return;
+
+       addr->refcnt--;
+
+       if (addr->refcnt == 0) {
+               hash_release(bgp->tip_hash, addr);
+               XFREE(MTYPE_TIP_ADDR, addr);
+       }
+}
 
 static void *bgp_address_hash_alloc(void *p)
 {
@@ -304,6 +379,7 @@ void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
 int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
 {
        struct bgp_addr tmp, *addr;
+       struct tip_addr tmp_tip, *tip;
 
        tmp.addr = nh_addr;
 
@@ -311,6 +387,11 @@ int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
        if (addr)
                return 1;
 
+       tmp_tip.addr = nh_addr;
+       tip = hash_lookup(bgp->tip_hash, &tmp_tip);
+       if (tip)
+               return 1;
+
        return 0;
 }
 
index 37dad577c2666627f19e975b74ddb36776fd7a7b..b482778fdfd427bb7787f3e2f2f99dbb6188994f 100644 (file)
@@ -66,6 +66,18 @@ struct bgp_nexthop_cache {
        struct bgp *bgp;
 };
 
+/* BGP own address structure */
+struct bgp_addr {
+       struct in_addr addr;
+       int refcnt;
+};
+
+/* Own tunnel-ip address structure */
+struct tip_addr {
+       struct in_addr addr;
+       int refcnt;
+};
+
 extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *,
                              int *, int *);
 extern void bgp_connected_add(struct bgp *bgp, struct connected *c);
@@ -82,5 +94,9 @@ extern void bgp_scan_finish(struct bgp *bgp);
 extern void bgp_scan_vty_init(void);
 extern void bgp_address_init(struct bgp *bgp);
 extern void bgp_address_destroy(struct bgp *bgp);
+extern void bgp_tip_add(struct bgp *bgp, struct in_addr *tip);
+extern void bgp_tip_del(struct bgp *bgp, struct in_addr *tip);
+extern void bgp_tip_hash_init(struct bgp *bgp);
+extern void bgp_tip_hash_destroy(struct bgp *bgp);
 
 #endif /* _QUAGGA_BGP_NEXTHOP_H */
index 3a7a60b14d368d97576fc43339f21d743244c63e..a0fc10c745bbb6846f4ef1fd9770aa3339109ee2 100644 (file)
@@ -482,6 +482,34 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
        evaluate_paths(bnc);
 }
 
+/*
+ * Cleanup nexthop registration and status information for BGP nexthops
+ * pertaining to this VRF. This is invoked upon VRF deletion.
+ */
+void bgp_cleanup_nexthops(struct bgp *bgp)
+{
+       afi_t afi;
+       struct bgp_node *rn;
+       struct bgp_nexthop_cache *bnc;
+
+       for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+               if (!bgp->nexthop_cache_table[afi])
+                       continue;
+
+               for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
+                    rn = bgp_route_next(rn)) {
+                       bnc = rn->info;
+                       if (!bnc)
+                               continue;
+
+                       /* Clear relevant flags. */
+                       UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
+                       UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
+                       UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
+               }
+       }
+}
+
 /**
  * make_prefix - make a prefix structure from the path (essentially
  * path's node.
index f649bb225963012dd47456ec0a1fb9d95c23bf68..4b297f410c80f3102ca574883546e61fb8f475a4 100644 (file)
@@ -66,4 +66,10 @@ void bgp_unlink_nexthop_by_peer(struct peer *);
  */
 extern void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer);
 
+/*
+ * Cleanup nexthop registration and status information for BGP nexthops
+ * pertaining to this VRF. This is invoked upon VRF deletion.
+ */
+extern void bgp_cleanup_nexthops(struct bgp *bgp);
+
 #endif /* _BGP_NHT_H */
index 3ee865e3ba114c0ba642952ee3d17e73e7a09429..5c9ba89a5786c5f63e0cf5e306fd536eb9f976e9 100644 (file)
@@ -1271,7 +1271,6 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
        as_t local_as;
        u_int32_t restart_time;
        u_char afi_safi_count = 0;
-       struct utsname names;
        int adv_addpath_tx = 0;
 
        /* Remember current pointer for Opt Parm Len. */
@@ -1441,8 +1440,7 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
        }
 
        /* Hostname capability */
-       uname(&names);
-       if (names.nodename[0] != '\0') {
+       if (cmd_hostname_get()) {
                SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
                stream_putc(s, BGP_OPEN_OPT_CAP);
                rcapp = stream_get_endp(s); /* Ptr to length placeholder */
@@ -1450,26 +1448,21 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
                stream_putc(s, CAPABILITY_CODE_FQDN);
                capp = stream_get_endp(s);
                stream_putc(s, 0); /* dummy len for now */
-               len = strlen(names.nodename);
+               len = strlen(cmd_hostname_get());
                if (len > BGP_MAX_HOSTNAME)
                        len = BGP_MAX_HOSTNAME;
 
                stream_putc(s, len);
-               stream_put(s, names.nodename, len);
-#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME
-               if ((names.domainname[0] != '\0')
-                   && (strcmp(names.domainname, "(none)") != 0)) {
-                       len = strlen(names.domainname);
+               stream_put(s, cmd_hostname_get(), len);
+               if (cmd_domainname_get()) {
+                       len = strlen(cmd_domainname_get());
                        if (len > BGP_MAX_HOSTNAME)
                                len = BGP_MAX_HOSTNAME;
 
                        stream_putc(s, len);
-                       stream_put(s, names.domainname, len);
+                       stream_put(s, cmd_domainname_get(), len);
                } else
-#endif
-               {
                        stream_putc(s, 0); /* 0 length */
-               }
 
                /* Set the lengths straight */
                len = stream_get_endp(s) - rcapp - 1;
@@ -1478,14 +1471,10 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
                stream_putc_at(s, capp, len);
 
                if (bgp_debug_neighbor_events(peer))
-#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME
                        zlog_debug(
                                "%s Sending hostname cap with hn = %s, dn = %s",
-                               peer->host, names.nodename, names.domainname);
-#else
-                       zlog_debug("%s Sending hostname cap with hn = %s",
-                                  peer->host, names.nodename);
-#endif
+                               peer->host, cmd_hostname_get(),
+                               cmd_domainname_get());
        }
 
        /* Sending base graceful-restart capability irrespective of the config
index 288271e5a15cdd570c0b4a286381899bfcfea148..ff88a55c084b33eaf0af0690311df6604e17b740 100644 (file)
@@ -2042,9 +2042,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
 
        /* Do we need to allocate or free labels?
         * Right now, since we only deal with per-prefix labels, it is not
-        * necessary
-        * to do this upon changes to best path except of the label index
-        * changes.
+        * necessary to do this upon changes to best path except if the label
+        * index changes
         */
        if (bgp->allocate_mpls_labels[afi][safi]) {
                if (new_select) {
@@ -2201,18 +2200,22 @@ static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
        struct bgp_process_queue *pqnode = data;
        struct bgp *bgp = pqnode->bgp;
        struct bgp_table *table;
-       struct bgp_node *rn, *nrn;
+       struct bgp_node *rn;
 
        /* eoiu marker */
        if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
                bgp_process_main_one(bgp, NULL, 0, 0);
-
+               /* should always have dedicated wq call */
+               assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
                return WQ_SUCCESS;
        }
 
-       STAILQ_FOREACH_SAFE(rn, &pqnode->pqueue, pq, nrn) {
+       while (!STAILQ_EMPTY(&pqnode->pqueue)) {
+               rn = STAILQ_FIRST(&pqnode->pqueue);
+               STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
+               STAILQ_NEXT(rn, pq) = NULL; /* complete unlink */
                table = bgp_node_table(rn);
-
+               /* note, new RNs may be added as part of processing */
                bgp_process_main_one(bgp, rn, table->afi, table->safi);
 
                bgp_unlock_node(rn);
@@ -2251,8 +2254,7 @@ void bgp_process_queue_init(void)
        bm->process_main_queue->spec.yield = 50 * 1000L;
 }
 
-static struct bgp_process_queue *bgp_process_queue_work(struct work_queue *wq,
-                                                       struct bgp *bgp)
+static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
 {
        struct bgp_process_queue *pqnode;
 
@@ -2262,8 +2264,6 @@ static struct bgp_process_queue *bgp_process_queue_work(struct work_queue *wq,
        pqnode->bgp = bgp_lock(bgp);
        STAILQ_INIT(&pqnode->pqueue);
 
-       work_queue_add(wq, pqnode);
-
        return pqnode;
 }
 
@@ -2272,6 +2272,7 @@ void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
 #define ARBITRARY_PROCESS_QLEN         10000
        struct work_queue *wq = bm->process_main_queue;
        struct bgp_process_queue *pqnode;
+       int pqnode_reuse = 0;
 
        /* already scheduled for processing? */
        if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
@@ -2288,19 +2289,25 @@ void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
 
                if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER) ||
                    pqnode->bgp != bgp || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
-                       pqnode = bgp_process_queue_work(wq, bgp);
+                       pqnode = bgp_processq_alloc(bgp);
+               else
+                       pqnode_reuse = 1;
        } else
-               pqnode = bgp_process_queue_work(wq, bgp);
-
+               pqnode = bgp_processq_alloc(bgp);
        /* all unlocked in bgp_process_wq */
        bgp_table_lock(bgp_node_table(rn));
 
        SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
        bgp_lock_node(rn);
 
+       /* can't be enqueued twice */
+       assert(STAILQ_NEXT(rn, pq) == NULL);
        STAILQ_INSERT_TAIL(&pqnode->pqueue, rn, pq);
        pqnode->queued++;
 
+       if (!pqnode_reuse)
+               work_queue_add(wq, pqnode);
+
        return;
 }
 
@@ -2311,9 +2318,10 @@ void bgp_add_eoiu_mark(struct bgp *bgp)
        if (bm->process_main_queue == NULL)
                return;
 
-       pqnode = bgp_process_queue_work(bm->process_main_queue, bgp);
+       pqnode = bgp_processq_alloc(bgp);
 
        SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
+       work_queue_add(bm->process_main_queue, pqnode);
 }
 
 static int bgp_maximum_prefix_restart_timer(struct thread *thread)
@@ -2425,8 +2433,8 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
 /* Unconditionally remove the route from the RIB, without taking
  * damping into consideration (eg, because the session went down)
  */
-static void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
-                          struct peer *peer, afi_t afi, safi_t safi)
+void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
+                   afi_t afi, safi_t safi)
 {
        bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi);
 
@@ -3391,21 +3399,22 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
 
        for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
                for (ain = rn->adj_in; ain; ain = ain->next) {
-                       if (ain->peer == peer) {
-                               struct bgp_info *ri = rn->info;
-                               mpls_label_t label =
-                                       (ri && ri->extra) ? ri->extra->label
-                                                         : MPLS_INVALID_LABEL;
+                       if (ain->peer != peer)
+                               continue;
 
-                               ret = bgp_update(
-                                       peer, &rn->p, ain->addpath_rx_id,
-                                       ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
-                                       BGP_ROUTE_NORMAL, prd, &label, 1, NULL);
+                       struct bgp_info *ri = rn->info;
+                       mpls_label_t label = (ri && ri->extra)
+                                                    ? ri->extra->label
+                                                    : MPLS_INVALID_LABEL;
 
-                               if (ret < 0) {
-                                       bgp_unlock_node(rn);
-                                       return;
-                               }
+                       ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
+                                        ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
+                                        BGP_ROUTE_NORMAL, prd, &label, 1,
+                                        NULL);
+
+                       if (ret < 0) {
+                               bgp_unlock_node(rn);
+                               return;
                        }
                }
 }
@@ -3454,24 +3463,25 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
        /* It is possible that we have multiple paths for a prefix from a peer
         * if that peer is using AddPath.
         */
-       for (ri = rn->info; ri; ri = ri->next)
-               if (ri->peer == peer) {
-                       /* graceful restart STALE flag set. */
-                       if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
-                           && peer->nsf[afi][safi]
-                           && !CHECK_FLAG(ri->flags, BGP_INFO_STALE)
-                           && !CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
-                               bgp_info_set_flag(rn, ri, BGP_INFO_STALE);
-                       else {
-                               /* If this is an EVPN route, process for
-                                * un-import. */
-                               if (safi == SAFI_EVPN)
-                                       bgp_evpn_unimport_route(peer->bgp, afi,
-                                                               safi, &rn->p,
-                                                               ri);
-                               bgp_rib_remove(rn, ri, peer, afi, safi);
-                       }
+       for (ri = rn->info; ri; ri = ri->next) {
+               if (ri->peer != peer)
+                       continue;
+
+               /* graceful restart STALE flag set. */
+               if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
+                   && peer->nsf[afi][safi]
+                   && !CHECK_FLAG(ri->flags, BGP_INFO_STALE)
+                   && !CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
+                       bgp_info_set_flag(rn, ri, BGP_INFO_STALE);
+               else {
+                       /* If this is an EVPN route, process for
+                        * un-import. */
+                       if (safi == SAFI_EVPN)
+                               bgp_evpn_unimport_route(peer->bgp, afi, safi,
+                                                       &rn->p, ri);
+                       bgp_rib_remove(rn, ri, peer, afi, safi);
                }
+       }
        return WQ_SUCCESS;
 }
 
@@ -3705,34 +3715,33 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
                        struct bgp_info *ri;
 
                        /* look for neighbor in tables */
-                       if ((table = rn->info) != NULL) {
-                               for (rm = bgp_table_top(table); rm;
-                                    rm = bgp_route_next(rm))
-                                       for (ri = rm->info; ri; ri = ri->next)
-                                               if (ri->peer == peer) {
-                                                       if (CHECK_FLAG(
-                                                                   ri->flags,
-                                                                   BGP_INFO_STALE))
-                                                               bgp_rib_remove(
-                                                                       rm, ri,
-                                                                       peer,
-                                                                       afi,
-                                                                       safi);
-                                                       break;
-                                               }
-                       }
+                       if ((table = rn->info) == NULL)
+                               continue;
+
+                       for (rm = bgp_table_top(table); rm;
+                            rm = bgp_route_next(rm))
+                               for (ri = rm->info; ri; ri = ri->next) {
+                                       if (ri->peer != peer)
+                                               continue;
+                                       if (!CHECK_FLAG(ri->flags,
+                                                       BGP_INFO_STALE))
+                                               break;
+
+                                       bgp_rib_remove(rm, ri, peer, afi, safi);
+                                       break;
+                               }
                }
        } else {
                for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn;
                     rn = bgp_route_next(rn))
-                       for (ri = rn->info; ri; ri = ri->next)
-                               if (ri->peer == peer) {
-                                       if (CHECK_FLAG(ri->flags,
-                                                      BGP_INFO_STALE))
-                                               bgp_rib_remove(rn, ri, peer,
-                                                              afi, safi);
+                       for (ri = rn->info; ri; ri = ri->next) {
+                               if (ri->peer != peer)
+                                       continue;
+                               if (!CHECK_FLAG(ri->flags, BGP_INFO_STALE))
                                        break;
-                               }
+                               bgp_rib_remove(rn, ri, peer, afi, safi);
+                               break;
+                       }
        }
 }
 
@@ -4556,28 +4565,27 @@ void bgp_static_add(struct bgp *bgp)
        for (afi = AFI_IP; afi < AFI_MAX; afi++)
                for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
                        for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
-                            rn = bgp_route_next(rn))
-                               if (rn->info != NULL) {
-                                       if ((safi == SAFI_MPLS_VPN)
-                                           || (safi == SAFI_ENCAP)
-                                           || (safi == SAFI_EVPN)) {
-                                               table = rn->info;
-
-                                               for (rm = bgp_table_top(table);
-                                                    rm;
-                                                    rm = bgp_route_next(rm)) {
-                                                       bgp_static = rm->info;
-                                                       bgp_static_update_safi(
-                                                               bgp, &rm->p,
-                                                               bgp_static, afi,
-                                                               safi);
-                                               }
-                                       } else {
-                                               bgp_static_update(bgp, &rn->p,
-                                                                 rn->info, afi,
-                                                                 safi);
+                            rn = bgp_route_next(rn)) {
+                               if (rn->info == NULL)
+                                       continue;
+
+                               if ((safi == SAFI_MPLS_VPN)
+                                   || (safi == SAFI_ENCAP)
+                                   || (safi == SAFI_EVPN)) {
+                                       table = rn->info;
+
+                                       for (rm = bgp_table_top(table); rm;
+                                            rm = bgp_route_next(rm)) {
+                                               bgp_static = rm->info;
+                                               bgp_static_update_safi(
+                                                       bgp, &rm->p, bgp_static,
+                                                       afi, safi);
                                        }
+                               } else {
+                                       bgp_static_update(bgp, &rn->p, rn->info,
+                                                         afi, safi);
                                }
+                       }
 }
 
 /* Called from bgp_delete().  Delete all static routes from the BGP
@@ -4594,37 +4602,36 @@ void bgp_static_delete(struct bgp *bgp)
        for (afi = AFI_IP; afi < AFI_MAX; afi++)
                for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
                        for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
-                            rn = bgp_route_next(rn))
-                               if (rn->info != NULL) {
-                                       if ((safi == SAFI_MPLS_VPN)
-                                           || (safi == SAFI_ENCAP)
-                                           || (safi == SAFI_EVPN)) {
-                                               table = rn->info;
-
-                                               for (rm = bgp_table_top(table);
-                                                    rm;
-                                                    rm = bgp_route_next(rm)) {
-                                                       bgp_static = rm->info;
-                                                       bgp_static_withdraw_safi(
-                                                               bgp, &rm->p,
-                                                               AFI_IP, safi,
-                                                               (struct
-                                                                prefix_rd *)&rn
-                                                                       ->p);
-                                                       bgp_static_free(
-                                                               bgp_static);
-                                                       rn->info = NULL;
-                                                       bgp_unlock_node(rn);
-                                               }
-                                       } else {
-                                               bgp_static = rn->info;
-                                               bgp_static_withdraw(bgp, &rn->p,
-                                                                   afi, safi);
+                            rn = bgp_route_next(rn)) {
+                               if (rn->info == NULL)
+                                       continue;
+
+                               if ((safi == SAFI_MPLS_VPN)
+                                   || (safi == SAFI_ENCAP)
+                                   || (safi == SAFI_EVPN)) {
+                                       table = rn->info;
+
+                                       for (rm = bgp_table_top(table); rm;
+                                            rm = bgp_route_next(rm)) {
+                                               bgp_static = rm->info;
+                                               bgp_static_withdraw_safi(
+                                                       bgp, &rm->p, AFI_IP,
+                                                       safi,
+                                                       (struct prefix_rd *)&rn
+                                                               ->p);
                                                bgp_static_free(bgp_static);
                                                rn->info = NULL;
                                                bgp_unlock_node(rn);
                                        }
+                               } else {
+                                       bgp_static = rn->info;
+                                       bgp_static_withdraw(bgp, &rn->p, afi,
+                                                           safi);
+                                       bgp_static_free(bgp_static);
+                                       rn->info = NULL;
+                                       bgp_unlock_node(rn);
                                }
+                       }
 }
 
 void bgp_static_redo_import_check(struct bgp *bgp)
@@ -4641,29 +4648,29 @@ void bgp_static_redo_import_check(struct bgp *bgp)
        for (afi = AFI_IP; afi < AFI_MAX; afi++)
                for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
                        for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
-                            rn = bgp_route_next(rn))
-                               if (rn->info != NULL) {
-                                       if ((safi == SAFI_MPLS_VPN)
-                                           || (safi == SAFI_ENCAP)
-                                           || (safi == SAFI_EVPN)) {
-                                               table = rn->info;
-
-                                               for (rm = bgp_table_top(table);
-                                                    rm;
-                                                    rm = bgp_route_next(rm)) {
-                                                       bgp_static = rm->info;
-                                                       bgp_static_update_safi(
-                                                               bgp, &rm->p,
-                                                               bgp_static, afi,
-                                                               safi);
-                                               }
-                                       } else {
-                                               bgp_static = rn->info;
-                                               bgp_static_update(bgp, &rn->p,
-                                                                 bgp_static,
-                                                                 afi, safi);
+                            rn = bgp_route_next(rn)) {
+                               if (rn->info == NULL)
+                                       continue;
+
+                               if ((safi == SAFI_MPLS_VPN)
+                                   || (safi == SAFI_ENCAP)
+                                   || (safi == SAFI_EVPN)) {
+                                       table = rn->info;
+
+                                       for (rm = bgp_table_top(table); rm;
+                                            rm = bgp_route_next(rm)) {
+                                               bgp_static = rm->info;
+                                               bgp_static_update_safi(
+                                                       bgp, &rm->p, bgp_static,
+                                                       afi, safi);
                                        }
+                               } else {
+                                       bgp_static = rn->info;
+                                       bgp_static_update(bgp, &rn->p,
+                                                         bgp_static, afi,
+                                                         safi);
                                }
+                       }
        bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
 }
 
@@ -4947,16 +4954,13 @@ static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
        return CMD_SUCCESS;
 }
 
-int bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
-                              safi_t safi, int *write)
+void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
+                               safi_t safi)
 {
        if (bgp->table_map[afi][safi].name) {
-               bgp_config_write_family_header(vty, afi, safi, write);
                vty_out(vty, "  table-map %s\n",
                        bgp->table_map[afi][safi].name);
        }
-
-       return 0;
 }
 
 DEFUN (bgp_table_map,
@@ -5687,83 +5691,75 @@ static void bgp_aggregate_add(struct bgp *bgp, struct prefix *p, afi_t afi,
        /* If routes exists below this node, generate aggregate routes. */
        top = bgp_node_get(table, p);
        for (rn = bgp_node_get(table, p); rn;
-            rn = bgp_route_next_until(rn, top))
-               if (rn->p.prefixlen > p->prefixlen) {
-                       match = 0;
+            rn = bgp_route_next_until(rn, top)) {
+               if (rn->p.prefixlen <= p->prefixlen)
+                       continue;
 
-                       for (ri = rn->info; ri; ri = ri->next) {
-                               if (BGP_INFO_HOLDDOWN(ri))
-                                       continue;
+               match = 0;
 
-                               if (ri->attr->flag
-                                   & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
-                                       atomic_aggregate = 1;
+               for (ri = rn->info; ri; ri = ri->next) {
+                       if (BGP_INFO_HOLDDOWN(ri))
+                               continue;
 
-                               if (ri->sub_type != BGP_ROUTE_AGGREGATE) {
-                                       /* summary-only aggregate route suppress
-                                          aggregated
-                                          route announcement.  */
-                                       if (aggregate->summary_only) {
-                                               (bgp_info_extra_get(ri))
-                                                       ->suppress++;
-                                               bgp_info_set_flag(
-                                                       rn, ri,
-                                                       BGP_INFO_ATTR_CHANGED);
-                                               match++;
-                                       }
+                       if (ri->attr->flag
+                           & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
+                               atomic_aggregate = 1;
 
-                                       /* If at least one route among routes
-                                        * that are aggregated has
-                                        * ORIGIN with the value INCOMPLETE,
-                                        * then the aggregated route
-                                        * MUST have the ORIGIN attribute with
-                                        * the value INCOMPLETE.
-                                        * Otherwise, if at least one route
-                                        * among routes that are
-                                        * aggregated has ORIGIN with the value
-                                        * EGP, then the aggregated
-                                        * route MUST have the ORIGIN attribute
-                                        * with the value EGP.
-                                        */
-                                       if (origin < ri->attr->origin)
-                                               origin = ri->attr->origin;
+                       if (ri->sub_type == BGP_ROUTE_AGGREGATE)
+                               continue;
 
-                                       /* as-set aggregate route generate
-                                          origin, as path,
-                                          community aggregation.  */
-                                       if (aggregate->as_set) {
-                                               if (aspath) {
-                                                       asmerge = aspath_aggregate(
-                                                               aspath,
-                                                               ri->attr->aspath);
-                                                       aspath_free(aspath);
-                                                       aspath = asmerge;
-                                               } else
-                                                       aspath = aspath_dup(
-                                                               ri->attr->aspath);
+                       /* summary-only aggregate route suppress
+                        * aggregated route announcement.  */
+                       if (aggregate->summary_only) {
+                               (bgp_info_extra_get(ri))->suppress++;
+                               bgp_info_set_flag(rn, ri,
+                                                 BGP_INFO_ATTR_CHANGED);
+                               match++;
+                       }
 
-                                               if (ri->attr->community) {
-                                                       if (community) {
-                                                               commerge = community_merge(
-                                                                       community,
-                                                                       ri->attr->community);
-                                                               community = community_uniq_sort(
-                                                                       commerge);
-                                                               community_free(
-                                                                       commerge);
-                                                       } else
-                                                               community = community_dup(
-                                                                       ri->attr->community);
-                                               }
-                                       }
-                                       aggregate->count++;
+                       /* If at least one route among routes that are
+                        * aggregated has ORIGIN with the value INCOMPLETE,
+                        * then the aggregated route MUST have the ORIGIN
+                        * attribute with the value INCOMPLETE.  Otherwise, if
+                        * at least one route among routes that are aggregated
+                        * has ORIGIN with the value EGP, then the aggregated
+                        * route MUST have the ORIGIN attribute with the value
+                        * EGP.
+                        */
+                       if (origin < ri->attr->origin)
+                               origin = ri->attr->origin;
+
+                       /* as-set aggregate route generate origin, as path,
+                        * community aggregation.  */
+                       if (aggregate->as_set) {
+                               if (aspath) {
+                                       asmerge = aspath_aggregate(
+                                               aspath, ri->attr->aspath);
+                                       aspath_free(aspath);
+                                       aspath = asmerge;
+                               } else
+                                       aspath = aspath_dup(ri->attr->aspath);
+
+                               if (ri->attr->community) {
+                                       if (community) {
+                                               commerge = community_merge(
+                                                       community,
+                                                       ri->attr->community);
+                                               community = community_uniq_sort(
+                                                       commerge);
+                                               community_free(commerge);
+                                       } else
+                                               community = community_dup(
+                                                       ri->attr->community);
                                }
                        }
-
-                       /* If this node is suppressed, process the change. */
-                       if (match)
-                               bgp_process(bgp, rn, afi, safi);
+                       aggregate->count++;
                }
+
+               /* If this node is suppressed, process the change. */
+               if (match)
+                       bgp_process(bgp, rn, afi, safi);
+       }
        bgp_unlock_node(top);
 
        /* Add aggregate route to BGP table. */
@@ -5809,34 +5805,34 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
        /* If routes exists below this node, generate aggregate routes. */
        top = bgp_node_get(table, p);
        for (rn = bgp_node_get(table, p); rn;
-            rn = bgp_route_next_until(rn, top))
-               if (rn->p.prefixlen > p->prefixlen) {
-                       match = 0;
+            rn = bgp_route_next_until(rn, top)) {
+               if (rn->p.prefixlen <= p->prefixlen)
+                       continue;
+               match = 0;
 
-                       for (ri = rn->info; ri; ri = ri->next) {
-                               if (BGP_INFO_HOLDDOWN(ri))
-                                       continue;
+               for (ri = rn->info; ri; ri = ri->next) {
+                       if (BGP_INFO_HOLDDOWN(ri))
+                               continue;
 
-                               if (ri->sub_type != BGP_ROUTE_AGGREGATE) {
-                                       if (aggregate->summary_only
-                                           && ri->extra) {
-                                               ri->extra->suppress--;
-
-                                               if (ri->extra->suppress == 0) {
-                                                       bgp_info_set_flag(
-                                                               rn, ri,
-                                                               BGP_INFO_ATTR_CHANGED);
-                                                       match++;
-                                               }
-                                       }
-                                       aggregate->count--;
+                       if (ri->sub_type == BGP_ROUTE_AGGREGATE)
+                               continue;
+
+                       if (aggregate->summary_only && ri->extra) {
+                               ri->extra->suppress--;
+
+                               if (ri->extra->suppress == 0) {
+                                       bgp_info_set_flag(
+                                               rn, ri, BGP_INFO_ATTR_CHANGED);
+                                       match++;
                                }
                        }
-
-                       /* If this node was suppressed, process the change. */
-                       if (match)
-                               bgp_process(bgp, rn, afi, safi);
+                       aggregate->count--;
                }
+
+               /* If this node was suppressed, process the change. */
+               if (match)
+                       bgp_process(bgp, rn, afi, safi);
+       }
        bgp_unlock_node(top);
 
        /* Delete aggregate route from BGP table. */
@@ -6270,46 +6266,66 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
 }
 
 /* Static function to display route. */
-static void route_vty_out_route(struct prefix *p, struct vty *vty)
+static void route_vty_out_route(struct prefix *p, struct vty *vty,
+                               json_object *json)
 {
        int len;
        u_int32_t destination;
        char buf[BUFSIZ];
 
        if (p->family == AF_INET) {
-               len = vty_out(vty, "%s",
-                             inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ));
-               destination = ntohl(p->u.prefix4.s_addr);
-
-               if ((IN_CLASSC(destination) && p->prefixlen == 24)
-                   || (IN_CLASSB(destination) && p->prefixlen == 16)
-                   || (IN_CLASSA(destination) && p->prefixlen == 8)
-                   || p->u.prefix4.s_addr == 0) {
-                       /* When mask is natural, mask is not displayed. */
-               } else
-                       len += vty_out(vty, "/%d", p->prefixlen);
+               if (!json) {
+                       len = vty_out(vty, "%s",
+                                     inet_ntop(p->family, &p->u.prefix, buf,
+                                               BUFSIZ));
+                       destination = ntohl(p->u.prefix4.s_addr);
+
+                       if ((IN_CLASSC(destination) && p->prefixlen == 24)
+                           || (IN_CLASSB(destination) && p->prefixlen == 16)
+                           || (IN_CLASSA(destination) && p->prefixlen == 8)
+                           || p->u.prefix4.s_addr == 0) {
+                               /* When mask is natural,
+                                  mask is not displayed. */
+                       } else
+                               len += vty_out(vty, "/%d", p->prefixlen);
+               } else {
+                       json_object_string_add(json, "prefix",
+                                              inet_ntop(p->family,
+                                                        &p->u.prefix, buf,
+                                                        BUFSIZ));
+                       json_object_int_add(json, "prefixLen", p->prefixlen);
+               }
        } else if (p->family == AF_ETHERNET) {
                prefix2str(p, buf, PREFIX_STRLEN);
                len = vty_out(vty, "%s", buf);
        } else if (p->family == AF_EVPN) {
 #if defined(HAVE_CUMULUS)
-               len = vty_out(vty, "%s",
-                             bgp_evpn_route2str((struct prefix_evpn *)p, buf,
-                                                BUFSIZ));
+               if (!json)
+                       len = vty_out(
+                               vty, "%s",
+                               bgp_evpn_route2str((struct prefix_evpn *)p, buf,
+                                                  BUFSIZ));
+               else
+                       bgp_evpn_route2json((struct prefix_evpn *)p, json);
 #else
                prefix2str(p, buf, PREFIX_STRLEN);
                len = vty_out(vty, "%s", buf);
 #endif
-       } else
-               len = vty_out(vty, "%s/%d",
-                             inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
-                             p->prefixlen);
+       } else {
+               if (!json)
+                       len = vty_out(
+                               vty, "%s/%d",
+                               inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
+                               p->prefixlen);
+       }
 
-       len = 17 - len;
-       if (len < 1)
-               vty_out(vty, "\n%*s", 20, " ");
-       else
-               vty_out(vty, "%*s", len, " ");
+       if (!json) {
+               len = 17 - len;
+               if (len < 1)
+                       vty_out(vty, "\n%*s", 20, " ");
+               else
+                       vty_out(vty, "%*s", len, " ");
+       }
 }
 
 enum bgp_display_type {
@@ -6413,9 +6429,11 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
        if (!json_paths) {
                /* print prefix and mask */
                if (!display)
-                       route_vty_out_route(p, vty);
+                       route_vty_out_route(p, vty, json_path);
                else
                        vty_out(vty, "%*s", 17, " ");
+       } else {
+               route_vty_out_route(p, vty, json_path);
        }
 
        /* Print attribute */
@@ -6711,7 +6729,7 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
                        json_net, "addrPrefix",
                        inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ));
        else
-               route_vty_out_route(p, vty);
+               route_vty_out_route(p, vty, NULL);
 
        /* Print attribute */
        if (attr) {
@@ -6844,7 +6862,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p,
        /* print prefix and mask */
        if (json == NULL) {
                if (!display)
-                       route_vty_out_route(p, vty);
+                       route_vty_out_route(p, vty, NULL);
                else
                        vty_out(vty, "%*s", 17, " ");
        }
@@ -6959,7 +6977,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
 
        /* print prefix and mask */
        if (!display)
-               route_vty_out_route(p, vty);
+               route_vty_out_route(p, vty, NULL);
        else
                vty_out(vty, "%*s", 17, " ");
 
@@ -7028,7 +7046,7 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p,
        /* print prefix and mask */
        if (!use_json) {
                if (!display)
-                       route_vty_out_route(p, vty);
+                       route_vty_out_route(p, vty, NULL);
                else
                        vty_out(vty, "%*s", 17, " ");
        }
@@ -7097,7 +7115,7 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p,
        /* print prefix and mask */
        if (!use_json) {
                if (!display)
-                       route_vty_out_route(p, vty);
+                       route_vty_out_route(p, vty, NULL);
                else
                        vty_out(vty, "%*s", 17, " ");
        }
@@ -8380,6 +8398,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
 #if defined(HAVE_CUMULUS)
        char buf3[EVPN_ROUTE_STRLEN];
 #endif
+       char prefix_str[BUFSIZ];
        int count = 0;
        int best = 0;
        int suppress = 0;
@@ -8401,10 +8420,9 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
                if (has_valid_label)
                        json_object_int_add(json, "localLabel", label);
 
-               json_object_string_add(json, "prefix",
-                                      inet_ntop(p->family, &p->u.prefix, buf2,
-                                                INET6_ADDRSTRLEN));
-               json_object_int_add(json, "prefixlen", p->prefixlen);
+               json_object_string_add(
+                       json, "prefix",
+                       prefix2str(p, prefix_str, sizeof(prefix_str)));
        } else {
 #if defined(HAVE_CUMULUS)
                if (safi == SAFI_EVPN)
@@ -8564,55 +8582,45 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
                        if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
                                continue;
 
-                       if ((table = rn->info) != NULL) {
-                               header = 1;
-
-                               if ((rm = bgp_node_match(table, &match))
-                                   != NULL) {
-                                       if (prefix_check
-                                           && rm->p.prefixlen
-                                                      != match.prefixlen) {
-                                               bgp_unlock_node(rm);
-                                               continue;
-                                       }
+                       if ((table = rn->info) == NULL)
+                               continue;
 
-                                       for (ri = rm->info; ri; ri = ri->next) {
-                                               if (header) {
-                                                       route_vty_out_detail_header(
-                                                               vty, bgp, rm,
-                                                               (struct
-                                                                prefix_rd *)&rn
-                                                                       ->p,
-                                                               AFI_IP, safi,
-                                                               json);
-                                                       header = 0;
-                                               }
-                                               display++;
-
-                                               if (pathtype == BGP_PATH_ALL
-                                                   || (pathtype
-                                                               == BGP_PATH_BESTPATH
-                                                       && CHECK_FLAG(
-                                                                  ri->flags,
-                                                                  BGP_INFO_SELECTED))
-                                                   || (pathtype
-                                                               == BGP_PATH_MULTIPATH
-                                                       && (CHECK_FLAG(
-                                                                   ri->flags,
-                                                                   BGP_INFO_MULTIPATH)
-                                                           || CHECK_FLAG(
-                                                                      ri->flags,
-                                                                      BGP_INFO_SELECTED))))
-                                                       route_vty_out_detail(
-                                                               vty, bgp,
-                                                               &rm->p, ri,
-                                                               AFI_IP, safi,
-                                                               json_paths);
-                                       }
+                       header = 1;
+
+                       if ((rm = bgp_node_match(table, &match)) == NULL)
+                               continue;
+
+                       if (prefix_check
+                           && rm->p.prefixlen != match.prefixlen) {
+                               bgp_unlock_node(rm);
+                               continue;
+                       }
 
-                                       bgp_unlock_node(rm);
+                       for (ri = rm->info; ri; ri = ri->next) {
+                               if (header) {
+                                       route_vty_out_detail_header(
+                                               vty, bgp, rm,
+                                               (struct prefix_rd *)&rn->p,
+                                               AFI_IP, safi, json);
+                                       header = 0;
                                }
+                               display++;
+
+                               if (pathtype == BGP_PATH_ALL
+                                   || (pathtype == BGP_PATH_BESTPATH
+                                       && CHECK_FLAG(ri->flags,
+                                                     BGP_INFO_SELECTED))
+                                   || (pathtype == BGP_PATH_MULTIPATH
+                                       && (CHECK_FLAG(ri->flags,
+                                                      BGP_INFO_MULTIPATH)
+                                           || CHECK_FLAG(ri->flags,
+                                                         BGP_INFO_SELECTED))))
+                                       route_vty_out_detail(vty, bgp, &rm->p,
+                                                            ri, AFI_IP, safi,
+                                                            json_paths);
                        }
+
+                       bgp_unlock_node(rm);
                }
        } else {
                header = 1;
@@ -9998,60 +10006,54 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
        for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
                if (in) {
                        for (ain = rn->adj_in; ain; ain = ain->next) {
-                               if (ain->peer == peer) {
-                                       if (header1) {
-                                               if (use_json) {
-                                                       json_object_int_add(
-                                                               json,
-                                                               "bgpTableVersion",
-                                                               0);
-                                                       json_object_string_add(
-                                                               json,
-                                                               "bgpLocalRouterId",
-                                                               inet_ntoa(
-                                                                       bgp->router_id));
-                                                       json_object_object_add(
-                                                               json,
-                                                               "bgpStatusCodes",
-                                                               json_scode);
-                                                       json_object_object_add(
-                                                               json,
-                                                               "bgpOriginCodes",
-                                                               json_ocode);
-                                               } else {
-                                                       vty_out(vty,
-                                                               "BGP table version is 0, local router ID is %s\n",
-                                                               inet_ntoa(
-                                                                       bgp->router_id));
-                                                       vty_out(vty,
-                                                               BGP_SHOW_SCODE_HEADER);
-                                                       vty_out(vty,
-                                                               BGP_SHOW_OCODE_HEADER);
-                                               }
-                                               header1 = 0;
-                                       }
-                                       if (header2) {
-                                               if (!use_json)
-                                                       vty_out(vty,
-                                                               BGP_SHOW_HEADER);
-                                               header2 = 0;
-                                       }
-                                       if (ain->attr) {
-                                               bgp_attr_dup(&attr, ain->attr);
-                                               if (bgp_input_modifier(
-                                                           peer, &rn->p, &attr,
-                                                           afi, safi,
-                                                           rmap_name)
-                                                   != RMAP_DENY) {
-                                                       route_vty_out_tmp(
-                                                               vty, &rn->p,
-                                                               &attr, safi,
-                                                               use_json,
-                                                               json_ar);
-                                                       output_count++;
-                                               } else
-                                                       filtered_count++;
+                               if (ain->peer != peer)
+                                       continue;
+                               if (header1) {
+                                       if (use_json) {
+                                               json_object_int_add(
+                                                       json, "bgpTableVersion",
+                                                       0);
+                                               json_object_string_add(
+                                                       json,
+                                                       "bgpLocalRouterId",
+                                                       inet_ntoa(
+                                                               bgp->router_id));
+                                               json_object_object_add(
+                                                       json, "bgpStatusCodes",
+                                                       json_scode);
+                                               json_object_object_add(
+                                                       json, "bgpOriginCodes",
+                                                       json_ocode);
+                                       } else {
+                                               vty_out(vty,
+                                                       "BGP table version is 0, local router ID is %s\n",
+                                                       inet_ntoa(
+                                                               bgp->router_id));
+                                               vty_out(vty,
+                                                       BGP_SHOW_SCODE_HEADER);
+                                               vty_out(vty,
+                                                       BGP_SHOW_OCODE_HEADER);
                                        }
+                                       header1 = 0;
+                               }
+                               if (header2) {
+                                       if (!use_json)
+                                               vty_out(vty, BGP_SHOW_HEADER);
+                                       header2 = 0;
+                               }
+                               if (ain->attr) {
+                                       bgp_attr_dup(&attr, ain->attr);
+                                       if (bgp_input_modifier(peer, &rn->p,
+                                                              &attr, afi, safi,
+                                                              rmap_name)
+                                           != RMAP_DENY) {
+                                               route_vty_out_tmp(vty, &rn->p,
+                                                                 &attr, safi,
+                                                                 use_json,
+                                                                 json_ar);
+                                               output_count++;
+                                       } else
+                                               filtered_count++;
                                }
                        }
                } else {
@@ -10338,10 +10340,6 @@ static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
                return CMD_WARNING;
        }
 
-       /* labeled-unicast routes live in the unicast table */
-       if (safi == SAFI_LABELED_UNICAST)
-               safi = SAFI_UNICAST;
-
        return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json);
 }
 
@@ -10859,32 +10857,27 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
                     rn = bgp_route_next(rn)) {
                        if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
                                continue;
+                       if ((table = rn->info) == NULL)
+                               continue;
+                       if ((rm = bgp_node_match(table, &match)) == NULL)
+                               continue;
 
-                       if ((table = rn->info) != NULL)
-                               if ((rm = bgp_node_match(table, &match))
-                                   != NULL) {
-                                       if (!prefix_check
-                                           || rm->p.prefixlen
-                                                      == match.prefixlen) {
-                                               ri = rm->info;
-                                               while (ri) {
-                                                       if (ri->extra
-                                                           && ri->extra
-                                                                      ->damp_info) {
-                                                               ri_temp =
-                                                                       ri->next;
-                                                               bgp_damp_info_free(
-                                                                       ri->extra
-                                                                               ->damp_info,
-                                                                       1);
-                                                               ri = ri_temp;
-                                                       } else
-                                                               ri = ri->next;
-                                               }
-                                       }
-
-                                       bgp_unlock_node(rm);
+                       if (!prefix_check
+                           || rm->p.prefixlen == match.prefixlen) {
+                               ri = rm->info;
+                               while (ri) {
+                                       if (ri->extra && ri->extra->damp_info) {
+                                               ri_temp = ri->next;
+                                               bgp_damp_info_free(
+                                                       ri->extra->damp_info,
+                                                       1);
+                                               ri = ri_temp;
+                                       } else
+                                               ri = ri->next;
                                }
+                       }
+
+                       bgp_unlock_node(rm);
                }
        } else {
                if ((rn = bgp_node_match(bgp->rib[afi][safi], &match))
@@ -10978,8 +10971,8 @@ DEFUN (clear_ip_bgp_dampening_address_mask,
 }
 
 /* also used for encap safi */
-static int bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
-                                       afi_t afi, safi_t safi, int *write)
+static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
+                                        afi_t afi, safi_t safi)
 {
        struct bgp_node *prn;
        struct bgp_node *rn;
@@ -10993,48 +10986,42 @@ static int bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
 
        /* Network configuration. */
        for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
-            prn = bgp_route_next(prn))
-               if ((table = prn->info) != NULL)
-                       for (rn = bgp_table_top(table); rn;
-                            rn = bgp_route_next(rn))
-                               if ((bgp_static = rn->info) != NULL) {
-                                       p = &rn->p;
-                                       prd = (struct prefix_rd *)&prn->p;
+            prn = bgp_route_next(prn)) {
+               if ((table = prn->info) == NULL)
+                       continue;
 
-                                       /* "address-family" display.  */
-                                       bgp_config_write_family_header(
-                                               vty, afi, safi, write);
+               for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
+                       if ((bgp_static = rn->info) == NULL)
+                               continue;
 
-                                       /* "network" configuration display.  */
-                                       prefix_rd2str(prd, rdbuf,
-                                                     RD_ADDRSTRLEN);
-                                       label = decode_label(
-                                               &bgp_static->label);
+                       p = &rn->p;
+                       prd = (struct prefix_rd *)&prn->p;
 
-                                       vty_out(vty, "  network %s/%d rd %s",
-                                               inet_ntop(p->family,
-                                                         &p->u.prefix, buf,
-                                                         SU_ADDRSTRLEN),
-                                               p->prefixlen, rdbuf);
-                                       if (safi == SAFI_MPLS_VPN)
-                                               vty_out(vty, " label %u",
-                                                       label);
-
-                                       if (bgp_static->rmap.name)
-                                               vty_out(vty, " route-map %s",
-                                                       bgp_static->rmap.name);
-                                       else {
-                                               if (bgp_static->backdoor)
-                                                       vty_out(vty,
-                                                               " backdoor");
-                                       }
-                                       vty_out(vty, "\n");
-                               }
-       return 0;
+                       /* "network" configuration display.  */
+                       prefix_rd2str(prd, rdbuf, RD_ADDRSTRLEN);
+                       label = decode_label(&bgp_static->label);
+
+                       vty_out(vty, "  network %s/%d rd %s",
+                               inet_ntop(p->family, &p->u.prefix, buf,
+                                         SU_ADDRSTRLEN),
+                               p->prefixlen, rdbuf);
+                       if (safi == SAFI_MPLS_VPN)
+                               vty_out(vty, " label %u", label);
+
+                       if (bgp_static->rmap.name)
+                               vty_out(vty, " route-map %s",
+                                       bgp_static->rmap.name);
+                       else {
+                               if (bgp_static->backdoor)
+                                       vty_out(vty, " backdoor");
+                       }
+                       vty_out(vty, "\n");
+               }
+       }
 }
 
-static int bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
-                                        afi_t afi, safi_t safi, int *write)
+static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
+                                         afi_t afi, safi_t safi)
 {
        struct bgp_node *prn;
        struct bgp_node *rn;
@@ -11048,59 +11035,50 @@ static int bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
 
        /* Network configuration. */
        for (prn = bgp_table_top(bgp->route[afi][safi]); prn;
-            prn = bgp_route_next(prn))
-               if ((table = prn->info) != NULL)
-                       for (rn = bgp_table_top(table); rn;
-                            rn = bgp_route_next(rn))
-                               if ((bgp_static = rn->info) != NULL) {
-                                       char *macrouter = NULL;
-                                       char *esi = NULL;
-
-                                       if (bgp_static->router_mac)
-                                               macrouter = prefix_mac2str(
-                                                       bgp_static->router_mac,
-                                                       NULL, 0);
-                                       if (bgp_static->eth_s_id)
-                                               esi = esi2str(
-                                                       bgp_static->eth_s_id);
-                                       p = &rn->p;
-                                       prd = (struct prefix_rd *)&prn->p;
+            prn = bgp_route_next(prn)) {
+               if ((table = prn->info) == NULL)
+                       continue;
 
-                                       /* "address-family" display.  */
-                                       bgp_config_write_family_header(
-                                               vty, afi, safi, write);
+               for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
+                       if ((bgp_static = rn->info) == NULL)
+                               continue;
 
-                                       /* "network" configuration display.  */
-                                       prefix_rd2str(prd, rdbuf,
-                                                     RD_ADDRSTRLEN);
+                       char *macrouter = NULL;
+                       char *esi = NULL;
 
-                                       inet_ntop(AF_INET,
-                                                 &bgp_static->igpnexthop, buf2,
-                                                 SU_ADDRSTRLEN);
+                       if (bgp_static->router_mac)
+                               macrouter = prefix_mac2str(
+                                       bgp_static->router_mac, NULL, 0);
+                       if (bgp_static->eth_s_id)
+                               esi = esi2str(bgp_static->eth_s_id);
+                       p = &rn->p;
+                       prd = (struct prefix_rd *)&prn->p;
 
-                                       prefix2str(p, buf, sizeof(buf)),
-                                               vty_out(vty,
-                                                       " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s",
-                                                       buf, rdbuf,
-                                                       p->u.prefix_evpn
-                                                               .eth_tag,
-                                                       decode_label(
-                                                               &bgp_static
-                                                                        ->label),
-                                                       esi, buf2, macrouter);
-                                       vty_out(vty, "\n");
-                                       if (macrouter)
-                                               XFREE(MTYPE_TMP, macrouter);
-                                       if (esi)
-                                               XFREE(MTYPE_TMP, esi);
-                               }
-       return 0;
+                       /* "network" configuration display.  */
+                       prefix_rd2str(prd, rdbuf, RD_ADDRSTRLEN);
+
+                       inet_ntop(AF_INET, &bgp_static->igpnexthop, buf2,
+                                 SU_ADDRSTRLEN);
+
+                       prefix2str(p, buf, sizeof(buf));
+                       vty_out(vty,
+                               " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s\n",
+                               buf, rdbuf, p->u.prefix_evpn.eth_tag,
+                               decode_label(&bgp_static->label), esi, buf2,
+                               macrouter);
+
+                       if (macrouter)
+                               XFREE(MTYPE_TMP, macrouter);
+                       if (esi)
+                               XFREE(MTYPE_TMP, esi);
+               }
+       }
 }
 
 /* Configuration of static route announcement and aggregate
    information. */
-int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
-                            safi_t safi, int *write)
+void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
+                             safi_t safi)
 {
        struct bgp_node *rn;
        struct prefix *p;
@@ -11108,106 +11086,98 @@ int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
        struct bgp_aggregate *bgp_aggregate;
        char buf[SU_ADDRSTRLEN];
 
-       if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
-               return bgp_config_write_network_vpn(vty, bgp, afi, safi, write);
+       if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
+               bgp_config_write_network_vpn(vty, bgp, afi, safi);
+               return;
+       }
 
-       if (afi == AFI_L2VPN && safi == SAFI_EVPN)
-               return bgp_config_write_network_evpn(vty, bgp, afi, safi,
-                                                    write);
+       if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
+               bgp_config_write_network_evpn(vty, bgp, afi, safi);
+               return;
+       }
 
        /* Network configuration. */
        for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
-            rn = bgp_route_next(rn))
-               if ((bgp_static = rn->info) != NULL) {
-                       p = &rn->p;
+            rn = bgp_route_next(rn)) {
+               if ((bgp_static = rn->info) == NULL)
+                       continue;
 
-                       /* "address-family" display.  */
-                       bgp_config_write_family_header(vty, afi, safi, write);
+               p = &rn->p;
 
-                       /* "network" configuration display.  */
-                       if (bgp_option_check(BGP_OPT_CONFIG_CISCO)
-                           && afi == AFI_IP) {
-                               u_int32_t destination;
-                               struct in_addr netmask;
-
-                               destination = ntohl(p->u.prefix4.s_addr);
-                               masklen2ip(p->prefixlen, &netmask);
-                               vty_out(vty, "  network %s",
-                                       inet_ntop(p->family, &p->u.prefix, buf,
-                                                 SU_ADDRSTRLEN));
-
-                               if ((IN_CLASSC(destination)
-                                    && p->prefixlen == 24)
-                                   || (IN_CLASSB(destination)
-                                       && p->prefixlen == 16)
-                                   || (IN_CLASSA(destination)
-                                       && p->prefixlen == 8)
-                                   || p->u.prefix4.s_addr == 0) {
-                                       /* Natural mask is not display. */
-                               } else
-                                       vty_out(vty, " mask %s",
-                                               inet_ntoa(netmask));
-                       } else {
-                               vty_out(vty, "  network %s/%d",
-                                       inet_ntop(p->family, &p->u.prefix, buf,
-                                                 SU_ADDRSTRLEN),
-                                       p->prefixlen);
-                       }
+               /* "network" configuration display.  */
+               if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
+                       u_int32_t destination;
+                       struct in_addr netmask;
 
-                       if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
-                               vty_out(vty, " label-index %u",
-                                       bgp_static->label_index);
+                       destination = ntohl(p->u.prefix4.s_addr);
+                       masklen2ip(p->prefixlen, &netmask);
+                       vty_out(vty, "  network %s",
+                               inet_ntop(p->family, &p->u.prefix, buf,
+                                         SU_ADDRSTRLEN));
 
-                       if (bgp_static->rmap.name)
-                               vty_out(vty, " route-map %s",
-                                       bgp_static->rmap.name);
-                       else {
-                               if (bgp_static->backdoor)
-                                       vty_out(vty, " backdoor");
-                       }
+                       if ((IN_CLASSC(destination) && p->prefixlen == 24)
+                           || (IN_CLASSB(destination) && p->prefixlen == 16)
+                           || (IN_CLASSA(destination) && p->prefixlen == 8)
+                           || p->u.prefix4.s_addr == 0) {
+                               /* Natural mask is not display. */
+                       } else
+                               vty_out(vty, " mask %s", inet_ntoa(netmask));
+               } else {
+                       vty_out(vty, "  network %s/%d",
+                               inet_ntop(p->family, &p->u.prefix, buf,
+                                         SU_ADDRSTRLEN),
+                               p->prefixlen);
+               }
 
-                       vty_out(vty, "\n");
+               if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
+                       vty_out(vty, " label-index %u",
+                               bgp_static->label_index);
+
+               if (bgp_static->rmap.name)
+                       vty_out(vty, " route-map %s", bgp_static->rmap.name);
+               else {
+                       if (bgp_static->backdoor)
+                               vty_out(vty, " backdoor");
                }
 
+               vty_out(vty, "\n");
+       }
+
        /* Aggregate-address configuration. */
        for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn;
-            rn = bgp_route_next(rn))
-               if ((bgp_aggregate = rn->info) != NULL) {
-                       p = &rn->p;
+            rn = bgp_route_next(rn)) {
+               if ((bgp_aggregate = rn->info) == NULL)
+                       continue;
 
-                       /* "address-family" display.  */
-                       bgp_config_write_family_header(vty, afi, safi, write);
+               p = &rn->p;
 
-                       if (bgp_option_check(BGP_OPT_CONFIG_CISCO)
-                           && afi == AFI_IP) {
-                               struct in_addr netmask;
+               if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) {
+                       struct in_addr netmask;
 
-                               masklen2ip(p->prefixlen, &netmask);
-                               vty_out(vty, "  aggregate-address %s %s",
-                                       inet_ntop(p->family, &p->u.prefix, buf,
-                                                 SU_ADDRSTRLEN),
-                                       inet_ntoa(netmask));
-                       } else {
-                               vty_out(vty, "  aggregate-address %s/%d",
-                                       inet_ntop(p->family, &p->u.prefix, buf,
-                                                 SU_ADDRSTRLEN),
-                                       p->prefixlen);
-                       }
-
-                       if (bgp_aggregate->as_set)
-                               vty_out(vty, " as-set");
+                       masklen2ip(p->prefixlen, &netmask);
+                       vty_out(vty, "  aggregate-address %s %s",
+                               inet_ntop(p->family, &p->u.prefix, buf,
+                                         SU_ADDRSTRLEN),
+                               inet_ntoa(netmask));
+               } else {
+                       vty_out(vty, "  aggregate-address %s/%d",
+                               inet_ntop(p->family, &p->u.prefix, buf,
+                                         SU_ADDRSTRLEN),
+                               p->prefixlen);
+               }
 
-                       if (bgp_aggregate->summary_only)
-                               vty_out(vty, " summary-only");
+               if (bgp_aggregate->as_set)
+                       vty_out(vty, " as-set");
 
-                       vty_out(vty, "\n");
-               }
+               if (bgp_aggregate->summary_only)
+                       vty_out(vty, " summary-only");
 
-       return 0;
+               vty_out(vty, "\n");
+       }
 }
 
-int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
-                             safi_t safi, int *write)
+void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
+                              safi_t safi)
 {
        struct bgp_node *rn;
        struct bgp_distance *bdistance;
@@ -11219,7 +11189,6 @@ int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
                || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
                || bgp->distance_local[afi][safi]
                           != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
-               bgp_config_write_family_header(vty, afi, safi, write);
                vty_out(vty, "  distance bgp %d %d %d\n",
                        bgp->distance_ebgp[afi][safi],
                        bgp->distance_ibgp[afi][safi],
@@ -11231,15 +11200,12 @@ int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
                if ((bdistance = rn->info) != NULL) {
                        char buf[PREFIX_STRLEN];
 
-                       bgp_config_write_family_header(vty, afi, safi, write);
                        vty_out(vty, "  distance %d %s %s\n",
                                bdistance->distance,
                                prefix2str(&rn->p, buf, sizeof(buf)),
                                bdistance->access_list ? bdistance->access_list
                                                       : "");
                }
-
-       return *write;
 }
 
 /* Allocate routing table structure and install commands. */
index 55f812d4a08d9b677f2b7380de90352a652425f7..9306d27c11dea96b8a2f3860cb67c78bfaacb473 100644 (file)
@@ -294,6 +294,8 @@ static inline int bgp_fibupd_safi(safi_t safi)
 }
 
 /* Prototypes. */
+extern void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri,
+                          struct peer *peer, afi_t afi, safi_t safi);
 extern void bgp_process_queue_init(void);
 extern void bgp_route_init(void);
 extern void bgp_route_finish(void);
@@ -367,12 +369,11 @@ extern void bgp_process(struct bgp *, struct bgp_node *, afi_t, safi_t);
  * queue element with NULL bgp node.
  */
 extern void bgp_add_eoiu_mark(struct bgp *);
-extern int bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t,
-                                     int *);
-extern int bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t,
-                                   int *);
-extern int bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t,
-                                    int *);
+extern void bgp_config_write_table_map(struct vty *, struct bgp *, afi_t,
+                                      safi_t);
+extern void bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t);
+extern void bgp_config_write_distance(struct vty *, struct bgp *, afi_t,
+                                     safi_t);
 
 extern void bgp_aggregate_increment(struct bgp *, struct prefix *,
                                    struct bgp_info *, afi_t, safi_t);
index 5a5d2a5d5d4f6fe88ec0522327f5a8ed40ed274a..602bacde2849c332f9badc6e205b719aa07de1f6 100644 (file)
@@ -658,8 +658,10 @@ static void *route_match_vni_compile(const char *arg)
                return NULL;
 
        *vni = strtoul(arg, &end, 10);
-       if (*end != '\0')
+       if (*end != '\0') {
+               XFREE(MTYPE_ROUTE_MAP_COMPILED, vni);
                return NULL;
+       }
 
        return vni;
 }
@@ -2669,25 +2671,27 @@ static int bgp_route_match_add(struct vty *vty, const char *command,
                               const char *arg, route_map_event_t type)
 {
        VTY_DECLVAR_CONTEXT(route_map_index, index);
+       int retval = CMD_SUCCESS;
        int ret;
 
        ret = route_map_add_match(index, command, arg);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% BGP Can't find rule.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty, "%% BGP Argument is malformed.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% BGP Can't find rule.\n");
+               retval = CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty, "%% BGP Argument is malformed.\n");
+               retval = CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               if (type != RMAP_EVENT_MATCH_ADDED) {
+                       route_map_upd8_dependency(type, arg, index->map->name);
                }
+               break;
        }
 
-       if (type != RMAP_EVENT_MATCH_ADDED) {
-               route_map_upd8_dependency(type, arg, index->map->name);
-       }
-
-       return CMD_SUCCESS;
+       return retval;
 }
 
 /* Delete bgp route map rule. */
@@ -2696,6 +2700,7 @@ static int bgp_route_match_delete(struct vty *vty, const char *command,
 {
        VTY_DECLVAR_CONTEXT(route_map_index, index);
        int ret;
+       int retval = CMD_SUCCESS;
        char *dep_name = NULL;
        const char *tmpstr;
        char *rmap_name = NULL;
@@ -2714,31 +2719,27 @@ static int bgp_route_match_delete(struct vty *vty, const char *command,
        }
 
        ret = route_map_delete_match(index, command, dep_name);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% BGP Can't find rule.\n");
-                       break;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty, "%% BGP Argument is malformed.\n");
-                       break;
-               }
-               if (dep_name)
-                       XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
-               if (rmap_name)
-                       XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
-               return CMD_WARNING_CONFIG_FAILED;
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% BGP Can't find rule.\n");
+               retval = CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty, "%% BGP Argument is malformed.\n");
+               retval = CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
+                       route_map_upd8_dependency(type, dep_name, rmap_name);
+               break;
        }
 
-       if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
-               route_map_upd8_dependency(type, dep_name, rmap_name);
-
        if (dep_name)
                XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
        if (rmap_name)
                XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
 
-       return CMD_SUCCESS;
+       return retval;
 }
 
 /*
index f040ed9a08896c7cade35c12e85fffb67a8c9d50..52c5d696e3c3c12a3065786a23daf0815c56f052 100644 (file)
@@ -1279,7 +1279,7 @@ static int bgp_update_delay_deconfig_vty(struct vty *vty)
        return CMD_SUCCESS;
 }
 
-int bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp)
+void bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp)
 {
        if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) {
                vty_out(vty, " update-delay %d", bgp->v_update_delay);
@@ -1287,8 +1287,6 @@ int bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp)
                        vty_out(vty, " %d", bgp->v_establish_wait);
                vty_out(vty, "\n");
        }
-
-       return 0;
 }
 
 
@@ -1342,12 +1340,10 @@ static int bgp_wpkt_quanta_config_vty(struct vty *vty, const char *num,
        return CMD_SUCCESS;
 }
 
-int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp)
+void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp)
 {
        if (bgp->wpkt_quanta != BGP_WRITE_PACKET_MAX)
                vty_out(vty, " write-quanta %d\n", bgp->wpkt_quanta);
-
-       return 0;
 }
 
 
@@ -1374,12 +1370,10 @@ DEFUN (no_bgp_wpkt_quanta,
        return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 0);
 }
 
-int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp)
+void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp)
 {
        if (bgp->coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME)
                vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time);
-
-       return 0;
 }
 
 
@@ -1503,17 +1497,15 @@ ALIAS_HIDDEN(no_bgp_maxpaths_ibgp, no_bgp_maxpaths_ibgp_hidden_cmd,
             "Number of paths\n"
             "Match the cluster length\n")
 
-int bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
-                             safi_t safi, int *write)
+void bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
+                              safi_t safi)
 {
        if (bgp->maxpaths[afi][safi].maxpaths_ebgp != MULTIPATH_NUM) {
-               bgp_config_write_family_header(vty, afi, safi, write);
                vty_out(vty, "  maximum-paths %d\n",
                        bgp->maxpaths[afi][safi].maxpaths_ebgp);
        }
 
        if (bgp->maxpaths[afi][safi].maxpaths_ibgp != MULTIPATH_NUM) {
-               bgp_config_write_family_header(vty, afi, safi, write);
                vty_out(vty, "  maximum-paths ibgp %d",
                        bgp->maxpaths[afi][safi].maxpaths_ibgp);
                if (CHECK_FLAG(bgp->maxpaths[afi][safi].ibgp_flags,
@@ -1521,8 +1513,6 @@ int bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi,
                        vty_out(vty, " equal-cluster-length");
                vty_out(vty, "\n");
        }
-
-       return 0;
 }
 
 /* BGP timers.  */
@@ -2459,7 +2449,7 @@ DEFUN (no_bgp_listen_range,
        return bgp_vty_return(vty, ret);
 }
 
-int bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
+void bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
 {
        struct peer_group *group;
        struct listnode *node, *nnode, *rnode, *nrnode;
@@ -2482,8 +2472,6 @@ int bgp_config_write_listen(struct vty *vty, struct bgp *bgp)
                        }
                }
        }
-
-       return 0;
 }
 
 
@@ -6424,6 +6412,57 @@ DEFUN (show_bgp_vrfs,
        return CMD_SUCCESS;
 }
 
+static void show_address_entry(struct hash_backet *backet, void *args)
+{
+       struct vty *vty = (struct vty *)args;
+       struct bgp_addr *addr = (struct bgp_addr *)backet->data;
+
+       vty_out(vty, "addr: %s, count: %d\n", inet_ntoa(addr->addr),
+               addr->refcnt);
+}
+
+static void show_tip_entry(struct hash_backet *backet, void *args)
+{
+       struct vty *vty = (struct vty *)args;
+       struct tip_addr *tip = (struct tip_addr *)backet->data;
+
+       vty_out(vty, "addr: %s, count: %d\n", inet_ntoa(tip->addr),
+               tip->refcnt);
+}
+
+static void bgp_show_martian_nexthops(struct vty *vty, struct bgp *bgp)
+{
+       vty_out(vty, "self nexthop database:\n");
+       hash_iterate(bgp->address_hash,
+                    (void (*)(struct hash_backet *, void *))show_address_entry,
+                    vty);
+
+       vty_out(vty, "Tunnel-ip database:\n");
+       hash_iterate(bgp->tip_hash,
+                    (void (*)(struct hash_backet *, void *))show_tip_entry,
+                    vty);
+}
+
+DEFUN(show_bgp_martian_nexthop_db,
+      show_bgp_martian_nexthop_db_cmd,
+      "show bgp martian next-hop",
+      SHOW_STR
+      BGP_STR
+      "martian next-hops\n"
+      "martian next-hop database\n")
+{
+       struct bgp *bgp = NULL;
+
+       bgp = bgp_get_default();
+       if (!bgp) {
+               vty_out(vty, "%% No BGP process is configured\n");
+               return CMD_WARNING;
+       }
+       bgp_show_martian_nexthops(vty, bgp);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (show_bgp_memory,
        show_bgp_memory_cmd,
        "show [ip] bgp memory",
@@ -6622,367 +6661,321 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
                if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
                        continue;
 
-               if (peer->afc[afi][safi]) {
-                       if (!count) {
-                               unsigned long ents;
-                               char memstrbuf[MTYPE_MEMSTR_LEN];
-                               int vrf_id_ui;
+               if (!peer->afc[afi][safi])
+                       continue;
 
-                               vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN)
-                                                   ? -1
-                                                   : bgp->vrf_id;
+               if (!count) {
+                       unsigned long ents;
+                       char memstrbuf[MTYPE_MEMSTR_LEN];
+                       int vrf_id_ui;
+
+                       vrf_id_ui =
+                               (bgp->vrf_id == VRF_UNKNOWN) ? -1 : bgp->vrf_id;
+
+                       /* Usage summary and header */
+                       if (use_json) {
+                               json_object_string_add(
+                                       json, "routerId",
+                                       inet_ntoa(bgp->router_id));
+                               json_object_int_add(json, "as", bgp->as);
+                               json_object_int_add(json, "vrfId", vrf_id_ui);
+                               json_object_string_add(
+                                       json, "vrfName",
+                                       (bgp->inst_type
+                                        == BGP_INSTANCE_TYPE_DEFAULT)
+                                               ? "Default"
+                                               : bgp->name);
+                       } else {
+                               vty_out(vty,
+                                       "BGP router identifier %s, local AS number %u vrf-id %d",
+                                       inet_ntoa(bgp->router_id), bgp->as,
+                                       vrf_id_ui);
+                               vty_out(vty, "\n");
+                       }
 
-                               /* Usage summary and header */
+                       if (bgp_update_delay_configured(bgp)) {
                                if (use_json) {
-                                       json_object_string_add(
-                                               json, "routerId",
-                                               inet_ntoa(bgp->router_id));
-                                       json_object_int_add(json, "as",
-                                                           bgp->as);
-                                       json_object_int_add(json, "vrfId",
-                                                           vrf_id_ui);
-                                       json_object_string_add(
-                                               json, "vrfName",
-                                               (bgp->inst_type
-                                                == BGP_INSTANCE_TYPE_DEFAULT)
-                                                       ? "Default"
-                                                       : bgp->name);
-                               } else {
-                                       vty_out(vty,
-                                               "BGP router identifier %s, local AS number %u vrf-id %d",
-                                               inet_ntoa(bgp->router_id),
-                                               bgp->as, vrf_id_ui);
-                                       vty_out(vty, "\n");
-                               }
+                                       json_object_int_add(
+                                               json, "updateDelayLimit",
+                                               bgp->v_update_delay);
 
-                               if (bgp_update_delay_configured(bgp)) {
-                                       if (use_json) {
+                                       if (bgp->v_update_delay
+                                           != bgp->v_establish_wait)
                                                json_object_int_add(
                                                        json,
-                                                       "updateDelayLimit",
-                                                       bgp->v_update_delay);
+                                                       "updateDelayEstablishWait",
+                                                       bgp->v_establish_wait);
 
-                                               if (bgp->v_update_delay
-                                                   != bgp->v_establish_wait)
-                                                       json_object_int_add(
-                                                               json,
-                                                               "updateDelayEstablishWait",
-                                                               bgp->v_establish_wait);
-
-                                               if (bgp_update_delay_active(
-                                                           bgp)) {
+                                       if (bgp_update_delay_active(bgp)) {
+                                               json_object_string_add(
+                                                       json,
+                                                       "updateDelayFirstNeighbor",
+                                                       bgp->update_delay_begin_time);
+                                               json_object_boolean_true_add(
+                                                       json,
+                                                       "updateDelayInProgress");
+                                       } else {
+                                               if (bgp->update_delay_over) {
                                                        json_object_string_add(
                                                                json,
                                                                "updateDelayFirstNeighbor",
                                                                bgp->update_delay_begin_time);
-                                                       json_object_boolean_true_add(
+                                                       json_object_string_add(
                                                                json,
-                                                               "updateDelayInProgress");
-                                               } else {
-                                                       if (bgp->update_delay_over) {
-                                                               json_object_string_add(
-                                                                       json,
-                                                                       "updateDelayFirstNeighbor",
-                                                                       bgp->update_delay_begin_time);
-                                                               json_object_string_add(
-                                                                       json,
-                                                                       "updateDelayBestpathResumed",
-                                                                       bgp->update_delay_end_time);
-                                                               json_object_string_add(
-                                                                       json,
-                                                                       "updateDelayZebraUpdateResume",
-                                                                       bgp->update_delay_zebra_resume_time);
-                                                               json_object_string_add(
-                                                                       json,
-                                                                       "updateDelayPeerUpdateResume",
-                                                                       bgp->update_delay_peers_resume_time);
-                                                       }
+                                                               "updateDelayBestpathResumed",
+                                                               bgp->update_delay_end_time);
+                                                       json_object_string_add(
+                                                               json,
+                                                               "updateDelayZebraUpdateResume",
+                                                               bgp->update_delay_zebra_resume_time);
+                                                       json_object_string_add(
+                                                               json,
+                                                               "updateDelayPeerUpdateResume",
+                                                               bgp->update_delay_peers_resume_time);
                                                }
-                                       } else {
+                                       }
+                               } else {
+                                       vty_out(vty,
+                                               "Read-only mode update-delay limit: %d seconds\n",
+                                               bgp->v_update_delay);
+                                       if (bgp->v_update_delay
+                                           != bgp->v_establish_wait)
                                                vty_out(vty,
-                                                       "Read-only mode update-delay limit: %d seconds\n",
-                                                       bgp->v_update_delay);
-                                               if (bgp->v_update_delay
-                                                   != bgp->v_establish_wait)
-                                                       vty_out(vty,
-                                                               "                   Establish wait: %d seconds\n",
-                                                               bgp->v_establish_wait);
+                                                       "                   Establish wait: %d seconds\n",
+                                                       bgp->v_establish_wait);
 
-                                               if (bgp_update_delay_active(
-                                                           bgp)) {
+                                       if (bgp_update_delay_active(bgp)) {
+                                               vty_out(vty,
+                                                       "  First neighbor established: %s\n",
+                                                       bgp->update_delay_begin_time);
+                                               vty_out(vty,
+                                                       "  Delay in progress\n");
+                                       } else {
+                                               if (bgp->update_delay_over) {
                                                        vty_out(vty,
                                                                "  First neighbor established: %s\n",
                                                                bgp->update_delay_begin_time);
                                                        vty_out(vty,
-                                                               "  Delay in progress\n");
-                                               } else {
-                                                       if (bgp->update_delay_over) {
-                                                               vty_out(vty,
-                                                                       "  First neighbor established: %s\n",
-                                                                       bgp->update_delay_begin_time);
-                                                               vty_out(vty,
-                                                                       "          Best-paths resumed: %s\n",
-                                                                       bgp->update_delay_end_time);
-                                                               vty_out(vty,
-                                                                       "        zebra update resumed: %s\n",
-                                                                       bgp->update_delay_zebra_resume_time);
-                                                               vty_out(vty,
-                                                                       "        peers update resumed: %s\n",
-                                                                       bgp->update_delay_peers_resume_time);
-                                                       }
+                                                               "          Best-paths resumed: %s\n",
+                                                               bgp->update_delay_end_time);
+                                                       vty_out(vty,
+                                                               "        zebra update resumed: %s\n",
+                                                               bgp->update_delay_zebra_resume_time);
+                                                       vty_out(vty,
+                                                               "        peers update resumed: %s\n",
+                                                               bgp->update_delay_peers_resume_time);
                                                }
                                        }
                                }
+                       }
 
-                               if (use_json) {
-                                       if (bgp_maxmed_onstartup_configured(bgp)
-                                           && bgp->maxmed_active)
-                                               json_object_boolean_true_add(
-                                                       json,
-                                                       "maxMedOnStartup");
-                                       if (bgp->v_maxmed_admin)
-                                               json_object_boolean_true_add(
-                                                       json,
-                                                       "maxMedAdministrative");
+                       if (use_json) {
+                               if (bgp_maxmed_onstartup_configured(bgp)
+                                   && bgp->maxmed_active)
+                                       json_object_boolean_true_add(
+                                               json, "maxMedOnStartup");
+                               if (bgp->v_maxmed_admin)
+                                       json_object_boolean_true_add(
+                                               json, "maxMedAdministrative");
 
-                                       json_object_int_add(
-                                               json, "tableVersion",
-                                               bgp_table_version(
-                                                       bgp->rib[afi][safi]));
-
-                                       ents = bgp_table_count(
-                                               bgp->rib[afi][safi]);
-                                       json_object_int_add(json, "ribCount",
-                                                           ents);
-                                       json_object_int_add(
-                                               json, "ribMemory",
-                                               ents * sizeof(struct bgp_node));
+                               json_object_int_add(
+                                       json, "tableVersion",
+                                       bgp_table_version(bgp->rib[afi][safi]));
 
-                                       ents = listcount(bgp->peer);
-                                       json_object_int_add(json, "peerCount",
-                                                           ents);
-                                       json_object_int_add(
-                                               json, "peerMemory",
-                                               ents * sizeof(struct peer));
+                               ents = bgp_table_count(bgp->rib[afi][safi]);
+                               json_object_int_add(json, "ribCount", ents);
+                               json_object_int_add(
+                                       json, "ribMemory",
+                                       ents * sizeof(struct bgp_node));
 
-                                       if ((ents = listcount(bgp->group))) {
-                                               json_object_int_add(
-                                                       json, "peerGroupCount",
-                                                       ents);
-                                               json_object_int_add(
-                                                       json, "peerGroupMemory",
-                                                       ents * sizeof(struct
-                                                                     peer_group));
-                                       }
+                               ents = listcount(bgp->peer);
+                               json_object_int_add(json, "peerCount", ents);
+                               json_object_int_add(json, "peerMemory",
+                                                   ents * sizeof(struct peer));
 
-                                       if (CHECK_FLAG(bgp->af_flags[afi][safi],
-                                                      BGP_CONFIG_DAMPENING))
-                                               json_object_boolean_true_add(
-                                                       json,
-                                                       "dampeningEnabled");
-                               } else {
-                                       if (bgp_maxmed_onstartup_configured(bgp)
-                                           && bgp->maxmed_active)
-                                               vty_out(vty,
-                                                       "Max-med on-startup active\n");
-                                       if (bgp->v_maxmed_admin)
-                                               vty_out(vty,
-                                                       "Max-med administrative active\n");
+                               if ((ents = listcount(bgp->group))) {
+                                       json_object_int_add(
+                                               json, "peerGroupCount", ents);
+                                       json_object_int_add(
+                                               json, "peerGroupMemory",
+                                               ents * sizeof(struct
+                                                             peer_group));
+                               }
 
+                               if (CHECK_FLAG(bgp->af_flags[afi][safi],
+                                              BGP_CONFIG_DAMPENING))
+                                       json_object_boolean_true_add(
+                                               json, "dampeningEnabled");
+                       } else {
+                               if (bgp_maxmed_onstartup_configured(bgp)
+                                   && bgp->maxmed_active)
                                        vty_out(vty,
-                                               "BGP table version %" PRIu64
-                                               "\n",
-                                               bgp_table_version(
-                                                       bgp->rib[afi][safi]));
-
-                                       ents = bgp_table_count(
-                                               bgp->rib[afi][safi]);
+                                               "Max-med on-startup active\n");
+                               if (bgp->v_maxmed_admin)
                                        vty_out(vty,
-                                               "RIB entries %ld, using %s of memory\n",
-                                               ents,
-                                               mtype_memstr(
-                                                       memstrbuf,
-                                                       sizeof(memstrbuf),
-                                                       ents * sizeof(struct
-                                                                     bgp_node)));
+                                               "Max-med administrative active\n");
+
+                               vty_out(vty, "BGP table version %" PRIu64 "\n",
+                                       bgp_table_version(bgp->rib[afi][safi]));
 
-                                       /* Peer related usage */
-                                       ents = listcount(bgp->peer);
+                               ents = bgp_table_count(bgp->rib[afi][safi]);
+                               vty_out(vty,
+                                       "RIB entries %ld, using %s of memory\n",
+                                       ents,
+                                       mtype_memstr(memstrbuf,
+                                                    sizeof(memstrbuf),
+                                                    ents * sizeof(struct
+                                                                  bgp_node)));
+
+                               /* Peer related usage */
+                               ents = listcount(bgp->peer);
+                               vty_out(vty, "Peers %ld, using %s of memory\n",
+                                       ents,
+                                       mtype_memstr(
+                                               memstrbuf, sizeof(memstrbuf),
+                                               ents * sizeof(struct peer)));
+
+                               if ((ents = listcount(bgp->group)))
                                        vty_out(vty,
-                                               "Peers %ld, using %s of memory\n",
+                                               "Peer groups %ld, using %s of memory\n",
                                                ents,
                                                mtype_memstr(
                                                        memstrbuf,
                                                        sizeof(memstrbuf),
                                                        ents * sizeof(struct
-                                                                     peer)));
+                                                                     peer_group)));
 
-                                       if ((ents = listcount(bgp->group)))
-                                               vty_out(vty,
-                                                       "Peer groups %ld, using %s of memory\n",
-                                                       ents,
-                                                       mtype_memstr(
-                                                               memstrbuf,
-                                                               sizeof(memstrbuf),
-                                                               ents * sizeof(struct
-                                                                             peer_group)));
-
-                                       if (CHECK_FLAG(bgp->af_flags[afi][safi],
-                                                      BGP_CONFIG_DAMPENING))
-                                               vty_out(vty,
-                                                       "Dampening enabled.\n");
-                                       vty_out(vty, "\n");
+                               if (CHECK_FLAG(bgp->af_flags[afi][safi],
+                                              BGP_CONFIG_DAMPENING))
+                                       vty_out(vty, "Dampening enabled.\n");
+                               vty_out(vty, "\n");
 
-                                       /* Subtract 8 here because 'Neighbor' is
-                                        * 8 characters */
-                                       vty_out(vty, "Neighbor");
-                                       vty_out(vty, "%*s",
-                                               max_neighbor_width - 8, " ");
-                                       vty_out(vty,
-                                               "V         AS MsgRcvd MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd\n");
-                               }
+                               /* Subtract 8 here because 'Neighbor' is
+                                * 8 characters */
+                               vty_out(vty, "Neighbor");
+                               vty_out(vty, "%*s", max_neighbor_width - 8,
+                                       " ");
+                               vty_out(vty,
+                                       "V         AS MsgRcvd MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd\n");
                        }
+               }
 
-                       count++;
-
-                       if (use_json) {
-                               json_peer = json_object_new_object();
-
-                               if (peer_dynamic_neighbor(peer))
-                                       json_object_boolean_true_add(
-                                               json_peer, "dynamicPeer");
+               count++;
 
-                               if (peer->hostname)
-                                       json_object_string_add(json_peer,
-                                                              "hostname",
-                                                              peer->hostname);
+               if (use_json) {
+                       json_peer = json_object_new_object();
+
+                       if (peer_dynamic_neighbor(peer))
+                               json_object_boolean_true_add(json_peer,
+                                                            "dynamicPeer");
+
+                       if (peer->hostname)
+                               json_object_string_add(json_peer, "hostname",
+                                                      peer->hostname);
+
+                       if (peer->domainname)
+                               json_object_string_add(json_peer, "domainname",
+                                                      peer->domainname);
+
+                       json_object_int_add(json_peer, "remoteAs", peer->as);
+                       json_object_int_add(json_peer, "version", 4);
+                       json_object_int_add(json_peer, "msgRcvd",
+                                           peer->open_in + peer->update_in
+                                                   + peer->keepalive_in
+                                                   + peer->notify_in
+                                                   + peer->refresh_in
+                                                   + peer->dynamic_cap_in);
+                       json_object_int_add(json_peer, "msgSent",
+                                           peer->open_out + peer->update_out
+                                                   + peer->keepalive_out
+                                                   + peer->notify_out
+                                                   + peer->refresh_out
+                                                   + peer->dynamic_cap_out);
+
+                       json_object_int_add(json_peer, "tableVersion",
+                                           peer->version[afi][safi]);
+                       json_object_int_add(json_peer, "outq",
+                                           peer->obuf->count);
+                       json_object_int_add(json_peer, "inq", 0);
+                       peer_uptime(peer->uptime, timebuf, BGP_UPTIME_LEN,
+                                   use_json, json_peer);
+                       json_object_int_add(json_peer, "prefixReceivedCount",
+                                           peer->pcount[afi][pfx_rcd_safi]);
 
-                               if (peer->domainname)
-                                       json_object_string_add(
-                                               json_peer, "domainname",
-                                               peer->domainname);
+                       if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
+                               json_object_string_add(json_peer, "state",
+                                                      "Idle (Admin)");
+                       else if (CHECK_FLAG(peer->sflags,
+                                           PEER_STATUS_PREFIX_OVERFLOW))
+                               json_object_string_add(json_peer, "state",
+                                                      "Idle (PfxCt)");
+                       else
+                               json_object_string_add(
+                                       json_peer, "state",
+                                       lookup_msg(bgp_status_msg, peer->status,
+                                                  NULL));
+
+                       if (peer->conf_if)
+                               json_object_string_add(json_peer, "idType",
+                                                      "interface");
+                       else if (peer->su.sa.sa_family == AF_INET)
+                               json_object_string_add(json_peer, "idType",
+                                                      "ipv4");
+                       else if (peer->su.sa.sa_family == AF_INET6)
+                               json_object_string_add(json_peer, "idType",
+                                                      "ipv6");
+
+                       json_object_object_add(json_peers, peer->host,
+                                              json_peer);
+               } else {
+                       memset(dn_flag, '\0', sizeof(dn_flag));
+                       if (peer_dynamic_neighbor(peer)) {
+                               dn_count++;
+                               dn_flag[0] = '*';
+                       }
 
-                               json_object_int_add(json_peer, "remoteAs",
-                                                   peer->as);
-                               json_object_int_add(json_peer, "version", 4);
-                               json_object_int_add(
-                                       json_peer, "msgRcvd",
-                                       peer->open_in + peer->update_in
-                                               + peer->keepalive_in
-                                               + peer->notify_in
-                                               + peer->refresh_in
-                                               + peer->dynamic_cap_in);
-                               json_object_int_add(
-                                       json_peer, "msgSent",
-                                       peer->open_out + peer->update_out
-                                               + peer->keepalive_out
-                                               + peer->notify_out
-                                               + peer->refresh_out
-                                               + peer->dynamic_cap_out);
-
-                               json_object_int_add(json_peer, "tableVersion",
-                                                   peer->version[afi][safi]);
-                               json_object_int_add(json_peer, "outq",
-                                                   peer->obuf->count);
-                               json_object_int_add(json_peer, "inq", 0);
+                       if (peer->hostname
+                           && bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME))
+                               len = vty_out(vty, "%s%s(%s)", dn_flag,
+                                             peer->hostname, peer->host);
+                       else
+                               len = vty_out(vty, "%s%s", dn_flag, peer->host);
+
+                       /* pad the neighbor column with spaces */
+                       if (len < max_neighbor_width)
+                               vty_out(vty, "%*s", max_neighbor_width - len,
+                                       " ");
+
+                       vty_out(vty, "4 %10u %7d %7d %8" PRIu64 " %4d %4zd %8s",
+                               peer->as,
+                               peer->open_in + peer->update_in
+                                       + peer->keepalive_in + peer->notify_in
+                                       + peer->refresh_in
+                                       + peer->dynamic_cap_in,
+                               peer->open_out + peer->update_out
+                                       + peer->keepalive_out + peer->notify_out
+                                       + peer->refresh_out
+                                       + peer->dynamic_cap_out,
+                               peer->version[afi][safi], 0, peer->obuf->count,
                                peer_uptime(peer->uptime, timebuf,
-                                           BGP_UPTIME_LEN, use_json,
-                                           json_peer);
-                               json_object_int_add(
-                                       json_peer, "prefixReceivedCount",
-                                       peer->pcount[afi][pfx_rcd_safi]);
+                                           BGP_UPTIME_LEN, 0, NULL));
 
+                       if (peer->status == Established)
+                               vty_out(vty, " %12ld",
+                                       peer->pcount[afi][pfx_rcd_safi]);
+                       else {
                                if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
-                                       json_object_string_add(json_peer,
-                                                              "state",
-                                                              "Idle (Admin)");
+                                       vty_out(vty, " Idle (Admin)");
                                else if (CHECK_FLAG(
                                                 peer->sflags,
                                                 PEER_STATUS_PREFIX_OVERFLOW))
-                                       json_object_string_add(json_peer,
-                                                              "state",
-                                                              "Idle (PfxCt)");
+                                       vty_out(vty, " Idle (PfxCt)");
                                else
-                                       json_object_string_add(
-                                               json_peer, "state",
+                                       vty_out(vty, " %12s",
                                                lookup_msg(bgp_status_msg,
                                                           peer->status, NULL));
-
-                               if (peer->conf_if)
-                                       json_object_string_add(json_peer,
-                                                              "idType",
-                                                              "interface");
-                               else if (peer->su.sa.sa_family == AF_INET)
-                                       json_object_string_add(
-                                               json_peer, "idType", "ipv4");
-                               else if (peer->su.sa.sa_family == AF_INET6)
-                                       json_object_string_add(
-                                               json_peer, "idType", "ipv6");
-
-                               json_object_object_add(json_peers, peer->host,
-                                                      json_peer);
-                       } else {
-                               memset(dn_flag, '\0', sizeof(dn_flag));
-                               if (peer_dynamic_neighbor(peer)) {
-                                       dn_count++;
-                                       dn_flag[0] = '*';
-                               }
-
-                               if (peer->hostname
-                                   && bgp_flag_check(bgp,
-                                                     BGP_FLAG_SHOW_HOSTNAME))
-                                       len = vty_out(vty, "%s%s(%s)", dn_flag,
-                                                     peer->hostname,
-                                                     peer->host);
-                               else
-                                       len = vty_out(vty, "%s%s", dn_flag,
-                                                     peer->host);
-
-                               /* pad the neighbor column with spaces */
-                               if (len < max_neighbor_width)
-                                       vty_out(vty, "%*s",
-                                               max_neighbor_width - len, " ");
-
-                               vty_out(vty, "4 %10u %7d %7d %8" PRIu64
-                                            " %4d %4zd %8s",
-                                       peer->as,
-                                       peer->open_in + peer->update_in
-                                               + peer->keepalive_in
-                                               + peer->notify_in
-                                               + peer->refresh_in
-                                               + peer->dynamic_cap_in,
-                                       peer->open_out + peer->update_out
-                                               + peer->keepalive_out
-                                               + peer->notify_out
-                                               + peer->refresh_out
-                                               + peer->dynamic_cap_out,
-                                       peer->version[afi][safi], 0,
-                                       peer->obuf->count,
-                                       peer_uptime(peer->uptime, timebuf,
-                                                   BGP_UPTIME_LEN, 0, NULL));
-
-                               if (peer->status == Established)
-                                       vty_out(vty, " %12ld",
-                                               peer->pcount[afi]
-                                                           [pfx_rcd_safi]);
-                               else {
-                                       if (CHECK_FLAG(peer->flags,
-                                                      PEER_FLAG_SHUTDOWN))
-                                               vty_out(vty, " Idle (Admin)");
-                                       else if (
-                                               CHECK_FLAG(
-                                                       peer->sflags,
-                                                       PEER_STATUS_PREFIX_OVERFLOW))
-                                               vty_out(vty, " Idle (PfxCt)");
-                                       else
-                                               vty_out(vty, " %12s",
-                                                       lookup_msg(
-                                                               bgp_status_msg,
-                                                               peer->status,
-                                                               NULL));
-                               }
-                               vty_out(vty, "\n");
                        }
+                       vty_out(vty, "\n");
                }
        }
 
@@ -7528,6 +7521,12 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
                                                             "defaultNotSent");
                }
 
+               if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
+                       if (p->bgp->advertise_all_vni)
+                               json_object_boolean_true_add(
+                                       json_addr, "advertiseAllVnis");
+               }
+
                if (filter->plist[FILTER_IN].name
                    || filter->dlist[FILTER_IN].name
                    || filter->aslist[FILTER_IN].name
@@ -7793,6 +7792,12 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
                                vty_out(vty, " default not sent\n");
                }
 
+               /* advertise-vni-all */
+               if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
+                       if (p->bgp->advertise_all_vni)
+                               vty_out(vty, "  advertise-all-vni\n");
+               }
+
                if (filter->plist[FILTER_IN].name
                    || filter->dlist[FILTER_IN].name
                    || filter->aslist[FILTER_IN].name
@@ -8577,6 +8582,41 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
                                        json_cap, "multiprotocolExtensions",
                                        json_multi);
 
+                               /* Hostname capabilities */
+                               json_object *json_hname = NULL;
+
+                               json_hname = json_object_new_object();
+
+                               if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV)) {
+                                       json_object_string_add(
+                                               json_hname, "advHostName",
+                                               bgp->peer_self->hostname
+                                                       ? bgp->peer_self
+                                                                 ->hostname
+                                                       : "n/a");
+                                       json_object_string_add(
+                                               json_hname, "advDomainName",
+                                               bgp->peer_self->domainname
+                                                       ? bgp->peer_self
+                                                                 ->domainname
+                                                       : "n/a");
+                               }
+
+
+                               if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_RCV)) {
+                                       json_object_string_add(
+                                               json_hname, "rcvHostName",
+                                               p->hostname ? p->hostname
+                                                           : "n/a");
+                                       json_object_string_add(
+                                               json_hname, "rcvDomainName",
+                                               p->domainname ? p->domainname
+                                                             : "n/a");
+                               }
+
+                               json_object_object_add(json_cap, "hostName",
+                                                      json_hname);
+
                                /* Gracefull Restart */
                                if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)
                                    || CHECK_FLAG(p->cap,
@@ -8910,25 +8950,36 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json,
                                                }
 
                                /* Hostname capability */
-                               if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV)
-                                   || CHECK_FLAG(p->cap,
-                                                 PEER_CAP_HOSTNAME_RCV)) {
+                               vty_out(vty, "    Hostname Capability:");
+
+                               if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV)) {
                                        vty_out(vty,
-                                               "    Hostname Capability:");
-                                       if (CHECK_FLAG(p->cap,
-                                                      PEER_CAP_HOSTNAME_ADV))
-                                               vty_out(vty, " advertised");
-                                       if (CHECK_FLAG(p->cap,
-                                                      PEER_CAP_HOSTNAME_RCV))
-                                               vty_out(vty, " %sreceived",
-                                                       CHECK_FLAG(
-                                                               p->cap,
-                                                               PEER_CAP_HOSTNAME_ADV)
-                                                               ? "and "
-                                                               : "");
-                                       vty_out(vty, "\n");
+                                               " advertised (name: %s,domain name: %s)",
+                                               bgp->peer_self->hostname
+                                                       ? bgp->peer_self
+                                                                 ->hostname
+                                                       : "n/a",
+                                               bgp->peer_self->domainname
+                                                       ? bgp->peer_self
+                                                                 ->domainname
+                                                       : "n/a");
+                               } else {
+                                       vty_out(vty, " not advertised");
                                }
 
+                               if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_RCV)) {
+                                       vty_out(vty,
+                                               " received (name: %s,domain name: %s)",
+                                               p->hostname ? p->hostname
+                                                           : "n/a",
+                                               p->domainname ? p->domainname
+                                                             : "n/a");
+                               } else {
+                                       vty_out(vty, " not received");
+                               }
+
+                               vty_out(vty, "\n");
+
                                /* Gracefull Restart */
                                if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)
                                    || CHECK_FLAG(p->cap,
@@ -11041,14 +11092,14 @@ DEFUN (no_bgp_redistribute_ipv6,
        return bgp_redistribute_unset(bgp, AFI_IP6, type, 0);
 }
 
-int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
-                                 safi_t safi, int *write)
+void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
+                                  safi_t safi)
 {
        int i;
 
        /* Unicast redistribution only.  */
        if (safi != SAFI_UNICAST)
-               return 0;
+               return;
 
        for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
                /* Redistribute BGP does not make sense.  */
@@ -11062,11 +11113,6 @@ int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
                                continue;
 
                        for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
-                               /* Display "address-family" when it is not yet
-                                * diplayed.  */
-                               bgp_config_write_family_header(vty, afi, safi,
-                                                              write);
-
                                /* "redistribute" configuration.  */
                                vty_out(vty, "  redistribute %s",
                                        zebra_route_string(i));
@@ -11082,7 +11128,6 @@ int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
                        }
                }
        }
-       return *write;
 }
 
 /* BGP node structure. */
@@ -12264,6 +12309,9 @@ void bgp_vty_init(void)
        /* "show [ip] bgp memory" commands. */
        install_element(VIEW_NODE, &show_bgp_memory_cmd);
 
+       /* "show bgp martian next-hop" */
+       install_element(VIEW_NODE, &show_bgp_martian_nexthop_db_cmd);
+
        /* "show [ip] bgp views" commands. */
        install_element(VIEW_NODE, &show_bgp_views_cmd);
 
index 62bc27d5073df9ff1301956b52ba9bd23d4c04e7..59bc0126615486b558de24fad308f9844b44f25e 100644 (file)
@@ -46,10 +46,10 @@ struct bgp;
 extern void bgp_vty_init(void);
 extern const char *afi_safi_print(afi_t, safi_t);
 extern const char *afi_safi_json(afi_t, safi_t);
-extern int bgp_config_write_update_delay(struct vty *, struct bgp *);
-extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
-extern int bgp_config_write_listen(struct vty *vty, struct bgp *bgp);
-extern int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp);
+extern void bgp_config_write_update_delay(struct vty *, struct bgp *);
+extern void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
+extern void bgp_config_write_listen(struct vty *vty, struct bgp *bgp);
+extern void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp);
 extern int bgp_vty_return(struct vty *vty, int ret);
 extern struct peer *peer_and_group_lookup_vty(struct vty *vty,
                                              const char *peer_str);
index 9a092404d58297b539508a0c0e9452c09b9fa5f8..8b9d55295d123b863226e4833cdc8a25f7519024 100644 (file)
@@ -1022,7 +1022,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
         * in
         * the RIB */
        if (info->sub_type == BGP_ROUTE_AGGREGATE)
-               SET_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE);
+               zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
 
        if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
            || info->sub_type == BGP_ROUTE_AGGREGATE) {
@@ -1152,7 +1152,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
        if (has_valid_label)
                SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
 
-       if (!CHECK_FLAG(api.flags, ZEBRA_FLAG_BLACKHOLE))
+       if (info->sub_type != BGP_ROUTE_AGGREGATE)
                api.nexthop_num = valid_nh_count;
 
        SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
index 11405d1c1b47569f6e024a3e4978669b50cbce10..7d37864f44a8cce16d32064a8dfbc77cadf002fc 100644 (file)
 extern void bgp_zebra_init(struct thread_master *master);
 extern void bgp_zebra_destroy(void);
 extern int bgp_if_update_all(void);
-extern int bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t,
-                                    int *);
-extern int bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
-                                        safi_t, int *);
+extern void bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t,
+                                     safi_t);
+extern void bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t,
+                                         safi_t);
 extern void bgp_zebra_announce(struct bgp_node *, struct prefix *,
                               struct bgp_info *, struct bgp *, afi_t, safi_t);
 extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t);
index 92121f6aef249441784bc32bbb7618ffe1aa3325..1e7111a01bf89a3924bf3eaee5198f42cd1dfaed 100644 (file)
@@ -2816,6 +2816,21 @@ static struct bgp *bgp_create(as_t *as, const char *name,
                XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
        bgp->peer_self->host =
                XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
+       if (bgp->peer_self->hostname != NULL) {
+               XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->hostname);
+               bgp->peer_self->hostname = NULL;
+       }
+       if (cmd_hostname_get())
+               bgp->peer_self->hostname =
+                       XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_hostname_get());
+
+       if (bgp->peer_self->domainname != NULL) {
+               XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->domainname);
+               bgp->peer_self->domainname = NULL;
+       }
+       if (cmd_domainname_get())
+               bgp->peer_self->domainname =
+                       XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_domainname_get());
        bgp->peer = list_new();
        bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
        bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same, NULL);
@@ -2988,6 +3003,7 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
        bgp = bgp_create(as, name, inst_type);
        bgp_router_id_set(bgp, &bgp->router_id_zebra);
        bgp_address_init(bgp);
+       bgp_tip_hash_init(bgp);
        bgp_scan_init(bgp);
        *bgp_val = bgp;
 
@@ -3069,6 +3085,9 @@ void bgp_instance_down(struct bgp *bgp)
 
        /* Purge network and redistributed routes. */
        bgp_purge_static_redist_routes(bgp);
+
+       /* Cleanup registered nexthops (flags) */
+       bgp_cleanup_nexthops(bgp);
 }
 
 /* Delete BGP instance. */
@@ -3200,6 +3219,7 @@ void bgp_free(struct bgp *bgp)
 
        bgp_scan_finish(bgp);
        bgp_address_destroy(bgp);
+       bgp_tip_hash_destroy(bgp);
 
        bgp_evpn_cleanup(bgp);
 
@@ -6184,14 +6204,8 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, u_char use_json,
        return buf;
 }
 
-#define afi_header_vty_out(vty, afi, safi, write, format, ...) \
-       do { \
-               bgp_config_write_family_header(vty, afi, safi, write); \
-               vty_out(vty, format, ## __VA_ARGS__); \
-       } while (0)
-
 static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
-                                   afi_t afi, safi_t safi, int *write)
+                                   afi_t afi, safi_t safi)
 {
        struct bgp_filter *filter;
        struct bgp_filter *gfilter = NULL;
@@ -6210,16 +6224,13 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
                if (!gfilter || !gfilter->dlist[in].name
                    || strcmp(filter->dlist[in].name, gfilter->dlist[in].name)
                               != 0) {
-                       afi_header_vty_out(
-                               vty, afi, safi, write,
-                               "  neighbor %s distribute-list %s in\n", addr,
-                               filter->dlist[in].name);
+                       vty_out(vty, "  neighbor %s distribute-list %s in\n",
+                               addr, filter->dlist[in].name);
                }
 
        if (filter->dlist[out].name && !gfilter) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s distribute-list %s out\n",
-                                  addr, filter->dlist[out].name);
+               vty_out(vty, "  neighbor %s distribute-list %s out\n", addr,
+                       filter->dlist[out].name);
        }
 
        /* prefix-list. */
@@ -6227,19 +6238,17 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
                if (!gfilter || !gfilter->plist[in].name
                    || strcmp(filter->plist[in].name, gfilter->plist[in].name)
                               != 0) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                          "  neighbor %s prefix-list %s in\n",
-                                          addr, filter->plist[in].name);
+                       vty_out(vty, "  neighbor %s prefix-list %s in\n", addr,
+                               filter->plist[in].name);
                }
 
-       if (filter->plist[out].name)
-               if (!gfilter || !gfilter->plist[out].name
-                   || strcmp(filter->plist[out].name, gfilter->plist[out].name)
-                               != 0) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                           "  neighbor %s prefix-list %s out\n",
-                                           addr, filter->plist[out].name);
-                }
+       if (filter->plist[out].name)
+               if (!gfilter || !gfilter->plist[out].name
+                   || strcmp(filter->plist[out].name, gfilter->plist[out].name)
+                              != 0) {
+                       vty_out(vty, "  neighbor %s prefix-list %s out\n", addr,
+                               filter->plist[out].name);
+               }
 
        /* route-map. */
        if (filter->map[RMAP_IN].name)
@@ -6247,9 +6256,8 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
                    || strcmp(filter->map[RMAP_IN].name,
                              gfilter->map[RMAP_IN].name)
                               != 0) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                          "  neighbor %s route-map %s in\n",
-                                          addr, filter->map[RMAP_IN].name);
+                       vty_out(vty, "  neighbor %s route-map %s in\n", addr,
+                               filter->map[RMAP_IN].name);
                }
 
        if (filter->map[RMAP_OUT].name)
@@ -6257,16 +6265,14 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
                    || strcmp(filter->map[RMAP_OUT].name,
                              gfilter->map[RMAP_OUT].name)
                               != 0) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                          "  neighbor %s route-map %s out\n",
-                                          addr, filter->map[RMAP_OUT].name);
+                       vty_out(vty, "  neighbor %s route-map %s out\n", addr,
+                               filter->map[RMAP_OUT].name);
                }
 
        /* unsuppress-map */
        if (filter->usmap.name && !gfilter) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s unsuppress-map %s\n", addr,
-                                  filter->usmap.name);
+               vty_out(vty, "  neighbor %s unsuppress-map %s\n", addr,
+                       filter->usmap.name);
        }
 
        /* filter-list. */
@@ -6274,15 +6280,13 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
                if (!gfilter || !gfilter->aslist[in].name
                    || strcmp(filter->aslist[in].name, gfilter->aslist[in].name)
                               != 0) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                          "  neighbor %s filter-list %s in\n",
-                                          addr, filter->aslist[in].name);
+                       vty_out(vty, "  neighbor %s filter-list %s in\n", addr,
+                               filter->aslist[in].name);
                }
 
        if (filter->aslist[out].name && !gfilter) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s filter-list %s out\n", addr,
-                                  filter->aslist[out].name);
+               vty_out(vty, "  neighbor %s filter-list %s out\n", addr,
+                       filter->aslist[out].name);
        }
 }
 
@@ -6602,8 +6606,7 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
 
 /* BGP peer configuration display function. */
 static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
-                                    struct peer *peer, afi_t afi, safi_t safi,
-                                    int *write)
+                                    struct peer *peer, afi_t afi, safi_t safi)
 {
        struct peer *g_peer = NULL;
        char *addr;
@@ -6626,36 +6629,29 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                /* If the peer-group is active but peer is not, print a 'no
                 * activate' */
                if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                          "  no neighbor %s activate\n", addr);
+                       vty_out(vty, "  no neighbor %s activate\n", addr);
                }
 
                /* If the peer-group is not active but peer is, print an
                   'activate' */
                else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                          "  neighbor %s activate\n", addr);
+                       vty_out(vty, "  neighbor %s activate\n", addr);
                }
        } else {
                if (peer->afc[afi][safi]) {
                        if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
                                if (bgp_flag_check(bgp,
                                                   BGP_FLAG_NO_DEFAULT_IPV4)) {
-                                       afi_header_vty_out(
-                                               vty, afi, safi, write,
-                                               "  neighbor %s activate\n",
+                                       vty_out(vty, "  neighbor %s activate\n",
                                                addr);
                                }
                        } else
-                               afi_header_vty_out(vty, afi, safi, write,
-                                                  "  neighbor %s activate\n",
-                                                  addr);
+                               vty_out(vty, "  neighbor %s activate\n", addr);
                } else {
                        if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
                                if (!bgp_flag_check(bgp,
                                                    BGP_FLAG_NO_DEFAULT_IPV4)) {
-                                       afi_header_vty_out(
-                                               vty, afi, safi, write,
+                                       vty_out(vty,
                                                "  no neighbor %s activate\n",
                                                addr);
                                }
@@ -6666,25 +6662,20 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
        /* addpath TX knobs */
        if (peergroup_af_flag_check(peer, afi, safi,
                                    PEER_FLAG_ADDPATH_TX_ALL_PATHS)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s addpath-tx-all-paths\n",
-                                  addr);
+               vty_out(vty, "  neighbor %s addpath-tx-all-paths\n", addr);
        }
 
        if (peergroup_af_flag_check(peer, afi, safi,
                                    PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s addpath-tx-bestpath-per-AS\n",
-                                  addr);
+               vty_out(vty, "  neighbor %s addpath-tx-bestpath-per-AS\n",
+                       addr);
        }
 
        /* ORF capability.  */
        if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
            || peergroup_af_flag_check(peer, afi, safi,
                                       PEER_FLAG_ORF_PREFIX_RM)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s capability orf prefix-list",
-                                  addr);
+               vty_out(vty, "  neighbor %s capability orf prefix-list", addr);
 
                if (peergroup_af_flag_check(peer, afi, safi,
                                            PEER_FLAG_ORF_PREFIX_SM)
@@ -6702,57 +6693,46 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
        /* Route reflector client. */
        if (peergroup_af_flag_check(peer, afi, safi,
                                    PEER_FLAG_REFLECTOR_CLIENT)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s route-reflector-client\n",
-                                  addr);
+               vty_out(vty, "  neighbor %s route-reflector-client\n", addr);
        }
 
        /* next-hop-self force */
        if (peergroup_af_flag_check(peer, afi, safi,
                                    PEER_FLAG_FORCE_NEXTHOP_SELF)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s next-hop-self force\n", addr);
+               vty_out(vty, "  neighbor %s next-hop-self force\n", addr);
        }
 
        /* next-hop-self */
        if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s next-hop-self\n", addr);
+               vty_out(vty, "  neighbor %s next-hop-self\n", addr);
        }
 
        /* remove-private-AS */
        if (peergroup_af_flag_check(peer, afi, safi,
                                    PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) {
-               afi_header_vty_out(
-                       vty, afi, safi, write,
-                       "  neighbor %s remove-private-AS all replace-AS\n",
+               vty_out(vty, "  neighbor %s remove-private-AS all replace-AS\n",
                        addr);
        }
 
        else if (peergroup_af_flag_check(peer, afi, safi,
                                         PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) {
-               afi_header_vty_out(
-                       vty, afi, safi, write,
-                       "  neighbor %s remove-private-AS replace-AS\n", addr);
+               vty_out(vty, "  neighbor %s remove-private-AS replace-AS\n",
+                       addr);
        }
 
        else if (peergroup_af_flag_check(peer, afi, safi,
                                         PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s remove-private-AS all\n",
-                                  addr);
+               vty_out(vty, "  neighbor %s remove-private-AS all\n", addr);
        }
 
        else if (peergroup_af_flag_check(peer, afi, safi,
                                         PEER_FLAG_REMOVE_PRIVATE_AS)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s remove-private-AS\n", addr);
+               vty_out(vty, "  neighbor %s remove-private-AS\n", addr);
        }
 
        /* as-override */
        if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s as-override\n", addr);
+               vty_out(vty, "  neighbor %s as-override\n", addr);
        }
 
        /* send-community print. */
@@ -6764,27 +6744,21 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                    && peergroup_af_flag_check(
                               peer, afi, safi,
                               PEER_FLAG_SEND_LARGE_COMMUNITY)) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                          "  neighbor %s send-community all\n",
-                                          addr);
+                       vty_out(vty, "  neighbor %s send-community all\n",
+                               addr);
                } else if (peergroup_af_flag_check(
                                   peer, afi, safi,
                                   PEER_FLAG_SEND_LARGE_COMMUNITY)) {
-                       afi_header_vty_out(
-                               vty, afi, safi, write,
-                               "  neighbor %s send-community large\n", addr);
+                       vty_out(vty, "  neighbor %s send-community large\n",
+                               addr);
                } else if (peergroup_af_flag_check(
                                   peer, afi, safi,
                                   PEER_FLAG_SEND_EXT_COMMUNITY)) {
-                       afi_header_vty_out(
-                               vty, afi, safi, write,
-                               "  neighbor %s send-community extended\n",
+                       vty_out(vty, "  neighbor %s send-community extended\n",
                                addr);
                } else if (peergroup_af_flag_check(peer, afi, safi,
                                                   PEER_FLAG_SEND_COMMUNITY)) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                          "  neighbor %s send-community\n",
-                                          addr);
+                       vty_out(vty, "  neighbor %s send-community\n", addr);
                }
        } else {
                if (!peer_af_flag_check(peer, afi, safi,
@@ -6801,9 +6775,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                    && (!g_peer || peer_af_flag_check(
                                           g_peer, afi, safi,
                                           PEER_FLAG_SEND_LARGE_COMMUNITY))) {
-                       afi_header_vty_out(
-                               vty, afi, safi, write,
-                               "  no neighbor %s send-community all\n", addr);
+                       vty_out(vty, "  no neighbor %s send-community all\n",
+                               addr);
                } else {
                        if (!peer_af_flag_check(peer, afi, safi,
                                                PEER_FLAG_SEND_LARGE_COMMUNITY)
@@ -6811,8 +6784,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                                || peer_af_flag_check(
                                           g_peer, afi, safi,
                                           PEER_FLAG_SEND_LARGE_COMMUNITY))) {
-                               afi_header_vty_out(
-                                       vty, afi, safi, write,
+                               vty_out(vty,
                                        "  no neighbor %s send-community large\n",
                                        addr);
                        }
@@ -6823,8 +6795,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                                || peer_af_flag_check(
                                           g_peer, afi, safi,
                                           PEER_FLAG_SEND_EXT_COMMUNITY))) {
-                               afi_header_vty_out(
-                                       vty, afi, safi, write,
+                               vty_out(vty,
                                        "  no neighbor %s send-community extended\n",
                                        addr);
                        }
@@ -6834,8 +6805,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                            && (!g_peer || peer_af_flag_check(
                                                   g_peer, afi, safi,
                                                   PEER_FLAG_SEND_COMMUNITY))) {
-                               afi_header_vty_out(
-                                       vty, afi, safi, write,
+                               vty_out(vty,
                                        "  no neighbor %s send-community\n",
                                        addr);
                        }
@@ -6853,8 +6823,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                    || (peer->default_rmap[afi][safi].name
                        && strcmp(peer->default_rmap[afi][safi].name,
                                  g_peer->default_rmap[afi][safi].name))))) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s default-originate", addr);
+               vty_out(vty, "  neighbor %s default-originate", addr);
                if (peer->default_rmap[afi][safi].name)
                        vty_out(vty, " route-map %s",
                                peer->default_rmap[afi][safi].name);
@@ -6863,9 +6832,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
 
        /* Soft reconfiguration inbound. */
        if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) {
-               afi_header_vty_out(
-                       vty, afi, safi, write,
-                       "  neighbor %s soft-reconfiguration inbound\n", addr);
+               vty_out(vty, "  neighbor %s soft-reconfiguration inbound\n",
+                       addr);
        }
 
        /* maximum-prefix. */
@@ -6878,9 +6846,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                                  PEER_FLAG_MAX_PREFIX_WARNING)
                               != CHECK_FLAG(peer->af_flags[afi][safi],
                                             PEER_FLAG_MAX_PREFIX_WARNING)) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                          "  neighbor %s maximum-prefix %lu",
-                                          addr, peer->pmax[afi][safi]);
+                       vty_out(vty, "  neighbor %s maximum-prefix %lu", addr,
+                               peer->pmax[afi][safi]);
                        if (peer->pmax_threshold[afi][safi]
                            != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
                                vty_out(vty, " %u",
@@ -6897,16 +6864,13 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
        /* Route server client. */
        if (peergroup_af_flag_check(peer, afi, safi,
                                    PEER_FLAG_RSERVER_CLIENT)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s route-server-client\n", addr);
+               vty_out(vty, "  neighbor %s route-server-client\n", addr);
        }
 
        /* Nexthop-local unchanged. */
        if (peergroup_af_flag_check(peer, afi, safi,
                                    PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
-               afi_header_vty_out(vty, afi, safi, write,
-                                  "  neighbor %s nexthop-local unchanged\n",
-                                  addr);
+               vty_out(vty, "  neighbor %s nexthop-local unchanged\n", addr);
        }
 
        /* allowas-in <1-10> */
@@ -6917,14 +6881,11 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                    || peer->allowas_in[afi][safi]
                               != g_peer->allowas_in[afi][safi]) {
                        if (peer->allowas_in[afi][safi] == 3) {
-                               afi_header_vty_out(vty, afi, safi, write,
-                                                  "  neighbor %s allowas-in\n",
-                                                  addr);
+                               vty_out(vty, "  neighbor %s allowas-in\n",
+                                       addr);
                        } else {
-                               afi_header_vty_out(
-                                       vty, afi, safi, write,
-                                       "  neighbor %s allowas-in %d\n", addr,
-                                       peer->allowas_in[afi][safi]);
+                               vty_out(vty, "  neighbor %s allowas-in %d\n",
+                                       addr, peer->allowas_in[afi][safi]);
                        }
                }
        }
@@ -6935,9 +6896,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                if (!peer_group_active(peer)
                    || !peer_af_flag_check(g_peer, afi, safi,
                                           PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
-                       afi_header_vty_out(vty, afi, safi, write,
-                                          "  neighbor %s allowas-in origin\n",
-                                          addr);
+                       vty_out(vty, "  neighbor %s allowas-in origin\n", addr);
                }
        }
 
@@ -6947,15 +6906,13 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                    || !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT)
                    || peer->weight[afi][safi] != g_peer->weight[afi][safi]) {
                        if (peer->weight[afi][safi]) {
-                               afi_header_vty_out(vty, afi, safi, write,
-                                                  "  neighbor %s weight %lu\n",
-                                                  addr,
-                                                  peer->weight[afi][safi]);
+                               vty_out(vty, "  neighbor %s weight %lu\n", addr,
+                                       peer->weight[afi][safi]);
                        }
                }
 
        /* Filter. */
-       bgp_config_write_filter(vty, peer, afi, safi, write);
+       bgp_config_write_filter(vty, peer, afi, safi);
 
        /* atribute-unchanged. */
        if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ||
@@ -6970,18 +6927,15 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                     peergroup_af_flag_check(peer, afi, safi,
                                             PEER_FLAG_MED_UNCHANGED)) {
 
-                       afi_header_vty_out(
-                               vty, afi, safi, write,
+                       vty_out(vty,
                                "  neighbor %s attribute-unchanged%s%s%s\n",
                                addr,
-                               peer_af_flag_check(
-                                       peer, afi, safi,
-                                       PEER_FLAG_AS_PATH_UNCHANGED)
+                               peer_af_flag_check(peer, afi, safi,
+                                                  PEER_FLAG_AS_PATH_UNCHANGED)
                                        ? " as-path"
                                        : "",
-                               peer_af_flag_check(
-                                       peer, afi, safi,
-                                       PEER_FLAG_NEXTHOP_UNCHANGED)
+                               peer_af_flag_check(peer, afi, safi,
+                                                  PEER_FLAG_NEXTHOP_UNCHANGED)
                                        ? " next-hop"
                                        : "",
                                peer_af_flag_check(peer, afi, safi,
@@ -6992,64 +6946,52 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
        }
 }
 
-/* Display "address-family" configuration header. */
-void bgp_config_write_family_header(struct vty *vty, afi_t afi, safi_t safi,
-                                   int *write)
+/* Address family based peer configuration display.  */
+static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
+                                   safi_t safi)
 {
-       if (*write)
-               return;
+       struct peer *peer;
+       struct peer_group *group;
+       struct listnode *node, *nnode;
 
-       vty_out(vty, " !\n address-family ");
 
+       vty_frame(vty, " !\n address-family ");
        if (afi == AFI_IP) {
                if (safi == SAFI_UNICAST)
-                       vty_out(vty, "ipv4 unicast");
+                       vty_frame(vty, "ipv4 unicast");
                else if (safi == SAFI_LABELED_UNICAST)
-                       vty_out(vty, "ipv4 labeled-unicast");
+                       vty_frame(vty, "ipv4 labeled-unicast");
                else if (safi == SAFI_MULTICAST)
-                       vty_out(vty, "ipv4 multicast");
+                       vty_frame(vty, "ipv4 multicast");
                else if (safi == SAFI_MPLS_VPN)
-                       vty_out(vty, "ipv4 vpn");
+                       vty_frame(vty, "ipv4 vpn");
                else if (safi == SAFI_ENCAP)
-                       vty_out(vty, "ipv4 encap");
+                       vty_frame(vty, "ipv4 encap");
        } else if (afi == AFI_IP6) {
                if (safi == SAFI_UNICAST)
-                       vty_out(vty, "ipv6 unicast");
+                       vty_frame(vty, "ipv6 unicast");
                else if (safi == SAFI_LABELED_UNICAST)
-                       vty_out(vty, "ipv6 labeled-unicast");
+                       vty_frame(vty, "ipv6 labeled-unicast");
                else if (safi == SAFI_MULTICAST)
-                       vty_out(vty, "ipv6 multicast");
+                       vty_frame(vty, "ipv6 multicast");
                else if (safi == SAFI_MPLS_VPN)
-                       vty_out(vty, "ipv6 vpn");
+                       vty_frame(vty, "ipv6 vpn");
                else if (safi == SAFI_ENCAP)
-                       vty_out(vty, "ipv6 encap");
+                       vty_frame(vty, "ipv6 encap");
        } else if (afi == AFI_L2VPN) {
                if (safi == SAFI_EVPN)
-                       vty_out(vty, "l2vpn evpn");
+                       vty_frame(vty, "l2vpn evpn");
        }
-       vty_out(vty, "\n");
-
-       *write = 1;
-}
-
-/* Address family based peer configuration display.  */
-static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
-                                  safi_t safi)
-{
-       int write = 0;
-       struct peer *peer;
-       struct peer_group *group;
-       struct listnode *node, *nnode;
+       vty_frame(vty, "\n");
 
-       bgp_config_write_distance(vty, bgp, afi, safi, &write);
+       bgp_config_write_distance(vty, bgp, afi, safi);
 
-       bgp_config_write_network(vty, bgp, afi, safi, &write);
+       bgp_config_write_network(vty, bgp, afi, safi);
 
-       bgp_config_write_redistribute(vty, bgp, afi, safi, &write);
+       bgp_config_write_redistribute(vty, bgp, afi, safi);
 
        for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
-               bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi,
-                                        &write);
+               bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi);
 
        for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
                /* Skip dynamic neighbors. */
@@ -7058,20 +7000,16 @@ static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
 
                /* Do not display doppelganger peers */
                if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
-                       bgp_config_write_peer_af(vty, bgp, peer, afi, safi,
-                                                &write);
+                       bgp_config_write_peer_af(vty, bgp, peer, afi, safi);
        }
 
-       bgp_config_write_maxpaths(vty, bgp, afi, safi, &write);
-       bgp_config_write_table_map(vty, bgp, afi, safi, &write);
+       bgp_config_write_maxpaths(vty, bgp, afi, safi);
+       bgp_config_write_table_map(vty, bgp, afi, safi);
 
        if (safi == SAFI_EVPN)
-               bgp_config_write_evpn_info(vty, bgp, afi, safi, &write);
-
-       if (write)
-               vty_out(vty, " exit-address-family\n");
+               bgp_config_write_evpn_info(vty, bgp, afi, safi);
 
-       return write;
+       vty_endframe(vty, " exit-address-family\n");
 }
 
 int bgp_config_write(struct vty *vty)
@@ -7099,11 +7037,11 @@ int bgp_config_write(struct vty *vty)
                vty_out(vty, "bgp route-map delay-timer %u\n",
                        bm->rmap_update_timer);
 
+       if (write)
+               vty_out(vty, "!\n");
+
        /* BGP configuration. */
        for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
-               if (write)
-                       vty_out(vty, "!\n");
-
                /* Router bgp ASN */
                vty_out(vty, "router bgp %u", bgp->as);
 
@@ -7323,54 +7261,46 @@ int bgp_config_write(struct vty *vty)
                        vty_out(vty, " no auto-summary\n");
 
                /* IPv4 unicast configuration.  */
-               write +=
-                       bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
+               bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
 
                /* IPv4 multicast configuration.  */
-               write += bgp_config_write_family(vty, bgp, AFI_IP,
-                                                SAFI_MULTICAST);
+               bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MULTICAST);
 
                /* IPv4 labeled-unicast configuration.  */
-               write += bgp_config_write_family(vty, bgp, AFI_IP,
-                                                SAFI_LABELED_UNICAST);
+               bgp_config_write_family(vty, bgp, AFI_IP, SAFI_LABELED_UNICAST);
 
                /* IPv4 VPN configuration.  */
-               write += bgp_config_write_family(vty, bgp, AFI_IP,
-                                                SAFI_MPLS_VPN);
+               bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MPLS_VPN);
 
                /* ENCAPv4 configuration.  */
-               write += bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
+               bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
 
                /* IPv6 unicast configuration.  */
-               write += bgp_config_write_family(vty, bgp, AFI_IP6,
-                                                SAFI_UNICAST);
+               bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_UNICAST);
 
                /* IPv6 multicast configuration.  */
-               write += bgp_config_write_family(vty, bgp, AFI_IP6,
-                                                SAFI_MULTICAST);
+               bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MULTICAST);
 
                /* IPv6 labeled-unicast configuration.  */
-               write += bgp_config_write_family(vty, bgp, AFI_IP6,
-                                                SAFI_LABELED_UNICAST);
+               bgp_config_write_family(vty, bgp, AFI_IP6,
+                                       SAFI_LABELED_UNICAST);
 
                /* IPv6 VPN configuration.  */
-               write += bgp_config_write_family(vty, bgp, AFI_IP6,
-                                                SAFI_MPLS_VPN);
+               bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
 
                /* ENCAPv6 configuration.  */
-               write += bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
+               bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
 
                /* EVPN configuration.  */
-               write +=
-                       bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
+               bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
 
 #if ENABLE_BGP_VNC
-               write += bgp_rfapi_cfg_write(vty, bgp);
+               bgp_rfapi_cfg_write(vty, bgp);
 #endif
 
-               write++;
+               vty_out(vty, "!\n");
        }
-       return write;
+       return 0;
 }
 
 void bgp_master_init(struct thread_master *master)
index 5ede9ba13d645aefd41dd2576bad32153afb16e5..00fce72124b8b456037cbb5b3e8b3a78695505d0 100644 (file)
@@ -318,6 +318,10 @@ struct bgp {
 
        struct hash *address_hash;
 
+       /* DB for all local tunnel-ips - used mainly for martian checks
+          Currently it only has all VxLan tunnel IPs*/
+       struct hash *tip_hash;
+
        /* Static route configuration.  */
        struct bgp_table *route[AFI_MAX][SAFI_MAX];
 
@@ -1234,7 +1238,6 @@ extern void peer_xfer_config(struct peer *dst, struct peer *src);
 extern char *peer_uptime(time_t, char *, size_t, u_char, json_object *);
 
 extern int bgp_config_write(struct vty *);
-extern void bgp_config_write_family_header(struct vty *, afi_t, safi_t, int *);
 
 extern void bgp_master_init(struct thread_master *master);
 
index c8e2dd95254eddd31f34070036d3c2544c421061..e3b446f76ad69b862f860529aaeaffcf39b972c2 100644 (file)
@@ -2977,11 +2977,6 @@ DEFUN_NOSH (vnc_vrf_policy,
        struct rfapi_nve_group_cfg *rfg;
        VTY_DECLVAR_CONTEXT(bgp, bgp);
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        /* Search for name */
        rfg = bgp_rfapi_cfg_match_byname(bgp, argv[1]->arg,
                                         RFAPI_GROUP_CFG_VRF);
@@ -3012,10 +3007,6 @@ DEFUN (vnc_no_vrf_policy,
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
        return bgp_rfapi_delete_named_nve_group(vty, bgp, argv[2]->arg,
                                                RFAPI_GROUP_CFG_VRF);
 }
@@ -3031,11 +3022,6 @@ DEFUN (vnc_vrf_policy_label,
        uint32_t label;
        VTY_DECLVAR_CONTEXT(bgp, bgp);
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        /* make sure it's still in list */
        if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) {
                /* Not in list anymore */
@@ -3145,11 +3131,6 @@ DEFUN (vnc_vrf_policy_rt_import,
        int is_export_bgp = 0;
        int is_export_zebra = 0;
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        /* make sure it's still in list */
        if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) {
                /* Not in list anymore */
@@ -3213,11 +3194,6 @@ DEFUN (vnc_vrf_policy_rt_export,
        VTY_DECLVAR_CONTEXT(bgp, bgp);
        int rc;
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        /* make sure it's still in list */
        if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) {
                /* Not in list anymore */
@@ -3253,11 +3229,6 @@ DEFUN (vnc_vrf_policy_rt_both,
        struct listnode *node;
        struct rfapi_rfg_name *rfgn;
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        /* make sure it's still in list */
        if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) {
                /* Not in list anymore */
@@ -3333,11 +3304,6 @@ DEFUN (vnc_vrf_policy_rd,
        VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg);
        VTY_DECLVAR_CONTEXT(bgp, bgp);
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        /* make sure it's still in list */
        if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) {
                /* Not in list anymore */
@@ -3420,11 +3386,6 @@ DEFUN_NOSH (vnc_l2_group,
        struct rfapi_l2_group_cfg *rfg;
        VTY_DECLVAR_CONTEXT(bgp, bgp);
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        /* Search for name */
        rfg = rfapi_l2_group_lookup_byname(bgp, argv[1]->arg);
 
@@ -3505,10 +3466,6 @@ DEFUN (vnc_no_l2_group,
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
        return bgp_rfapi_delete_named_l2_group(vty, bgp, argv[3]->arg);
 }
 
@@ -3522,11 +3479,6 @@ DEFUN (vnc_l2_group_lni,
        VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg);
        VTY_DECLVAR_CONTEXT(bgp, bgp);
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        /* make sure it's still in list */
        if (!listnode_lookup(bgp->rfapi_cfg->l2_groups, rfg)) {
                /* Not in list anymore */
@@ -3549,11 +3501,6 @@ DEFUN (vnc_l2_group_labels,
        VTY_DECLVAR_CONTEXT(bgp, bgp);
        struct list *ll;
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        /* make sure it's still in list */
        if (!listnode_lookup(bgp->rfapi_cfg->l2_groups, rfg)) {
                /* Not in list anymore */
@@ -3589,11 +3536,6 @@ DEFUN (vnc_l2_group_no_labels,
        VTY_DECLVAR_CONTEXT(bgp, bgp);
        struct list *ll;
 
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        /* make sure it's still in list */
        if (!listnode_lookup(bgp->rfapi_cfg->l2_groups, rfg)) {
                /* Not in list anymore */
@@ -3646,10 +3588,6 @@ DEFUN (vnc_l2_group_rt,
                vty_out(vty, "Unknown option, %s\n", argv[1]->arg);
                return CMD_ERR_NO_MATCH;
        }
-       if (!bgp) {
-               vty_out(vty, "No BGP process is configured\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
 
        /* make sure it's still in list */
        if (!listnode_lookup(bgp->rfapi_cfg->l2_groups, rfg)) {
index d63975a22bff02105ede300fb0d467b0dbfd905f..3f427c39031ee336ec05c1b44fda998dadc3c392 100644 (file)
@@ -3875,10 +3875,9 @@ rfapiBgpInfoFilteredImportFunction(safi_t safi)
 
        default:
                /* not expected */
+               zlog_err("%s: bad safi %d", __func__, safi);
                return NULL;
        }
-       zlog_err("%s: bad safi %d", __func__, safi);
-       return NULL;
 }
 
 void rfapiProcessUpdate(struct peer *peer,
index bf66e00f9fbcb9b0e3220d08816a87eb011cc2bd..fb73583c28bc9387355d31e8eed83170958ad2ac 100755 (executable)
@@ -195,6 +195,7 @@ fi
 
 dnl always want these CFLAGS
 AC_C_FLAG([-fno-omit-frame-pointer])
+AC_C_FLAG([-funwind-tables])
 AC_C_FLAG([-Wall])
 AC_C_FLAG([-Wextra])
 AC_C_FLAG([-Wmissing-prototypes])
@@ -320,6 +321,8 @@ AC_ARG_WITH(rfp-path,
   AS_HELP_STRING([--with-rfp-path[=DIR]],[path to replaced stub RFP used with BGP VNC]))
 AC_ARG_ENABLE(snmp,
   AS_HELP_STRING([--enable-snmp=ARG], [enable SNMP support (smux or agentx)]))
+AC_ARG_ENABLE(zeromq,
+  AS_HELP_STRING([--enable-zeromq], [enable ZeroMQ handler (libfrrzmq)]))
 AC_ARG_WITH(libpam,
   AS_HELP_STRING([--with-libpam], [use libpam for PAM support in vtysh]))
 AC_ARG_ENABLE(ospfapi,
@@ -1714,6 +1717,21 @@ AC_CHECK_HEADER([malloc.h],
   )
  ], [], FRR_INCLUDES)
 
+dnl ------
+dnl ZeroMQ
+dnl ------
+if test "x$enable_zeromq" != "xno"; then
+  PKG_CHECK_MODULES(ZEROMQ, [libzmq >= 4.0.0], [
+    AC_DEFINE(HAVE_ZEROMQ, 1, [Enable ZeroMQ support])
+    ZEROMQ=true
+  ], [
+    if test "x$enable_zeromq" = "xyes"; then
+      AC_MSG_ERROR([configuration specifies --enable-zeromq but libzmq was not found])
+    fi
+  ])
+fi
+AM_CONDITIONAL([ZEROMQ], test "x$ZEROMQ" = "xtrue")
+
 dnl ----------
 dnl configure date
 dnl ----------
@@ -1819,6 +1837,7 @@ AC_CONFIG_FILES([Makefile
          doc/watchfrr.8
          doc/zebra.8
          doc/frr.1
+         doc/frr-args.8
          pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh
          pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh
          pkgsrc/eigrpd.sh])
index 49aeb395bb3998f8b5ca981816c0041c7415da2d..8fc5fa5fa60f6133cf5623f324f52b4efa5f334f 100644 (file)
@@ -16,6 +16,7 @@ usr/share/man/man8/ripngd.8
 usr/share/man/man8/zebra.8
 usr/share/man/man8/isisd.8
 usr/share/man/man8/watchfrr.8
+usr/share/man/man8/frr-args.8
 usr/share/snmp/mibs/
 tools/etc/* etc/
 tools/*.service    lib/systemd/system
index 9016df73724e9af9f5171c0d1de1f61490131e42..7d31e4cc476a2215112ede33c9d250d61b869b2b 100644 (file)
@@ -52,7 +52,7 @@ info_TEXINFOS = frr.texi
 # because it cant just work from the png's directly it seems - contrary
 # to the documentation...
 frr.pdf: $(info_TEXINFOS) $(figures_pdf) $(frr_TEXINFOS) defines.texi
-       $(TEXI2PDF) -o "$@" $<
+       $(TEXI2PDF) -o "$@" $< || true
 
 # don't ask me why the info file is in srcdir
 $(srcdir)/frr.info: $(frr_TEXINFOS) defines.texi
@@ -79,7 +79,7 @@ frr_TEXINFOS = appendix.texi basic.texi bgpd.texi isisd.texi filter.texi \
 .dia.png:
        $(DIATOPNG) "$@" $<
 
-man_MANS = frr.1
+man_MANS = frr.1 frr-args.8
 
 if PIMD
 man_MANS += pimd.8
index d6b07a270fdd717ec69f7ebe99e0ef45abc2f118..8e0da129493bd1d007fd3728aa8c9d423e756996 100644 (file)
@@ -698,11 +698,8 @@ This command is deprecated and may be removed in a future release. Its
 use should be avoided.
 @end deffn
 
-@c for some reason, using [all] here triggers a bug in texinfo...
-@deffn {BGP} {neighbor @var{peer} next-hop-self} {}
-@deffnx {BGP} {no neighbor @var{peer} next-hop-self} {}
-@deffnx {BGP} {neighbor @var{peer} next-hop-self all} {}
-@deffnx {BGP} {no neighbor @var{peer} next-hop-self all} {}
+@deffn {BGP} {neighbor @var{peer} next-hop-self [all]} {}
+@deffnx {BGP} {no neighbor @var{peer} next-hop-self [all]} {}
 This command specifies an announced route's nexthop as being equivalent
 to the address of the bgp router if it is learned via eBGP.
 If the optional keyword @code{all} is specified the modifiation is done
diff --git a/doc/frr-args.8.in b/doc/frr-args.8.in
new file mode 100644 (file)
index 0000000..3dc84e1
--- /dev/null
@@ -0,0 +1,248 @@
+.TH frr-args 8 "28 August 2017" "@PACKAGE_FULLNAME@ general options" "Version @PACKAGE_VERSION@"
+.SH NAME
+frr-args \- common command line options for all @PACKAGE_FULLNAME@ daemons.
+.SH SYNOPSIS
+<\fBzebra\fR|\fBbgpd\fR|\fB...\fR>
+[\fB\-h\fR] [\fB\-v\fR]
+
+<\fBzebra\fR|\fBbgpd\fR|\fB...\fR>
+[\fB\-d\fR|\fB\-t\fR|\fB\-dt\fR]
+[\fB\-C\fR]
+[\fB\-f\fR \fIconfig-file\fR]
+[\fB\-i\fR \fIpid-file\fR]
+[\fB\-z\fR \fIzclient-path\fR]
+[\fB\-u\fR \fIuser\fR]
+[\fB\-g\fR \fIgroup\fR]
+[\fB\-A\fR \fIvty-addr\fR]
+[\fB\-P\fR \fIvty-port\fR]
+[\fB\-M\fR \fImodule\fR[\fB:\fIoptions\fR]]
+[\fB\-N\fR \fIpathspace\fR]
+[\fB\-\-vty_socket\fR \fIvty-path\fR]
+[\fB\-\-moduledir\fR \fImodule-path\fR]
+
+.SH DESCRIPTION
+@PACKAGE_NAME@ daemons share a large part of their command line options;
+this man page documents these.  For options on specific daemons please refer
+to their respective man pages.  Most of the common options are related to
+process control, configuration and common library functionality.
+
+.SH HELP AND VERSION
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print a short description of the daemon's command line options.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print version and build information for the daemon.
+.PP
+Both of these options inhibit normal operation and will immediately exit.
+
+.SH PROCESS CONTROL
+These options control background operation:
+.TP
+\fB\-d\fR, \fB\-\-daemon\fR
+Launches the process in background/daemon mode, forking and detaching from
+the terminal.
+
+The parent process will delay its exit until the daemon/child has finished
+its initialization and has entered its main loop.  This is important for
+\fBzebra\fR startup because the other daemons will attempt to connect to
+\fBzebra\fR.  A return from \fBzebra -d\fR guarantees its readiness to
+accept these connections.
+.TP
+\fB\-t\fR, \fB\-\-terminal\fR
+Opens an interactive VTY session on the terminal, allowing for both state
+and configuration operations.  Note that the terminal starts operating after
+startup has completed and the configuration file has been loaded.
+
+The process will exit when end of file is detected on the terminal.  It is
+possible to daemonize a process started with \fB-t\fR (but without \fB-d\fR)
+by sending \fISIGQUIT\fR to the process (normally mapped to a \fI^\\\fR
+keypress.)
+.TP
+\fB\-dt\fR, \fB\-\-daemon \-\-terminal\fR
+This combination of the previous two options will delay the daemon from
+going into background until the terminal session ends (by end of file.)
+
+If the process receives \fISIGINT\fR (e.g. a \fI^C\fR keypress) in this
+mode, it will exit instead of daemonizing.
+.PP
+It is safe to suspend (\fISIGTSTP\fR / \fI^Z\fR) the terminal session
+opened by the previous two options;  this will only stop the terminal but
+not the protocol daemon itself (which runs in a separate second process.)
+
+.SH CONFIGURATION AND PATHS
+The following options control configuration and file system locations for
+@PACKAGE_NAME@ processes:
+.TP
+\fB\-f\fR, \fB\-\-config_file\fR \fIconfig-file\fR
+Specify a configuration file to be used instead of the default 
+\fB\fI@CFG_SYSCONF@/<daemon>.conf\fR file.
+
+Note that the daemon will attempt to write to this file if the
+\fIwrite file\fR command is issued on its VTY interface or through
+\fBvtysh\fR.
+.TP
+\fB\-C\fR, \fB\-\-dryrun\fR
+Load the configuration file and check its validity, then exit.
+.TP
+\fB\-i\fR, \fB\-\-pid_file\fR \fIpid-file\fR
+Output a pid file to a location other than the default 
+\fB\fI@CFG_STATE@/<daemon>.pid\fR.
+.TP
+\fB\-z\fR, \fB\-\-socket\fR \fIzclient-path\fR
+Override the path of the ZAPI socket used to communicate between \fBzebra\fR
+and the various protocol daemons. The default is
+\fB\fI@CFG_STATE@/zserv.api\fR.  The value of this option must be the same
+across all daemons.
+.TP
+\fB\-N\fR, \fB\-\-pathspace\fR \fIpathspace\fR
+Insert \fIpathspace\fR into all default paths, changing the defaults to:
+.IP
+\fB@CFG_SYSCONF@/\fIpathspace\fB/<daemon>.conf\fR
+.br
+\fB@CFG_STATE@/\fIpathspace\fB/<daemon>.pid\fR
+.br
+\fB@CFG_STATE@/\fIpathspace\fB/<daemon>.vty\fR
+.br
+\fB@CFG_STATE@/\fIpathspace\fB/zserv.api\fR
+
+\'.\' and \'/\' characters will not be accepted in \fIpathspace\fR, but the
+empty string will be accepted.
+
+Note that this only changes the respective defaults, it has no effect on
+the respective path if the \fB\-f\fR, \fB\-i\fR, \fB\-z\fR or
+\fB\-\-vty_socket\fR options are used.
+
+The purpose of this option is to easily group all file system related
+bits together for running multiple fully-separate "logical routers" on a
+system, particularly with Linux network namespaces.  Groups of daemons
+running with distinct \fIpathspace\fR values will be completely unaware
+of each other and not interact in any way.
+
+This option does not do any system setup (like network namespaces.) This
+must be done by the user, for example by running:
+.IP
+\fBip netns exec \fInamespace \fB<daemon> -N \fInamespace\fR
+
+.SH PROCESS CREDENTIALS
+.TP
+\fB\-u\fR, \fB\-\-user\fR \fIuser\fR
+(default: \fB@enable_user@\fR)
+.TP
+\fB\-g\fR, \fB\-\-group\fR \fIgroup\fR
+(default: \fB@enable_group@\fR)
+.IP
+Change the user/group which the daemon will switch to.
+.PP
+Note that there is an additional group, \fB@enable_vty_group@\fR, which
+controls group ownership of the VTY sockets.  The name of this group cannot
+currently be changed, and \fIuser\fR must be a member of this group.
+
+.SH VTY SETUP
+These following options control the daemon's VTY (interactive command line)
+interface.  The interface is available over TCP, using the telnet protocol,
+as well as through the \fBvtysh\fR frontend.
+.TP
+\fB\-A\fR, \fB--vty_addr\fR \fIvty-addr\fR
+Specify an IP/IPv6 address to bind the TCP VTY interface to.  It is
+generally recommended to specify \fI::1\fR or \fI127.0.0.1\fR.  For reasons
+of backwards compatibility, the default is to listen on all interfaces.
+.TP
+\fB\-P\fR, \fB--vty_port\fR \fIvty-port\fR
+Override the daemon's default TCP VTY port (each daemon has a different
+default value upwards of 2600, listed below.)  Specifying \fI0\fR disables
+the TCP VTY interface.
+
+Default ports are:
+
+.ta 16m
+zebra  2601
+.br
+ripd   2602
+.br
+ripngd 2603
+.br
+ospfd  2604
+.br
+bgpd   2605
+.br
+ospf6d 2606
+.br
+isisd  2608
+.br
+babeld 2609
+.br
+nhrpd  2610
+.br
+pimd   2611
+.br
+ldpd   2612
+.br
+eigrpd 2613
+
+Port 2607 is used for ospfd's Opaque LSA API, while port 2600 is used for
+the (insecure) TCP-ZEBRA interface.
+.TP
+\fB\-\-vty_socket\fR \fIvty-path\fR
+Overrides the directory used for the \fB<daemon>.vty\fR sockets.
+\fBvtysh\fR connects to these sockets in order to access each daemon's
+VTY.
+.br
+Default: \fB\fI@CFG_STATE@\fR[\fB/\fI<pathspace>\fR]
+
+NB: Unlike the other options, this option specifies a \fBdirectory\fR,
+not a full path.
+
+This option is primarily used by the SNAP packaging system, its semantics
+may change.  It should not be neccessary in most other scenarios.
+
+.SH MODULE LOADING
+@PACKAGE_NAME@ supports optional dynamically loadable modules, although
+these can only be loaded at startup.  The set of available modules may vary
+across distributions and packages, and modules may be available for
+installation as separate packages.
+.TP
+\fB\-M\fR, \fB\-\-module\fR \fImodule\fR[\fB:\fIoptions\fR]
+Load a module named \fImodule\fR, optionally passing \fIoptions\fR to it.
+
+If there is a \'/\' character in \fImodule\fR, the value is assumed to be
+a pathname to a module.
+
+If there is no \'/\' character, the module directory (see next option)
+is searched first for a module named "\fI<daemon>\fB_\fI<module>\fB.so\fR",
+then for "\fI<module>\fB.so\fR".
+This allows for a module to exist in variations appropriate for particular
+daemons, e.g. \fIzebra_snmp\fR and \fIbgp_snmp\fR, with the correct one
+selected by \fI\-M snmp\fR.
+
+The meaning of \fIoptions\fR is specific to the module being loaded.  Most
+modules currently ignore it.
+
+Modules are loaded in the order as listed on the command line.  This is
+not generally relevant.
+.TP
+\fB\-\-moduledir\fR \fImodule-path\fR
+Look for modules in the \fImodule-path\fR directory instead of the default
+\fI@CFG_MODULE@\fR.  (This path is \fBnot\fR affected by the \fB\-N\fR
+option.)
+.PP
+The list of loaded modules can be inspected at runtime with the
+\fBshow modules\fR VTY command.
+
+
+.SH "SEE ALSO"
+.BR zebra (8),
+.BR vtysh (1),
+.BR ripd (8),
+.BR ripngd (8),
+.BR ospfd (8),
+.BR ospf6d (8),
+.BR bgpd (8),
+.BR isisd (8),
+.BR babeld (8),
+.BR nhrpd (8),
+.BR pimd (8),
+.BR ldpd (8),
+.BR eigrpd (8)
+
+\fIhttps://frrouting.org/
index 265d6295efe961a62c9255e4d0501674c58db000..9e2ca5e506e9ebe10b7174d03491c751fbedbfe8 100644 (file)
@@ -65,6 +65,17 @@ Up or down the current interface.
 Set the IPv4 or IPv6 address/prefix for the interface.
 @end deffn
 
+@deffn {Interface Command} {ip address @var{local-addr} peer @var{peer-addr/prefix}} {}
+@deffnx {Interface Command} {no ip address @var{local-addr} peer @var{peer-addr/prefix}} {}
+Configure an IPv4 Pointopoint address on the interface.
+(The concept of PtP addressing does not exist for IPv6.)
+
+@var{local-addr} has no subnet mask since the local side in PtP
+addressing is always a single (/32) address.  @var{peer-addr/prefix}
+can be an arbitrary subnet behind the other end of the link (or even on the
+link in Point-to-Multipoint setups), though generally /32s are used.
+@end deffn
+
 @deffn {Interface Command} {ip address @var{address/prefix} secondary} {}
 @deffnx {Interface Command} {no ip address @var{address/prefix} secondary} {}
 Set the secondary flag for this address. This causes ospfd to not treat the
index 74515c98cb6a23d3556a0b30bdc71e627bcb1fb3..98c72668fc6aab2fd4708859508847dee06b038d 100644 (file)
@@ -295,11 +295,13 @@ void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn)
 
        vty_out(vty, "%s, ",
                prefix2str(tn->destination, buffer, PREFIX_STRLEN));
-       vty_out(vty, "%u successors, ", successors->count);
+       vty_out(vty, "%u successors, ",
+               (successors) ? successors->count : 0);
        vty_out(vty, "FD is %u, serno: %" PRIu64 " \n", tn->fdistance,
                tn->serno);
 
-       list_delete(successors);
+       if (successors)
+               list_delete(successors);
 }
 
 void show_ip_eigrp_neighbor_entry(struct vty *vty, struct eigrp *eigrp,
index ef10ebf54c7f59ea57b111470ed13fa84ac67252..49647c6b85bbff60e48d383e0cddab69a723bb04 100644 (file)
@@ -412,11 +412,15 @@ void eigrp_sw_version_initialize(void)
 {
        char ver_string[] = VERSION;
        char *dash = strstr(ver_string, "-");
+       int ret;
 
        if (dash)
                dash[0] = '\0';
 
-       sscanf(ver_string, "%d.%d", &FRR_MAJOR, &FRR_MINOR);
+       ret = sscanf(ver_string, "%d.%d", &FRR_MAJOR, &FRR_MINOR);
+       if (ret != 2)
+               zlog_err("Did not Properly parse %s, please fix VERSION string",
+                        VERSION);
 }
 
 /**
index aa5951600250081076d7e17ddb27dd55f5342e5b..ee3e2217b38beb7bc6316274b3e6c6b2082f5ac5 100644 (file)
@@ -249,15 +249,14 @@ int eigrp_if_up(struct eigrp_interface *ei)
        struct eigrp_metrics metric;
        struct eigrp_interface *ei2;
        struct listnode *node, *nnode;
-       struct eigrp *eigrp = eigrp_lookup();
+       struct eigrp *eigrp;
 
        if (ei == NULL)
                return 0;
 
-       if (eigrp != NULL)
-               eigrp_adjust_sndbuflen(eigrp, ei->ifp->mtu);
-       else
-               zlog_warn("%s: eigrp_lookup () returned NULL", __func__);
+       eigrp = ei->eigrp;
+       eigrp_adjust_sndbuflen(eigrp, ei->ifp->mtu);
+
        eigrp_if_stream_set(ei);
 
        /* Set multicast memberships appropriately for new state. */
index 68e7cdcbbe7086dcbfb43eaa93bc164ae3ade225..8a7d4d958714aed4b41ff8cda2e52b79292e2562 100644 (file)
@@ -193,6 +193,12 @@ int eigrp_check_md5_digest(struct stream *s,
        if (keychain)
                key = key_lookup_for_send(keychain);
 
+       if (!key) {
+               zlog_warn("Interface %s: Expected key value not found in config",
+                         nbr->ei->ifp->name);
+               return 0;
+       }
+
        memset(&ctx, 0, sizeof(ctx));
        MD5Init(&ctx);
 
@@ -229,8 +235,7 @@ int eigrp_check_md5_digest(struct stream *s,
        }
 
        /* save neighbor's crypt_seqnum */
-       if (nbr)
-               nbr->crypt_seqnum = authTLV->key_sequence;
+       nbr->crypt_seqnum = authTLV->key_sequence;
 
        return 1;
 }
@@ -240,10 +245,11 @@ int eigrp_make_sha256_digest(struct eigrp_interface *ei, struct stream *s,
 {
        struct key *key = NULL;
        struct keychain *keychain;
-       char *source_ip;
+       char source_ip[PREFIX_STRLEN];
 
        unsigned char digest[EIGRP_AUTH_TYPE_SHA256_LEN];
        unsigned char buffer[1 + PLAINTEXT_LENGTH + 45 + 1] = {0};
+
        HMAC_SHA256_CTX ctx;
        void *ibuf;
        size_t backup_get, backup_end;
@@ -263,11 +269,13 @@ int eigrp_make_sha256_digest(struct eigrp_interface *ei, struct stream *s,
        if (keychain)
                key = key_lookup_for_send(keychain);
 
-       //     saved_len[index] = strnzcpyn(saved_key[index], key,
-       //                             PLAINTEXT_LENGTH + 1);
+       if (!key) {
+               zlog_warn("Interface %s: Expected key value not found in config",
+                         ei->ifp->name);
+               return 0;
+       }
 
-       source_ip = calloc(16, sizeof(char));
-       inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, 16);
+       inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, PREFIX_STRLEN);
 
        memset(&ctx, 0, sizeof(ctx));
        buffer[0] = '\n';
@@ -287,7 +295,6 @@ int eigrp_make_sha256_digest(struct eigrp_interface *ei, struct stream *s,
        stream_set_endp(s, backup_end);
 
        eigrp_authTLV_SHA256_free(auth_TLV);
-       free(source_ip);
 
        return EIGRP_AUTH_TYPE_SHA256_LEN;
 }
@@ -613,10 +620,10 @@ int eigrp_read(struct thread *thread)
        opcode = eigrph->opcode;
 
        if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) {
-               char src[100], dst[100];
+               char src[PREFIX_STRLEN], dst[PREFIX_STRLEN];
 
-               strcpy(src, inet_ntoa(iph->ip_src));
-               strcpy(dst, inet_ntoa(iph->ip_dst));
+               strncpy(src, inet_ntoa(iph->ip_src), PREFIX_STRLEN);
+               strncpy(dst, inet_ntoa(iph->ip_dst), PREFIX_STRLEN);
                zlog_debug("Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
                           lookup_msg(eigrp_packet_type_str, opcode, NULL),
                           ntohl(eigrph->sequence), ntohl(eigrph->ack), length,
index b645ed198784babf9964edf5040c2e741d2a0c20..360e28adf704028367bc79a20fbd9a4b92c77a2d 100644 (file)
@@ -137,16 +137,19 @@ static int eigrp_route_match_add(struct vty *vty, struct route_map_index *index,
 {
        int ret;
        ret = route_map_add_match(index, command, arg);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% Can't find rule.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty, "%% Argument is malformed.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% Can't find rule.\n");
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty, "%% Argument is malformed.\n");
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               break;
        }
+
        return CMD_SUCCESS;
 }
 
@@ -157,16 +160,19 @@ static int eigrp_route_match_delete(struct vty *vty,
 {
        int ret;
        ret = route_map_delete_match(index, command, arg);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% Can't find rule.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty, "%% Argument is malformed.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% Can't find rule.\n");
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty, "%% Argument is malformed.\n");
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               break;
        }
+
        return CMD_SUCCESS;
 }
 
@@ -177,25 +183,27 @@ static int eigrp_route_set_add(struct vty *vty, struct route_map_index *index,
        int ret;
 
        ret = route_map_add_set(index, command, arg);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% Can't find rule.\n");
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% Can't find rule.\n");
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               /*
+                * rip, ripng and other protocols share the set metric command
+                * but only values from 0 to 16 are valid for rip and ripng
+                * if metric is out of range for rip and ripng, it is
+                * not for other protocols. Do not return an error
+                */
+               if (strcmp(command, "metric")) {
+                       vty_out(vty, "%% Argument is malformed.\n");
                        return CMD_WARNING_CONFIG_FAILED;
-               case RMAP_COMPILE_ERROR:
-                       /* rip, ripng and other protocols share the set metric
-                          command
-                          but only values from 0 to 16 are valid for rip and
-                          ripng
-                          if metric is out of range for rip and ripng, it is
-                          not for
-                          other protocols. Do not return an error */
-                       if (strcmp(command, "metric")) {
-                               vty_out(vty, "%% Argument is malformed.\n");
-                               return CMD_WARNING_CONFIG_FAILED;
-                       }
                }
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               break;
        }
+
        return CMD_SUCCESS;
 }
 
@@ -207,16 +215,19 @@ static int eigrp_route_set_delete(struct vty *vty,
        int ret;
 
        ret = route_map_delete_set(index, command, arg);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% Can't find rule.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty, "%% Argument is malformed.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% Can't find rule.\n");
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty, "%% Argument is malformed.\n");
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               break;
        }
+
        return CMD_SUCCESS;
 }
 
index 64e65b694cce8838dfd44de393cb22051b6c4fa3..8390bfc66ee606e4b7f11083f46dc958f923bcb2 100644 (file)
@@ -444,7 +444,7 @@ void eigrp_topology_update_node_flags(struct eigrp_prefix_entry *dest)
 
        for (ALL_LIST_ELEMENTS_RO(dest->entries, node, entry)) {
                if (((uint64_t)entry->distance
-                    <= (uint64_t)(dest->distance * eigrp->variance))
+                    <= (uint64_t)dest->distance * (uint64_t)eigrp->variance)
                    && entry->distance != EIGRP_MAX_METRIC) // is successor
                {
                        entry->flags |= EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
index d6a1134124f581adbdbfa44af97e9a56189753ae..430068496b1f2bcc93e7ba3fbf443c0bd0fd9136 100644 (file)
@@ -443,6 +443,9 @@ void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph,
 
        eigrp_query_send_all(eigrp);
        eigrp_update_send_all(eigrp, ei);
+
+       if (nbr_prefixes)
+               list_delete(nbr_prefixes);
 }
 
 /*send EIGRP Update packet*/
index dfd965bf6a1ef287a5147f329ec0dd029305e857..d4d3bb36926cee0267bc8b5437e9bc1551a4a9cc 100644 (file)
@@ -93,7 +93,7 @@ static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp)
        struct listnode *node;
 
        for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
-               vty_out(vty, "interface %s\n", ei->ifp->name);
+               vty_frame(vty, "interface %s\n", ei->ifp->name);
 
                if ((IF_DEF_PARAMS(ei->ifp)->auth_type)
                    == EIGRP_AUTH_TYPE_MD5) {
@@ -128,7 +128,7 @@ static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp)
                }
 
                /*Separate this EIGRP interface configuration from the others*/
-               vty_out(vty, "!\n");
+               vty_endframe(vty, "!\n");
        }
 
        return 0;
@@ -140,7 +140,7 @@ static int eigrp_write_interface(struct vty *vty)
        struct interface *ifp;
 
        for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
-               vty_out(vty, "interface %s\n", ifp->name);
+               vty_frame(vty, "interface %s\n", ifp->name);
 
                if (ifp->desc)
                        vty_out(vty, " description %s\n", ifp->desc);
@@ -157,7 +157,7 @@ static int eigrp_write_interface(struct vty *vty)
                        vty_out(vty, " ip hold-time eigrp %u\n",
                                IF_DEF_PARAMS(ifp)->v_wait);
 
-               vty_out(vty, "!\n");
+               vty_endframe(vty, "!\n");
        }
 
        return 0;
@@ -1267,7 +1267,11 @@ DEFUN (clear_ip_eigrp_neighbors_IP,
        struct eigrp_neighbor *nbr;
        struct in_addr nbr_addr;
 
-       inet_aton(argv[4]->arg, &nbr_addr);
+       if (!inet_aton(argv[4]->arg, &nbr_addr)) {
+               vty_out(vty, "Unable to parse %s",
+                       argv[4]->arg);
+               return CMD_WARNING;
+       }
 
        /* Check if eigrp process is enabled */
        eigrp = eigrp_lookup();
@@ -1370,7 +1374,11 @@ DEFUN (clear_ip_eigrp_neighbors_IP_soft,
        struct eigrp_neighbor *nbr;
        struct in_addr nbr_addr;
 
-       inet_aton(argv[4]->arg, &nbr_addr);
+       if (!inet_aton(argv[4]->arg, &nbr_addr)) {
+               vty_out(vty, "Unable to parse: %s",
+                       argv[4]->arg);
+               return CMD_WARNING;
+       }
 
        /* Check if eigrp process is enabled */
        eigrp = eigrp_lookup();
index a1aa87e396d15ecbfc7333a90eca2c6c12304a4a..7dd83039075b735ffab0a7602c4680a22237d954 100644 (file)
@@ -948,7 +948,7 @@ int isis_interface_config_write(struct vty *vty)
                        continue;
 
                /* IF name */
-               vty_out(vty, "interface %s\n", ifp->name);
+               vty_frame(vty, "interface %s\n", ifp->name);
                write++;
                /* IF desc */
                if (ifp->desc) {
@@ -1145,7 +1145,7 @@ int isis_interface_config_write(struct vty *vty)
                        }
                        write += circuit_write_mt_settings(circuit, vty);
                }
-               vty_out(vty, "!\n");
+               vty_endframe(vty, "!\n");
        }
 
        return write;
index 6fa7988304263020e6829f82fa4402eb436f7995..17b043444c47d05732634455173c0914392e828d 100644 (file)
@@ -146,6 +146,6 @@ void dynhn_print_all(struct vty *vty)
        }
 
        vty_out(vty, "     * %s %s\n", sysid_print(isis->sysid),
-               unix_hostname());
+               cmd_hostname_get());
        return;
 }
index 6bf6e45d9239b6253236ab8f4a3760701bca9dab..2e1e8e5fc367d6359ff784a1382d6d4aa29d05ab 100644 (file)
@@ -290,12 +290,21 @@ int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno,
        return LSP_OLDER;
 }
 
-static void put_lsp_hdr(struct isis_lsp *lsp, size_t *len_pointer)
+static void put_lsp_hdr(struct isis_lsp *lsp, size_t *len_pointer, bool keep)
 {
        uint8_t pdu_type =
                (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE : L2_LINK_STATE;
        struct isis_lsp_hdr *hdr = &lsp->hdr;
        struct stream *stream = lsp->pdu;
+       size_t orig_getp, orig_endp;
+
+       if (keep) {
+               orig_getp = stream_get_getp(lsp->pdu);
+               orig_endp = stream_get_endp(lsp->pdu);
+       }
+
+       stream_set_getp(lsp->pdu, 0);
+       stream_set_endp(lsp->pdu, 0);
 
        fill_fixed_hdr(pdu_type, stream);
 
@@ -307,6 +316,11 @@ static void put_lsp_hdr(struct isis_lsp *lsp, size_t *len_pointer)
        stream_putl(stream, hdr->seqno);
        stream_putw(stream, hdr->checksum);
        stream_putc(stream, hdr->lsp_bits);
+
+       if (keep) {
+               stream_set_endp(lsp->pdu, orig_endp);
+               stream_set_getp(lsp->pdu, orig_getp);
+       }
 }
 
 static void lsp_add_auth(struct isis_lsp *lsp)
@@ -325,8 +339,7 @@ static void lsp_pack_pdu(struct isis_lsp *lsp)
        lsp_add_auth(lsp);
 
        size_t len_pointer;
-       stream_reset(lsp->pdu);
-       put_lsp_hdr(lsp, &len_pointer);
+       put_lsp_hdr(lsp, &len_pointer, false);
        isis_pack_tlvs(lsp->tlvs, lsp->pdu, len_pointer, false, true);
 
        lsp->hdr.pdu_len = stream_get_endp(lsp->pdu);
@@ -457,16 +470,10 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
                lsp->own_lsp = 0;
        }
 
+       lsp_update_data(lsp, hdr, tlvs, stream, area, level);
        if (confusion) {
-               lsp_clear_data(lsp);
-               if (lsp->pdu != NULL)
-                       stream_free(lsp->pdu);
-               lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
-               lsp->age_out = ZERO_AGE_LIFETIME;
-               lsp->hdr.rem_lifetime = 0;
-               lsp_pack_pdu(lsp);
-       } else {
-               lsp_update_data(lsp, hdr, tlvs, stream, area, level);
+               lsp->hdr.rem_lifetime = hdr->rem_lifetime = 0;
+               put_lsp_hdr(lsp, NULL, true);
        }
 
        /* insert the lsp back into the database */
@@ -523,7 +530,7 @@ struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id,
        lsp->level = level;
        lsp->age_out = ZERO_AGE_LIFETIME;
        lsp_link_fragment(lsp, lsp0);
-       put_lsp_hdr(lsp, NULL);
+       put_lsp_hdr(lsp, NULL, false);
 
        if (isis->debugs & DEBUG_EVENTS)
                zlog_debug("New LSP with ID %s-%02x-%02x len %d seqnum %08x",
@@ -600,7 +607,7 @@ static void lspid_print(u_char *lsp_id, u_char *trg, char dynhost, char frag)
        if (dyn)
                sprintf((char *)id, "%.14s", dyn->hostname);
        else if (!memcmp(isis->sysid, lsp_id, ISIS_SYS_ID_LEN) && dynhost)
-               sprintf((char *)id, "%.14s", unix_hostname());
+               sprintf((char *)id, "%.14s", cmd_hostname_get());
        else
                memcpy(id, sysid_print(lsp_id), 15);
        if (frag)
@@ -880,9 +887,9 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area)
        }
        /* Dynamic Hostname */
        if (area->dynhostname) {
-               isis_tlvs_set_dynamic_hostname(lsp->tlvs, unix_hostname());
+               isis_tlvs_set_dynamic_hostname(lsp->tlvs, cmd_hostname_get());
                lsp_debug("ISIS (%s): Adding dynamic hostname '%s'",
-                         area->area_tag, unix_hostname());
+                         area->area_tag, cmd_hostname_get());
        } else {
                lsp_debug("ISIS (%s): Not adding dynamic hostname (disabled)",
                          area->area_tag);
index e8888a5f5bc0a379009a0bfa318b106cd9a57b09..0a1d9aaa1ac54117687e2c74bf8da332c5d39440 100644 (file)
@@ -431,24 +431,6 @@ struct in_addr newprefix2inaddr(u_char *prefix_start, u_char prefix_masklen)
        return new_prefix;
 }
 
-/*
- * Returns host.name if any, otherwise
- * it returns the system hostname.
- */
-const char *unix_hostname(void)
-{
-       static struct utsname names;
-       const char *hostname;
-
-       hostname = host.name;
-       if (!hostname) {
-               uname(&names);
-               hostname = names.nodename;
-       }
-
-       return hostname;
-}
-
 /*
  * Returns the dynamic hostname associated with the passed system ID.
  * If no dynamic hostname found then returns formatted system ID.
@@ -462,7 +444,7 @@ const char *print_sys_hostname(const u_char *sysid)
 
        /* For our system ID return our host name */
        if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
-               return unix_hostname();
+               return cmd_hostname_get();
 
        dyn = dynhn_find_by_id(sysid);
        if (dyn)
index 5a19a1ffa0debe6bd5d78df4c0e4bd8b3f0da7e9..b81db34df658be773755a736a2f05bea8985ab48 100644 (file)
@@ -56,7 +56,6 @@ void zlog_dump_data(void *data, int len);
  * misc functions
  */
 unsigned long isis_jitter(unsigned long timer, unsigned long jitter);
-const char *unix_hostname(void);
 
 /*
  * macros
index 9acbc21838459a5d9ace187ccb8789473be3bd84..bc852e209f2737fcc68f3b291add7e59f66971db 100644 (file)
@@ -1294,10 +1294,10 @@ static int isis_run_spf(struct isis_area *area, int level, int family,
        /*
         * C.2.7 Step 2
         */
-       if (isis_vertex_queue_count(&spftree->tents) == 0) {
+       if (!isis_vertex_queue_count(&spftree->tents)
+           && (isis->debugs & DEBUG_SPF_EVENTS)) {
                zlog_warn("ISIS-Spf: TENT is empty SPF-root:%s",
                          print_sys_hostname(sysid));
-               goto out;
        }
 
        while (isis_vertex_queue_count(&spftree->tents)) {
index 3d39a1ed529dbbbf0a936d30fb9777f5e583c670..bdc1d836db6bb89515589fa8e63ed7ceb08e3e76 100644 (file)
@@ -1441,7 +1441,7 @@ static int show_isis_database(struct vty *vty, const char *argv, int ui_level)
                                                lsp = lsp_search(
                                                        lspid,
                                                        area->lspdb[level]);
-                                       } else if (strncmp(unix_hostname(),
+                                       } else if (strncmp(cmd_hostname_get(),
                                                           sysid, 15)
                                                   == 0) {
                                                memcpy(lspid, isis->sysid,
index c86025a3bd12d0251f60ac12b1cfbcd3d944df7e..a3037813705b0d1e56324244fafa7cde97f14773 100644 (file)
@@ -125,6 +125,23 @@ vector cmdvec = NULL;
 /* Host information structure. */
 struct host host;
 
+/*
+ * Returns host.name if any, otherwise
+ * it returns the system hostname.
+ */
+const char *cmd_hostname_get(void)
+{
+       return host.name;
+}
+
+/*
+ * Returns unix domainname
+ */
+const char *cmd_domainname_get(void)
+{
+       return host.domainname;
+}
+
 /* Standard command node structures. */
 static struct cmd_node auth_node = {
        AUTH_NODE, "Password: ",
@@ -475,8 +492,8 @@ static char *zencrypt(const char *passwd)
 /* This function write configuration of this host. */
 static int config_write_host(struct vty *vty)
 {
-       if (host.name)
-               vty_out(vty, "hostname %s\n", host.name);
+       if (cmd_hostname_get())
+               vty_out(vty, "hostname %s\n", cmd_hostname_get());
 
        if (host.encrypt) {
                if (host.password_encrypt)
@@ -1411,7 +1428,7 @@ DEFUN (show_version,
        "Displays zebra version\n")
 {
        vty_out(vty, "%s %s (%s).\n", FRR_FULL_NAME, FRR_VERSION,
-               host.name ? host.name : "");
+               cmd_hostname_get() ? cmd_hostname_get() : "");
        vty_out(vty, "%s%s\n", FRR_COPYRIGHT, GIT_INFO);
        vty_out(vty, "configured with:\n    %s\n", FRR_CONFIG_ARGS);
 
@@ -1745,6 +1762,40 @@ DEFUN (show_startup_config,
        return CMD_SUCCESS;
 }
 
+int cmd_domainname_set(const char *domainname)
+{
+       XFREE(MTYPE_HOST, host.domainname);
+       host.domainname = domainname ? XSTRDUP(MTYPE_HOST, domainname) : NULL;
+       return CMD_SUCCESS;
+}
+
+/* Hostname configuration */
+DEFUN(config_domainname,
+      domainname_cmd,
+      "domainname WORD",
+      "Set system's domain name\n"
+      "This system's domain name\n")
+{
+       struct cmd_token *word = argv[1];
+
+       if (!isalpha((int)word->arg[0])) {
+               vty_out(vty, "Please specify string starting with alphabet\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       return cmd_domainname_set(word->arg);
+}
+
+DEFUN(config_no_domainname,
+      no_domainname_cmd,
+      "no domainname [DOMAINNAME]",
+      NO_STR
+      "Reset system's domain name\n"
+      "domain name of this router\n")
+{
+       return cmd_domainname_set(NULL);
+}
+
 int cmd_hostname_set(const char *hostname)
 {
        XFREE(MTYPE_HOST, host.name);
@@ -2515,9 +2566,12 @@ void install_default(enum node_type node)
  * terminal = -1 -- watchfrr / no logging, but minimal config control */
 void cmd_init(int terminal)
 {
+       struct utsname names;
+
        if (array_size(node_names) != NODE_TYPE_MAX)
                assert(!"Update the CLI node description array!");
 
+       uname(&names);
        qobj_init();
 
        varhandlers = list_new();
@@ -2526,7 +2580,15 @@ void cmd_init(int terminal)
        cmdvec = vector_init(VECTOR_MIN_SIZE);
 
        /* Default host value settings. */
-       host.name = NULL;
+       host.name = XSTRDUP(MTYPE_HOST, names.nodename);
+#ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME
+       if ((strcmp(names.domainname, "(none)") == 0))
+               host.domainname = NULL;
+       else
+               host.domainname = XSTRDUP(MTYPE_HOST, names.domainname);
+#else
+       host.domainname = NULL;
+#endif
        host.password = NULL;
        host.enable = NULL;
        host.logfile = NULL;
@@ -2579,6 +2641,8 @@ void cmd_init(int terminal)
 
        install_element(CONFIG_NODE, &hostname_cmd);
        install_element(CONFIG_NODE, &no_hostname_cmd);
+       install_element(CONFIG_NODE, &domainname_cmd);
+       install_element(CONFIG_NODE, &no_domainname_cmd);
        install_element(CONFIG_NODE, &frr_version_defaults_cmd);
        install_element(CONFIG_NODE, &debug_memstats_cmd);
 
@@ -2644,6 +2708,8 @@ void cmd_terminate()
 
        if (host.name)
                XFREE(MTYPE_HOST, host.name);
+       if (host.domainname)
+               XFREE(MTYPE_HOST, host.domainname);
        if (host.password)
                XFREE(MTYPE_HOST, host.password);
        if (host.password_encrypt)
index 8f12e2aabd108bd56b7cb4806c425570644ce9e5..1c6938523ccffd33699bc2d096d8da080084a768 100644 (file)
@@ -41,6 +41,9 @@ struct host {
        /* Host name of this router. */
        char *name;
 
+       /* Domainname of this router */
+       char *domainname;
+
        /* Password for vty interface. */
        char *password;
        char *password_encrypt;
@@ -398,7 +401,10 @@ extern void cmd_terminate(void);
 extern void cmd_exit(struct vty *vty);
 extern int cmd_list_cmds(struct vty *vty, int do_permute);
 
+extern int cmd_domainname_set(const char *domainname);
 extern int cmd_hostname_set(const char *hostname);
+extern const char *cmd_hostname_get(void);
+extern const char *cmd_domainname_get(void);
 
 /* NOT safe for general use; call this only if DEV_BUILD! */
 extern void grammar_sandbox_init(void);
diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c
new file mode 100644 (file)
index 0000000..861f7a5
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * libzebra ZeroMQ bindings
+ * Copyright (C) 2015  David Lamparter
+ *
+ * This program 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This program 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 <zmq.h>
+
+#include "thread.h"
+#include "memory.h"
+#include "frr_zmq.h"
+#include "log.h"
+
+DEFINE_MTYPE_STATIC(LIB, ZEROMQ_CB, "ZeroMQ callback")
+
+/* libzmq's context */
+void *frrzmq_context = NULL;
+static unsigned frrzmq_initcount = 0;
+
+void frrzmq_init(void)
+{
+       if (frrzmq_initcount++ == 0) {
+               frrzmq_context = zmq_ctx_new();
+               zmq_ctx_set(frrzmq_context, ZMQ_IPV6, 1);
+       }
+}
+
+void frrzmq_finish(void)
+{
+       if (--frrzmq_initcount == 0) {
+               zmq_ctx_term(frrzmq_context);
+               frrzmq_context = NULL;
+       }
+}
+
+/* read callback integration */
+struct frrzmq_cb {
+       struct thread *thread;
+       void *zmqsock;
+       void *arg;
+       int fd;
+
+       bool cancelled;
+
+       void (*cb_msg)(void *arg, void *zmqsock);
+       void (*cb_part)(void *arg, void *zmqsock,
+                       zmq_msg_t *msg, unsigned partnum);
+};
+
+
+static int frrzmq_read_msg(struct thread *t)
+{
+       struct frrzmq_cb *cb = THREAD_ARG(t);
+       zmq_msg_t msg;
+       unsigned partno;
+       int ret, more;
+       size_t moresz;
+
+       while (1) {
+               zmq_pollitem_t polli = {
+                       .socket = cb->zmqsock,
+                       .events = ZMQ_POLLIN
+               };
+               ret = zmq_poll(&polli, 1, 0);
+
+               if (ret < 0)
+                       goto out_err;
+               if (!(polli.revents & ZMQ_POLLIN))
+                       break;
+
+               if (cb->cb_msg) {
+                       cb->cb_msg(cb->arg, cb->zmqsock);
+
+                       if (cb->cancelled) {
+                               XFREE(MTYPE_ZEROMQ_CB, cb);
+                               return 0;
+                       }
+                       continue;
+               }
+
+               partno = 0;
+               if (zmq_msg_init(&msg))
+                       goto out_err;
+               do {
+                       ret = zmq_msg_recv(&msg, cb->zmqsock, ZMQ_NOBLOCK);
+                       if (ret < 0) {
+                               if (errno == EAGAIN)
+                                       break;
+
+                               zmq_msg_close(&msg);
+                               goto out_err;
+                       }
+
+                       cb->cb_part(cb->arg, cb->zmqsock, &msg, partno);
+                       if (cb->cancelled) {
+                               zmq_msg_close(&msg);
+                               XFREE(MTYPE_ZEROMQ_CB, cb);
+                               return 0;
+                       }
+
+                       /* cb_part may have read additional parts of the
+                        * message; don't use zmq_msg_more here */
+                       moresz = sizeof(more);
+                       more = 0;
+                       ret = zmq_getsockopt(cb->zmqsock, ZMQ_RCVMORE,
+                                            &more, &moresz);
+                       if (ret < 0) {
+                               zmq_msg_close(&msg);
+                               goto out_err;
+                       }
+
+                       partno++;
+               } while (more);
+               zmq_msg_close(&msg);
+       }
+
+       funcname_thread_add_read_write(THREAD_READ, t->master, frrzmq_read_msg,
+                       cb, cb->fd, &cb->thread, t->funcname, t->schedfrom,
+                       t->schedfrom_line);
+       return 0;
+
+out_err:
+       zlog_err("ZeroMQ error: %s(%d)", strerror (errno), errno);
+       return 0;
+}
+
+struct frrzmq_cb *funcname_frrzmq_thread_add_read(
+               struct thread_master *master,
+               void (*msgfunc)(void *arg, void *zmqsock),
+               void (*partfunc)(void *arg, void *zmqsock,
+                                zmq_msg_t *msg, unsigned partnum),
+               void *arg, void *zmqsock, debugargdef)
+{
+       int fd, events;
+       size_t len;
+       struct frrzmq_cb *cb;
+
+       if (!(msgfunc || partfunc) || (msgfunc && partfunc))
+               return NULL;
+       len = sizeof(fd);
+       if (zmq_getsockopt(zmqsock, ZMQ_FD, &fd, &len))
+               return NULL;
+       len = sizeof(events);
+       if (zmq_getsockopt(zmqsock, ZMQ_EVENTS, &events, &len))
+               return NULL;
+
+       cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb));
+       if (!cb)
+               return NULL;
+
+       cb->arg = arg;
+       cb->zmqsock = zmqsock;
+       cb->cb_msg = msgfunc;
+       cb->cb_part = partfunc;
+       cb->fd = fd;
+
+       if (events & ZMQ_POLLIN)
+               funcname_thread_add_event(master,
+                               frrzmq_read_msg, cb, fd, &cb->thread,
+                               funcname, schedfrom, fromln);
+       else
+               funcname_thread_add_read_write(THREAD_READ, master,
+                               frrzmq_read_msg, cb, fd, &cb->thread,
+                               funcname, schedfrom, fromln);
+       return cb;
+}
+
+void frrzmq_thread_cancel(struct frrzmq_cb *cb)
+{
+       if (!cb->thread) {
+               /* canceling from within callback */
+               cb->cancelled = 1;
+               return;
+       }
+       thread_cancel(cb->thread);
+       XFREE(MTYPE_ZEROMQ_CB, cb);
+}
diff --git a/lib/frr_zmq.h b/lib/frr_zmq.h
new file mode 100644 (file)
index 0000000..69c6f85
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * libzebra ZeroMQ bindings
+ * Copyright (C) 2015  David Lamparter
+ *
+ * This program 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This program 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 _FRRZMQ_H
+#define _FRRZMQ_H
+
+#include "thread.h"
+#include <zmq.h>
+
+/* linking/packaging note:  this is a separate library that needs to be
+ * linked into any daemon/library/module that wishes to use its
+ * functionality.  The purpose of this is to encapsulate the libzmq
+ * dependency and not make libfrr/FRR itself depend on libzmq.
+ *
+ * libfrrzmq should be put in LDFLAGS/LIBADD *before* either libfrr or
+ * libzmq, and both of these should always be listed, e.g.
+ *   foo_LDFLAGS = libfrrzmq.la libfrr.la $(ZEROMQ_LIBS)
+ */
+
+/* libzmq's context
+ *
+ * this is mostly here as a convenience, it has IPv6 enabled but nothing
+ * else is tied to it;  you can use a separate context without problems
+ */
+extern void *frrzmq_context;
+
+extern void frrzmq_init (void);
+extern void frrzmq_finish (void);
+
+#define debugargdef const char *funcname, const char *schedfrom, int fromln
+
+/* core event registration, one of these 2 macros should be used */
+#define frrzmq_thread_add_read_msg(m,f,a,z) funcname_frrzmq_thread_add_read( \
+                               m,f,NULL,a,z,#f,__FILE__,__LINE__)
+#define frrzmq_thread_add_read_part(m,f,a,z) funcname_frrzmq_thread_add_read( \
+                               m,NULL,f,a,z,#f,__FILE__,__LINE__)
+
+struct frrzmq_cb;
+
+/* Set up a POLLIN notification to be called from the libfrr main loop.
+ * This has the following properties:
+ *
+ * - since ZeroMQ works with edge triggered notifications, it will loop and
+ *   dispatch as many events as ZeroMQ has pending at the time libfrr calls
+ *   into this code
+ * - due to this looping (which means it non-single-issue), the callback is
+ *   also persistent.  Do _NOT_ re-register the event inside of your
+ *   callback function.
+ * - either msgfunc or partfunc will be called (only one can be specified)
+ *   - msgfunc is called once for each incoming message
+ *   - if partfunc is specified, the message is read and partfunc is called
+ *     for each ZeroMQ multi-part subpart.  Note that you can't send replies
+ *     before all parts have been read because that violates the ZeroMQ FSM.
+ * - you can safely cancel the callback from within itself
+ * - installing a callback will check for pending events (ZMQ_EVENTS) and
+ *   may schedule the event to run as soon as libfrr is back in its main
+ *   loop.
+ *
+ * TODO #1: add ZMQ_POLLERR / error callback
+ * TODO #2: add frrzmq_check_events() function to check for edge triggered
+ *          things that may have happened after a zmq_send() call or so
+ */
+extern struct frrzmq_cb *funcname_frrzmq_thread_add_read(
+               struct thread_master *master,
+               void (*msgfunc)(void *arg, void *zmqsock),
+               void (*partfunc)(void *arg, void *zmqsock,
+                                zmq_msg_t *msg, unsigned partnum),
+               void *arg, void *zmqsock, debugargdef);
+
+extern void frrzmq_thread_cancel(struct frrzmq_cb *cb);
+
+#endif /* _FRRZMQ_H */
index 89b0993d1d0e6642828e69464ccf18dd66987bbc..264c7c48f00ec6a30d91670bf777c0710efce8a4 100644 (file)
@@ -50,6 +50,7 @@ int main(int argc, char **argv)
        /* Library inits. */
        cmd_init(1);
        host.name = strdup("test");
+       host.domainname = strdup("testdomainname");
 
        vty_init(master);
        memory_init();
index 9944fdd1e163ad6ab8bad34a3f43efb95ede36dd..3e2e0082234b395d8e860bf6175822f46cb8b275 100644 (file)
@@ -101,13 +101,15 @@ static const struct optspec os_always = {
 static const struct option lo_cfg_pid_dry[] = {
        {"pid_file", required_argument, NULL, 'i'},
        {"config_file", required_argument, NULL, 'f'},
+       {"pathspace", required_argument, NULL, 'N'},
        {"dryrun", no_argument, NULL, 'C'},
        {"terminal", no_argument, NULL, 't'},
        {NULL}};
 static const struct optspec os_cfg_pid_dry = {
-       "f:i:Ct",
+       "f:i:CtN:",
        "  -f, --config_file  Set configuration file name\n"
        "  -i, --pid_file     Set process identifier file name\n"
+       "  -N, --pathspace    Insert prefix into config & socket paths\n"
        "  -C, --dryrun       Check configuration for validity and exit\n"
        "  -t, --terminal     Open terminal session on stdio\n"
        "  -d -t              Daemonize after terminal session ends\n",
@@ -351,6 +353,23 @@ static int frr_opt(int opt)
                        return 1;
                di->config_file = optarg;
                break;
+       case 'N':
+               if (di->flags & FRR_NO_CFG_PID_DRY)
+                       return 1;
+               if (di->pathspace) {
+                       fprintf(stderr,
+                               "-N/--pathspace option specified more than once!\n");
+                       errors++;
+                       break;
+               }
+               if (strchr(optarg, '/') || strchr(optarg, '.')) {
+                       fprintf(stderr,
+                               "slashes or dots are not permitted in the --pathspace option.\n");
+                       errors++;
+                       break;
+               }
+               di->pathspace = optarg;
+               break;
        case 'C':
                if (di->flags & FRR_NO_CFG_PID_DRY)
                        return 1;
@@ -500,14 +519,25 @@ struct thread_master *frr_init(void)
        struct option_chain *oc;
        struct frrmod_runtime *module;
        char moderr[256];
+       char p_instance[16] = "", p_pathspace[256] = "";
        const char *dir;
        dir = di->module_path ? di->module_path : frr_moduledir;
 
        srandom(time(NULL));
 
-       if (di->instance)
+       if (di->instance) {
                snprintf(frr_protonameinst, sizeof(frr_protonameinst), "%s[%u]",
                         di->logname, di->instance);
+               snprintf(p_instance, sizeof(p_instance), "-%d", di->instance);
+       }
+       if (di->pathspace)
+               snprintf(p_pathspace, sizeof(p_pathspace), "/%s",
+                        di->pathspace);
+
+       snprintf(config_default, sizeof(config_default), "%s%s/%s%s.conf",
+                frr_sysconfdir, p_pathspace, di->name, p_instance);
+       snprintf(pidfile_default, sizeof(pidfile_default), "%s%s/%s%s.pid",
+                frr_vtydir, p_pathspace, di->name, p_instance);
 
        zprivs_preinit(di->privs);
 
@@ -695,14 +725,6 @@ void frr_config_fork(void)
 {
        hook_call(frr_late_init, master);
 
-       if (di->instance) {
-               snprintf(config_default, sizeof(config_default),
-                        "%s/%s-%d.conf", frr_sysconfdir, di->name,
-                        di->instance);
-               snprintf(pidfile_default, sizeof(pidfile_default),
-                        "%s/%s-%d.pid", frr_vtydir, di->name, di->instance);
-       }
-
        vty_read_config(di->config_file, config_default);
 
        /* Don't start execution if we are in dry-run mode */
@@ -723,7 +745,13 @@ void frr_vty_serv(void)
         * (not currently set anywhere) */
        if (!di->vty_path) {
                const char *dir;
-               dir = di->vty_sock_path ? di->vty_sock_path : frr_vtydir;
+               char defvtydir[256];
+
+               snprintf(defvtydir, sizeof(defvtydir), "%s%s%s", frr_vtydir,
+                        di->pathspace ? "/" : "",
+                        di->pathspace ? di->pathspace : "");
+
+               dir = di->vty_sock_path ? di->vty_sock_path : defvtydir;
 
                if (di->instance)
                        snprintf(vtypath_default, sizeof(vtypath_default),
index f7d69eecb3fbe004f8df52210fdc64d68cb5f0cb..fe6c46670a3c6b312cb83fcd59b535a0d7f3c623 100644 (file)
@@ -54,6 +54,7 @@ struct frr_daemon_info {
        const char *pid_file;
        const char *vty_path;
        const char *module_path;
+       const char *pathspace;
 
        const char *proghelp;
        void (*printhelp)(FILE *target);
index 7180be33dd852ab0bdccdcddefbc9e53c0fd446b..2dba412f452b1140b2fbba5280ab56d1a74a8a2f 100644 (file)
@@ -36,7 +36,8 @@ DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop")
 DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label")
 
 /* check if nexthops are same, non-recursive */
-int nexthop_same_no_recurse(struct nexthop *next1, struct nexthop *next2)
+int nexthop_same_no_recurse(const struct nexthop *next1,
+                           const struct nexthop *next2)
 {
        if (next1->type != next2->type)
                return 0;
index e7804379f19f739cf9662d66c1d7b2d0b406ab91..781eb9341349eca685e1550409b937545bfcd205 100644 (file)
@@ -43,6 +43,13 @@ enum nexthop_types_t {
        NEXTHOP_TYPE_BLACKHOLE,    /* Null0 nexthop.  */
 };
 
+enum blackhole_type {
+       BLACKHOLE_UNSPEC = 0,
+       BLACKHOLE_NULL,
+       BLACKHOLE_REJECT,
+       BLACKHOLE_ADMINPROHIB,
+};
+
 /* Nexthop label structure. */
 struct nexthop_label {
        u_int8_t num_labels;
@@ -69,7 +76,10 @@ struct nexthop {
 #define NEXTHOP_FLAG_FILTERED   (1 << 5) /* rmap filtered, used by static only */
 
        /* Nexthop address */
-       union g_addr gate;
+       union {
+               union g_addr gate;
+               enum blackhole_type bh_type;
+       };
        union g_addr src;
        union g_addr rmap_src; /* Src is set via routemap */
 
@@ -128,8 +138,8 @@ void nexthop_add_labels(struct nexthop *, enum lsp_types_t, u_int8_t,
 void nexthop_del_labels(struct nexthop *);
 
 extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type);
-extern int nexthop_same_no_recurse(struct nexthop *next1,
-                                  struct nexthop *next2);
+extern int nexthop_same_no_recurse(const struct nexthop *next1,
+                                  const struct nexthop *next2);
 extern int nexthop_labels_match(struct nexthop *nh1, struct nexthop *nh2);
 
 extern const char *nexthop2str(struct nexthop *nexthop, char *str, int size);
index a70248633c087d68a9fa232765b31ac3a5d2de7a..409c9c378076a11d1ee511fe8517682fe5ae9585 100644 (file)
@@ -416,23 +416,25 @@ int generic_match_add(struct vty *vty, struct route_map_index *index,
        int ret;
 
        ret = route_map_add_match(index, command, arg);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% [%s] Can't find rule.\n",
-                               frr_protonameinst);
-                       return CMD_WARNING_CONFIG_FAILED;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty,
-                               "%% [%s] Argument form is unsupported or malformed.\n",
-                               frr_protonameinst);
-                       return CMD_WARNING_CONFIG_FAILED;
+       switch (ret) {
+       case RMAP_COMPILE_SUCCESS:
+               if (type != RMAP_EVENT_MATCH_ADDED) {
+                       route_map_upd8_dependency(type, arg, index->map->name);
                }
+               break;
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% [%s] Can't find rule.\n",
+                       frr_protonameinst);
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty,
+                       "%% [%s] Argument form is unsupported or malformed.\n",
+                       frr_protonameinst);
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
        }
 
-       if (type != RMAP_EVENT_MATCH_ADDED) {
-               route_map_upd8_dependency(type, arg, index->map->name);
-       }
        return CMD_SUCCESS;
 }
 
@@ -441,6 +443,7 @@ int generic_match_delete(struct vty *vty, struct route_map_index *index,
                         route_map_event_t type)
 {
        int ret;
+       int retval = CMD_SUCCESS;
        char *dep_name = NULL;
        const char *tmpstr;
        char *rmap_name = NULL;
@@ -459,34 +462,30 @@ int generic_match_delete(struct vty *vty, struct route_map_index *index,
        }
 
        ret = route_map_delete_match(index, command, dep_name);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% [%s] Can't find rule.\n",
-                               frr_protonameinst);
-                       break;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty,
-                               "%% [%s] Argument form is unsupported or malformed.\n",
-                               frr_protonameinst);
-                       break;
-               }
-               if (dep_name)
-                       XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
-               if (rmap_name)
-                       XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
-               return CMD_WARNING_CONFIG_FAILED;
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% [%s] Can't find rule.\n",
+                       frr_protonameinst);
+               retval = CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty,
+                       "%% [%s] Argument form is unsupported or malformed.\n",
+                       frr_protonameinst);
+               retval = CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
+                       route_map_upd8_dependency(type, dep_name, rmap_name);
+               break;
        }
 
-       if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
-               route_map_upd8_dependency(type, dep_name, rmap_name);
-
        if (dep_name)
                XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
        if (rmap_name)
                XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
 
-       return CMD_SUCCESS;
+       return retval;
 }
 
 int generic_set_add(struct vty *vty, struct route_map_index *index,
@@ -495,19 +494,22 @@ int generic_set_add(struct vty *vty, struct route_map_index *index,
        int ret;
 
        ret = route_map_add_set(index, command, arg);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% [%s] Can't find rule.\n",
-                               frr_protonameinst);
-                       return CMD_WARNING_CONFIG_FAILED;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty,
-                               "%% [%s] Argument form is unsupported or malformed.\n",
-                               frr_protonameinst);
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% [%s] Can't find rule.\n",
+                       frr_protonameinst);
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty,
+                       "%% [%s] Argument form is unsupported or malformed.\n",
+                       frr_protonameinst);
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               break;
        }
+
        return CMD_SUCCESS;
 }
 
@@ -517,19 +519,22 @@ int generic_set_delete(struct vty *vty, struct route_map_index *index,
        int ret;
 
        ret = route_map_delete_set(index, command, arg);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% [%s] Can't find rule.\n",
-                               frr_protonameinst);
-                       return CMD_WARNING_CONFIG_FAILED;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty,
-                               "%% [%s] Argument form is unsupported or malformed.\n",
-                               frr_protonameinst);
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% [%s] Can't find rule.\n",
+                       frr_protonameinst);
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty,
+                       "%% [%s] Argument form is unsupported or malformed.\n",
+                       frr_protonameinst);
+               return CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               break;
        }
+
        return CMD_SUCCESS;
 }
 
@@ -1217,7 +1222,7 @@ int route_map_add_match(struct route_map_index *index, const char *match_name,
                                              RMAP_EVENT_CALL_ADDED);
        }
 
-       return 0;
+       return RMAP_COMPILE_SUCCESS;
 }
 
 /* Delete specified route match rule. */
@@ -1304,7 +1309,7 @@ int route_map_add_set(struct route_map_index *index, const char *set_name,
                route_map_notify_dependencies(index->map->name,
                                              RMAP_EVENT_CALL_ADDED);
        }
-       return 0;
+       return RMAP_COMPILE_SUCCESS;
 }
 
 /* Delete route map set rule. */
@@ -2201,7 +2206,7 @@ DEFUN (no_set_ip_nexthop,
        "Next hop address\n"
        "IP address of next hop\n")
 {
-       int idx;
+       int idx = 0;
        VTY_DECLVAR_CONTEXT(route_map_index, index);
        const char *arg = NULL;
 
index 43af8dbcfe347c07d9685f21c05f06a64790b653..b166de1e0956c327952fc566a4d33c9799fd542b 100644 (file)
@@ -99,8 +99,10 @@ struct route_map_rule_cmd {
 
 /* Route map apply error. */
 enum {
+       RMAP_COMPILE_SUCCESS,
+
        /* Route map rule is missing. */
-       RMAP_RULE_MISSING = 1,
+       RMAP_RULE_MISSING,
 
        /* Route map rule can't compile */
        RMAP_COMPILE_ERROR
index 7b1c7ba9c56414aff8b11dd735dd30bc7eef90a3..67a7a46272d3370aef68ac6b78fcdbf2f33cf62e 100644 (file)
@@ -34,6 +34,7 @@ union sockunion {
        struct sockaddr_in6 sin6;
 #ifdef __OpenBSD__
        struct sockaddr_mpls smpls;
+       struct sockaddr_rtlabel rtlabel;
 #endif
 };
 
index d6349ba22df2f2b0646460482a6e6d4e982ac5e6..5f38cc7a14f123c0efd83efcc17a245d78d87fee 100644 (file)
@@ -183,6 +183,21 @@ lib_libfrrsnmp_la_SOURCES = \
        lib/snmp.c \
        # end
 
+#
+# ZeroMQ support
+#
+if ZEROMQ
+lib_LTLIBRARIES += lib/libfrrzmq.la
+pkginclude_HEADERS += lib/frr_zmq.h
+endif
+
+lib_libfrrzmq_la_CFLAGS = $(WERROR) $(ZEROMQ_CFLAGS)
+lib_libfrrzmq_la_LDFLAGS = -version-info 0:0:0
+lib_libfrrzmq_la_LIBADD = lib/libfrr.la $(ZEROMQ_LIBS)
+lib_libfrrzmq_la_SOURCES = \
+       lib/frr_zmq.c \
+       #end
+
 #
 # CLI utilities
 #
index 59a8825357b1989e63c8e546e8ab90f47581d588..12c3c12394a6774cb614002fdb72005e232ffb92 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -91,6 +91,24 @@ char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
 
 static int do_log_commands = 0;
 
+void vty_frame(struct vty *vty, const char *format, ...)
+{
+       va_list args;
+
+       va_start(args, format);
+       vsnprintf(vty->frame + vty->frame_pos,
+                 sizeof(vty->frame) - vty->frame_pos, format, args);
+       vty->frame_pos = strlen(vty->frame);
+       va_end(args);
+}
+
+void vty_endframe(struct vty *vty, const char *endtext)
+{
+       if (vty->frame_pos == 0 && endtext)
+               vty_out(vty, "%s", endtext);
+       vty->frame_pos = 0;
+}
+
 /* VTY standard output function. */
 int vty_out(struct vty *vty, const char *format, ...)
 {
@@ -100,6 +118,11 @@ int vty_out(struct vty *vty, const char *format, ...)
        char buf[1024];
        char *p = NULL;
 
+       if (vty->frame_pos) {
+               vty->frame_pos = 0;
+               vty_out(vty, "%s", vty->frame);
+       }
+
        if (vty_shell(vty)) {
                va_start(args, format);
                vprintf(format, args);
@@ -250,16 +273,8 @@ void vty_hello(struct vty *vty)
 /* Put out prompt and wait input from user. */
 static void vty_prompt(struct vty *vty)
 {
-       struct utsname names;
-       const char *hostname;
-
        if (vty->type == VTY_TERM) {
-               hostname = host.name;
-               if (!hostname) {
-                       uname(&names);
-                       hostname = names.nodename;
-               }
-               vty_out(vty, cmd_prompt(vty->node), hostname);
+               vty_out(vty, cmd_prompt(vty->node), cmd_hostname_get());
        }
 }
 
index 9acd62af3cb1a6268cff82bef12495d42e2af73a..3b75afb02ceec496818ba1ee5ebd653b4c918555 100644 (file)
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -125,6 +125,12 @@ struct vty {
 
        /* What address is this vty comming from. */
        char address[SU_ADDRSTRLEN];
+
+       /* "frame" output.  This is buffered and will be printed if some
+        * actual output follows, or will be discarded if the frame ends
+        * without any output. */
+       size_t frame_pos;
+       char frame[1024];
 };
 
 static inline void vty_push_context(struct vty *vty, int node, uint64_t id)
@@ -247,7 +253,16 @@ extern void vty_terminate(void);
 extern void vty_reset(void);
 extern struct vty *vty_new(void);
 extern struct vty *vty_stdio(void (*atclose)(int isexit));
+
+/* - vty_frame() output goes to a buffer (for context-begin markers)
+ * - vty_out() will first print this buffer, and clear it
+ * - vty_endframe() clears the buffer without printing it, and prints an
+ *   extra string if the buffer was empty before (for context-end markers)
+ */
 extern int vty_out(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
+extern void vty_frame(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
+extern void vty_endframe(struct vty *, const char *);
+
 extern void vty_read_config(const char *, char *);
 extern void vty_time_print(struct vty *, int);
 extern void vty_serv_sock(const char *, unsigned short, const char *);
index 72fa2679b320a7f1b1f3ee47270493af5cac24b0..910e05cb47f8ee1ab8cffdd5123ab0dabe65145e 100644 (file)
@@ -621,10 +621,9 @@ static int zclient_connect(struct thread *t)
  * |       IPv4 Nexthop address or Interface Index number          |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
- * Alternatively, if the flags field has ZEBRA_FLAG_BLACKHOLE or
- * ZEBRA_FLAG_REJECT is set then Nexthop count is set to 1, then _no_
- * nexthop information is provided, and the message describes a prefix
- * to blackhole or reject route.
+ * Alternatively, if the route is a blackhole route, then Nexthop count
+ * is set to 1 and a nexthop of type NEXTHOP_TYPE_BLACKHOLE is the sole
+ * nexthop.
  *
  * The original struct zapi_ipv4, zapi_ipv4_route() and zread_ipv4_*()
  * infrastructure was built around the traditional (32-bit "gate OR
@@ -692,14 +691,7 @@ int zapi_ipv4_route(u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
 
        /* Nexthop, ifindex, distance and metric information. */
        if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               /* traditional 32-bit data units */
-               if (CHECK_FLAG(api->flags, ZEBRA_FLAG_BLACKHOLE)) {
-                       stream_putc(s, 1);
-                       stream_putc(s, NEXTHOP_TYPE_BLACKHOLE);
-                       /* XXX assert(api->nexthop_num == 0); */
-                       /* XXX assert(api->ifindex_num == 0); */
-               } else
-                       stream_putc(s, api->nexthop_num + api->ifindex_num);
+               stream_putc(s, api->nexthop_num + api->ifindex_num);
 
                for (i = 0; i < api->nexthop_num; i++) {
                        stream_putc(s, NEXTHOP_TYPE_IPV4);
@@ -769,13 +761,7 @@ int zapi_ipv4_route_ipv6_nexthop(u_char cmd, struct zclient *zclient,
 
        /* Nexthop, ifindex, distance and metric information. */
        if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               if (CHECK_FLAG(api->flags, ZEBRA_FLAG_BLACKHOLE)) {
-                       stream_putc(s, 1);
-                       stream_putc(s, NEXTHOP_TYPE_BLACKHOLE);
-                       /* XXX assert(api->nexthop_num == 0); */
-                       /* XXX assert(api->ifindex_num == 0); */
-               } else
-                       stream_putc(s, api->nexthop_num + api->ifindex_num);
+               stream_putc(s, api->nexthop_num + api->ifindex_num);
 
                for (i = 0; i < api->nexthop_num; i++) {
                        stream_putc(s, NEXTHOP_TYPE_IPV6);
@@ -855,13 +841,7 @@ int zapi_ipv6_route(u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
 
        /* Nexthop, ifindex, distance and metric information. */
        if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               if (CHECK_FLAG(api->flags, ZEBRA_FLAG_BLACKHOLE)) {
-                       stream_putc(s, 1);
-                       stream_putc(s, NEXTHOP_TYPE_BLACKHOLE);
-                       /* XXX assert(api->nexthop_num == 0); */
-                       /* XXX assert(api->ifindex_num == 0); */
-               } else
-                       stream_putc(s, api->nexthop_num + api->ifindex_num);
+               stream_putc(s, api->nexthop_num + api->ifindex_num);
 
                for (i = 0; i < api->nexthop_num; i++) {
                        stream_putc(s, NEXTHOP_TYPE_IPV6);
@@ -948,6 +928,7 @@ int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api)
                        stream_putc(s, api_nh->type);
                        switch (api_nh->type) {
                        case NEXTHOP_TYPE_BLACKHOLE:
+                               stream_putc(s, api_nh->bh_type);
                                break;
                        case NEXTHOP_TYPE_IPV4:
                                stream_put_in_addr(s, &api_nh->gate.ipv4);
@@ -1060,6 +1041,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
                        api_nh->type = stream_getc(s);
                        switch (api_nh->type) {
                        case NEXTHOP_TYPE_BLACKHOLE:
+                               api_nh->bh_type = stream_getc(s);
                                break;
                        case NEXTHOP_TYPE_IPV4:
                                api_nh->gate.ipv4.s_addr = stream_get_ipv4(s);
index 7c4780201e07a434c9856779448d05b61b875e29..288951eb1aff47de97a40daa7296bc2f964fc18e 100644 (file)
@@ -222,7 +222,10 @@ struct zserv_header {
 struct zapi_nexthop {
        enum nexthop_types_t type;
        ifindex_t ifindex;
-       union g_addr gate;
+       union {
+               union g_addr gate;
+               enum blackhole_type bh_type;
+       };
 
        /* MPLS labels for BGP-LU or Segment Routing */
        uint8_t label_num;
@@ -429,4 +432,14 @@ extern int zclient_route_send(u_char, struct zclient *, struct zapi_route *);
 extern int zapi_route_encode(u_char, struct stream *, struct zapi_route *);
 extern int zapi_route_decode(struct stream *, struct zapi_route *);
 
+static inline void zapi_route_set_blackhole(struct zapi_route *api,
+                                           enum blackhole_type bh_type)
+{
+       api->nexthop_num = 1;
+       api->nexthops[0].type = NEXTHOP_TYPE_BLACKHOLE;
+       api->nexthops[0].bh_type = bh_type;
+       SET_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP);
+};
+
+
 #endif /* _ZEBRA_ZCLIENT_H */
index 6d64bbd670cd036a901d4da89ed5dd68fd1f2d73..fa5fa89f776116c2b1aff76c9241017a63222a5e 100644 (file)
@@ -404,13 +404,13 @@ extern const char *zserv_command_string(unsigned int command);
 /* Zebra message flags */
 #define ZEBRA_FLAG_INTERNAL           0x01
 #define ZEBRA_FLAG_SELFROUTE          0x02
-#define ZEBRA_FLAG_BLACKHOLE          0x04
 #define ZEBRA_FLAG_IBGP               0x08
 #define ZEBRA_FLAG_SELECTED           0x10
 #define ZEBRA_FLAG_STATIC             0x40
-#define ZEBRA_FLAG_REJECT             0x80
 #define ZEBRA_FLAG_SCOPE_LINK         0x100
 #define ZEBRA_FLAG_FIB_OVERRIDE       0x200
+/* ZEBRA_FLAG_BLACKHOLE was 0x04 */
+/* ZEBRA_FLAG_REJECT was 0x80 */
 
 /* Zebra FEC flags. */
 #define ZEBRA_FEC_REGISTER_LABEL_INDEX        0x1
index 4b86bca5f75b1dbd311cf8a9c9bb08a25931a7e7..495e226f1516c71ba7771f06341b4338d9ff9bf1 100644 (file)
@@ -99,7 +99,9 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
 
        switch (type) {
        case NHRP_CACHE_NEGATIVE:
-               SET_FLAG(api.flags, ZEBRA_FLAG_REJECT);
+               zapi_route_set_blackhole(&api, BLACKHOLE_REJECT);
+               ifp = NULL;
+               nexthop = NULL;
                break;
        case NHRP_CACHE_DYNAMIC:
        case NHRP_CACHE_NHS:
@@ -158,7 +160,7 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
                        " count %d dev %s",
                        add ? "add" : "del", buf[0],
                        nexthop ? inet_ntop(api.prefix.family, &api_nh->gate, buf[1], sizeof(buf[1])) : "<onlink>",
-                       api.metric, api.nexthop_num, ifp->name);
+                       api.metric, api.nexthop_num, ifp ? ifp->name : "none");
        }
 
        zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, zclient,
index 6d78fc1d2b25f37cc52dda164251a8f4dca79491..bd5b1aa6f164704ee9f5f87ca8eadfd5dc8faf6a 100644 (file)
@@ -854,7 +854,7 @@ static int interface_config_write(struct vty *vty)
        int i;
 
        for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) {
-               vty_out (vty, "interface %s\n", ifp->name);
+               vty_frame(vty, "interface %s\n", ifp->name);
                if (ifp->desc)
                        vty_out (vty, " description %s\n", ifp->desc);
 
@@ -913,7 +913,7 @@ static int interface_config_write(struct vty *vty)
                        }
                }
 
-               vty_out (vty, "!\n");
+               vty_endframe(vty, "!\n");
        }
 
        return 0;
index 649d7a100041346fba7cb346fa9a53ddf092f6ba..485937d882a39730c775d44ad3334d0cfa00717c 100644 (file)
@@ -643,9 +643,9 @@ void ospf6_area_plist_update(struct prefix_list *plist, int add)
        const char *name = prefix_list_name(plist);
 
        for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
-               if (!strcmp(PREFIX_NAME_IN(oa), name))
+               if (PREFIX_NAME_IN(oa) && !strcmp(PREFIX_NAME_IN(oa), name))
                        PREFIX_LIST_IN(oa) = add ? plist : NULL;
-               if (!strcmp(PREFIX_NAME_OUT(oa), name))
+               if (PREFIX_NAME_OUT(oa) && !strcmp(PREFIX_NAME_OUT(oa), name))
                        PREFIX_LIST_OUT(oa) = add ? plist : NULL;
        }
 }
index dd3630af160ce32278a95c2a0f82531313c08757..de20fbc3abf514e608a24fa7bb3dc0da616fac30 100644 (file)
@@ -985,21 +985,20 @@ static struct route_map_rule_cmd ospf6_routemap_rule_set_tag_cmd = {
 
 static int route_map_command_status(struct vty *vty, int ret)
 {
-       if (!ret)
-               return CMD_SUCCESS;
-
        switch (ret) {
        case RMAP_RULE_MISSING:
                vty_out(vty, "OSPF6 Can't find rule.\n");
+               return CMD_WARNING_CONFIG_FAILED;
                break;
        case RMAP_COMPILE_ERROR:
                vty_out(vty, "OSPF6 Argument is malformed.\n");
+               return CMD_WARNING_CONFIG_FAILED;
                break;
-       default:
-               vty_out(vty, "OSPF6 route-map add set failed.\n");
+       case RMAP_COMPILE_SUCCESS:
                break;
        }
-       return CMD_WARNING_CONFIG_FAILED;
+
+       return CMD_SUCCESS;
 }
 
 /* add "set metric-type" */
index bb63fb966ed8b6c7e868a1188dbbb39d7bd9dd79..8cfed81a810b318131651c0017fcceea9d83cc7f 100644 (file)
@@ -1755,7 +1755,7 @@ static int config_write_ospf6_interface(struct vty *vty)
                if (oi == NULL)
                        continue;
 
-               vty_out(vty, "interface %s\n", oi->interface->name);
+               vty_frame(vty, "interface %s\n", oi->interface->name);
 
                if (ifp->desc)
                        vty_out(vty, " description %s\n", ifp->desc);
@@ -1808,7 +1808,7 @@ static int config_write_ospf6_interface(struct vty *vty)
 
                ospf6_bfd_write_config(vty, oi);
 
-               vty_out(vty, "!\n");
+               vty_endframe(vty, "!\n");
        }
        return 0;
 }
index 387690bc8ad84fd2fb1c9c1caf42d7ffad0ad9ac..e77bf690f355cc9ccf3181de1b7ceb3e96555c2d 100644 (file)
@@ -306,21 +306,25 @@ DEFUN (no_router_ospf6,
 }
 
 /* change Router_ID commands. */
-DEFUN (ospf6_router_id,
-       ospf6_router_id_cmd,
-       "router-id A.B.C.D",
-       "Configure OSPF Router-ID\n"
-       V4NOTATION_STR)
+DEFUN(ospf6_router_id,
+      ospf6_router_id_cmd,
+      "ospf6 router-id A.B.C.D",
+      OSPF6_STR
+      "Configure OSPF6 Router-ID\n"
+      V4NOTATION_STR)
 {
        VTY_DECLVAR_CONTEXT(ospf6, o);
-       int idx_ipv4 = 1;
+       int idx = 0;
        int ret;
+       const char *router_id_str;
        u_int32_t router_id;
 
-       ret = inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
+       argv_find(argv, argc, "A.B.C.D", &idx);
+       router_id_str = argv[idx]->arg;
+
+       ret = inet_pton(AF_INET, router_id_str, &router_id);
        if (ret == 0) {
-               vty_out(vty, "malformed OSPF Router-ID: %s\n",
-                       argv[idx_ipv4]->arg);
+               vty_out(vty, "malformed OSPF Router-ID: %s\n", router_id_str);
                return CMD_SUCCESS;
        }
 
@@ -331,6 +335,39 @@ DEFUN (ospf6_router_id,
        return CMD_SUCCESS;
 }
 
+DEFUN(no_ospf6_router_id,
+      no_ospf6_router_id_cmd,
+      "no ospf6 router-id [A.B.C.D]",
+      NO_STR OSPF6_STR
+      "Configure OSPF6 Router-ID\n"
+      V4NOTATION_STR)
+{
+       VTY_DECLVAR_CONTEXT(ospf6, o);
+       o->router_id_static = 0;
+       o->router_id = 0;
+
+       return CMD_SUCCESS;
+}
+
+#if CONFDATE > 20180828
+CPP_NOTICE("ospf6: `router-id A.B.C.D` deprecated 2017/08/28")
+#endif
+ALIAS_HIDDEN(ospf6_router_id,
+            ospf6_router_id_hdn_cmd,
+            "router-id A.B.C.D",
+            "Configure OSPF6 Router-ID\n"
+            V4NOTATION_STR)
+
+#if CONFDATE > 20180828
+CPP_NOTICE("ospf6: `no router-id A.B.C.D` deprecated 2017/08/28")
+#endif
+ALIAS_HIDDEN(no_ospf6_router_id,
+            no_ospf6_router_id_hdn_cmd,
+            "no router-id [A.B.C.D]",
+            NO_STR
+            "Configure OSPF6 Router-ID\n"
+            V4NOTATION_STR)
+
 DEFUN (ospf6_log_adjacency_changes,
        ospf6_log_adjacency_changes_cmd,
        "log-adjacency-changes",
@@ -974,7 +1011,7 @@ static int config_write_ospf6(struct vty *vty)
                  sizeof(router_id));
        vty_out(vty, "router ospf6\n");
        if (ospf6->router_id_static != 0)
-               vty_out(vty, " router-id %s\n", router_id);
+               vty_out(vty, " ospf6 router-id %s\n", router_id);
 
        /* log-adjacency-changes flag print. */
        if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) {
@@ -1032,6 +1069,9 @@ void ospf6_top_init(void)
 
        install_default(OSPF6_NODE);
        install_element(OSPF6_NODE, &ospf6_router_id_cmd);
+       install_element(OSPF6_NODE, &no_ospf6_router_id_cmd);
+       install_element(OSPF6_NODE, &ospf6_router_id_hdn_cmd);
+       install_element(OSPF6_NODE, &no_ospf6_router_id_hdn_cmd);
        install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
        install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
        install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
index 3443bc47b616acd3900294bbc4c3e1b4daeb71e7..2372bc54b798aa3b159e167b31972a980f004c2f 100644 (file)
@@ -231,11 +231,7 @@ static int ospf6_zebra_read_route(int command, struct zclient *zclient,
                char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128];
                prefix2str((struct prefix *)&api.prefix, prefixstr,
                           sizeof(prefixstr));
-               if (nexthop)
-                       inet_ntop(AF_INET6, nexthop, nexthopstr,
-                                 sizeof(nexthopstr));
-               else
-                       snprintf(nexthopstr, sizeof(nexthopstr), "::");
+               inet_ntop(AF_INET6, nexthop, nexthopstr, sizeof(nexthopstr));
 
                zlog_debug(
                        "Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %" ROUTE_TAG_PRI,
@@ -392,9 +388,9 @@ void ospf6_zebra_add_discard(struct ospf6_route *request)
                memset(&api, 0, sizeof(api));
                api.vrf_id = VRF_DEFAULT;
                api.type = ZEBRA_ROUTE_OSPF6;
-               api.flags = ZEBRA_FLAG_BLACKHOLE;
                api.safi = SAFI_UNICAST;
                api.prefix = *dest;
+               zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
 
                zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
 
@@ -425,9 +421,9 @@ void ospf6_zebra_delete_discard(struct ospf6_route *request)
                memset(&api, 0, sizeof(api));
                api.vrf_id = VRF_DEFAULT;
                api.type = ZEBRA_ROUTE_OSPF6;
-               api.flags = ZEBRA_FLAG_BLACKHOLE;
                api.safi = SAFI_UNICAST;
                api.prefix = *dest;
+               zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
 
                zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
 
index 1c1c76c1afdda52e4d35bf1c6259ba1da3ece51f..55170089098553adb1e0d32dbdb0a54377646665 100644 (file)
@@ -2425,7 +2425,7 @@ DEFUN (show_ip_ospf_mpls_te_router,
                if (ntohs(OspfMplsTE.router_addr.header.type) != 0)
                        show_vty_router_addr(vty,
                                             &OspfMplsTE.router_addr.header);
-               else if (vty != NULL)
+               else
                        vty_out(vty, "  N/A\n");
        }
        return CMD_SUCCESS;
index 89a470896f7f0731849d9e8f0262fb1eba40bd0f..4cbd4b4a9939f9d1256503616e5c6f342561fcff 100644 (file)
@@ -2268,7 +2268,9 @@ DEFUN (no_ospf_timers_lsa_min_arrival,
        return CMD_SUCCESS;
 }
 
-/* Deprecated: 08/07/2017 */
+#if CONFDATE > 20180708
+CPP_NOTICE("ospf: `timers lsa arrival (0-1000)` deprecated 2017/07/08")
+#endif
 ALIAS_HIDDEN (ospf_timers_lsa_min_arrival,
               ospf_timers_lsa_arrival_cmd,
               "timers lsa arrival (0-1000)",
@@ -2277,7 +2279,9 @@ ALIAS_HIDDEN (ospf_timers_lsa_min_arrival,
               "ospf minimum arrival interval delay\n"
               "delay (msec) between accepted lsas\n");
 
-/* Deprecated: 08/07/2017 */
+#if CONFDATE > 20180708
+CPP_NOTICE("ospf: `no timers lsa arrival (0-1000)` deprecated 2017/07/08")
+#endif
 ALIAS_HIDDEN (no_ospf_timers_lsa_min_arrival,
               no_ospf_timers_lsa_arrival_cmd,
               "no timers lsa arrival (0-1000)",
@@ -2306,7 +2310,10 @@ DEFUN (ospf_neighbor,
        unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
        unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT;
 
-       inet_aton(argv[idx_ipv4]->arg, &nbr_addr);
+       if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
+               vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
        if (argc > 2)
                priority = strtoul(argv[idx_pri]->arg, NULL, 10);
@@ -2343,7 +2350,10 @@ DEFUN (ospf_neighbor_poll_interval,
        unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
        unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT;
 
-       inet_aton(argv[idx_ipv4]->arg, &nbr_addr);
+       if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
+               vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
        interval = strtoul(argv[idx_poll]->arg, NULL, 10);
 
@@ -2374,7 +2384,10 @@ DEFUN (no_ospf_neighbor,
        int idx_ipv4 = 2;
        struct in_addr nbr_addr;
 
-       inet_aton(argv[idx_ipv4]->arg, &nbr_addr);
+       if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
+               vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
        (void)ospf_nbr_nbma_unset(ospf, nbr_addr);
 
@@ -2396,7 +2409,10 @@ DEFUN (no_ospf_neighbor_poll,
        int idx_ipv4 = 2;
        struct in_addr nbr_addr;
 
-       inet_aton(argv[idx_ipv4]->arg, &nbr_addr);
+       if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
+               vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
        (void)ospf_nbr_nbma_unset(ospf, nbr_addr);
 
@@ -6958,7 +6974,10 @@ DEFUN (ip_ospf_area,
 
        // Check if we have an address arg and proccess it
        if (argc == idx + 3) {
-               inet_aton(argv[idx + 2]->arg, &addr);
+               if (!inet_aton(argv[idx + 2]->arg, &addr)) {
+                       vty_out(vty, "Please specify Intf Address by A.B.C.D\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
                // update/create address-level params
                params = ospf_get_if_params((ifp), (addr));
                if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) {
@@ -7017,7 +7036,10 @@ DEFUN (no_ip_ospf_area,
 
        // Check if we have an address arg and proccess it
        if (argc == idx + 3) {
-               inet_aton(argv[idx + 2]->arg, &addr);
+               if (!inet_aton(argv[idx + 2]->arg, &addr)) {
+                       vty_out(vty, "Please specify Intf Address by A.B.C.D\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
                params = ospf_lookup_if_params(ifp, addr);
                if ((params) == NULL)
                        return CMD_SUCCESS;
@@ -8152,8 +8174,8 @@ static int config_write_interface(struct vty *vty)
                if (ifp->ifindex == IFINDEX_DELETED)
                        continue;
 
-               vty_out(vty, "!\n");
-               vty_out(vty, "interface %s\n", ifp->name);
+               vty_frame(vty, "!\n");
+               vty_frame(vty, "interface %s\n", ifp->name);
                if (ifp->desc)
                        vty_out(vty, " description %s\n", ifp->desc);
 
@@ -8367,6 +8389,8 @@ static int config_write_interface(struct vty *vty)
                } while (rn);
 
                ospf_opaque_config_write_if(vty, ifp);
+
+               vty_endframe(vty, NULL);
        }
 
        return write;
index dcb392f1add5129ba9411e7fa64ae6448117ab75..e26a33c35f1e6c5dbb74c9a235569226c1135014 100644 (file)
@@ -442,9 +442,9 @@ void ospf_zebra_add_discard(struct prefix_ipv4 *p)
        api.vrf_id = VRF_DEFAULT;
        api.type = ZEBRA_ROUTE_OSPF;
        api.instance = ospf->instance;
-       api.flags = ZEBRA_FLAG_BLACKHOLE;
        api.safi = SAFI_UNICAST;
        memcpy(&api.prefix, p, sizeof(*p));
+       zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
 
        zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
 
@@ -462,9 +462,9 @@ void ospf_zebra_delete_discard(struct prefix_ipv4 *p)
        api.vrf_id = VRF_DEFAULT;
        api.type = ZEBRA_ROUTE_OSPF;
        api.instance = ospf->instance;
-       api.flags = ZEBRA_FLAG_BLACKHOLE;
        api.safi = SAFI_UNICAST;
        memcpy(&api.prefix, p, sizeof(*p));
+       zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
 
        zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
 
@@ -900,17 +900,10 @@ static int ospf_zebra_read_route(int command, struct zclient *zclient,
 
        if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
                /* XXX|HACK|TODO|FIXME:
-                * Maybe we should ignore reject/blackhole routes? Testing shows
-                * that
-                * there is no problems though and this is only way to
-                * "summarize"
-                * routes in ASBR at the moment. Maybe we need just a better
-                * generalised
-                * solution for these types?
-                *
-                * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE)
-                *     || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT))
-                * return 0;
+                * Maybe we should ignore reject/blackhole routes? Testing
+                * shows that there is no problems though and this is only way
+                * to "summarize" routes in ASBR at the moment. Maybe we need
+                * just a better generalised solution for these types?
                 */
 
                /* Protocol tag overwrites all other tag value sent by zebra */
index ae509f4a9bbbcdaa00c8aeefd425bf92e6a3754a..4a9c53cf2905d13920bc744062303774463d4ef1 100644 (file)
@@ -4895,6 +4895,9 @@ DEFUN (show_ip_mroute_count,
        int idx = 2;
        struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
 
+       if (!vrf)
+               return CMD_WARNING;
+
        show_mroute_count(vrf->info, vty);
        return CMD_SUCCESS;
 }
index 7fc77556ec65debd967b3e3b8ccc352b87f79769..d1f8085b48bf51fcfa73507de8180398309480a3 100644 (file)
@@ -195,11 +195,16 @@ static int pim_vrf_config_write(struct vty *vty)
        RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
        {
                pim = vrf->info;
-               if (!pim || vrf->vrf_id != VRF_DEFAULT) {
-                       vty_out(vty, "vrf %s\n", vrf->name);
-                       pim_global_config_write_worker(pim, vty);
-                       vty_out(vty, "!\n");
-               }
+
+               if (!pim)
+                       continue;
+
+               if (vrf->vrf_id == VRF_DEFAULT)
+                       continue;
+
+               vty_out(vty, "vrf %s\n", vrf->name);
+               pim_global_config_write_worker(pim, vty);
+               vty_out(vty, "!\n");
        }
 
        return 0;
index 52d240f54b40a06952e5a17a68c2f9c095ab946a..dca3bf4af313f0710ce08f465c2a1ea69949b270 100644 (file)
@@ -713,21 +713,26 @@ int pim_mroute_socket_enable(struct pim_instance *pim)
 
        fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
 
+       if (fd < 0) {
+               zlog_warn("Could not create mroute socket: errno=%d: %s", errno,
+                         safe_strerror(errno));
+               return -2;
+       }
+
 #ifdef SO_BINDTODEVICE
-       setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, pim->vrf->name,
-                  strlen(pim->vrf->name));
+       if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, pim->vrf->name,
+                      strlen(pim->vrf->name))) {
+               zlog_warn("Could not setsockopt SO_BINDTODEVICE: %s",
+                         safe_strerror(errno));
+               close(fd);
+               return -3;
+       }
 #endif
 
        if (pimd_privs.change(ZPRIVS_LOWER))
                zlog_err("pim_mroute_socket_enable: could not lower privs, %s",
                         safe_strerror(errno));
 
-       if (fd < 0) {
-               zlog_warn("Could not create mroute socket: errno=%d: %s", errno,
-                         safe_strerror(errno));
-               return -2;
-       }
-
        pim->mroute_socket = fd;
        if (pim_mroute_set(pim, 1)) {
                zlog_warn(
index 9473462e6325ed08db0400d4266b41f0e970e7bb..f245a043534af4557dca3210e35dfab4418e6906 100644 (file)
@@ -156,9 +156,15 @@ int pim_msdp_sock_listen(struct pim_instance *pim)
                if (!ifp) {
                        zlog_err("%s: Unable to lookup vrf interface: %s",
                                 __PRETTY_FUNCTION__, pim->vrf->name);
+                       close(sock);
+                       return -1;
+               }
+               if (pim_socket_bind(sock, ifp)) {
+                       zlog_err("%s: Unable to bind to socket: %s",
+                                __PRETTY_FUNCTION__, safe_strerror(errno));
+                       close(sock);
                        return -1;
                }
-               pim_socket_bind(sock, ifp);
        }
 
        if (pimd_privs.change(ZPRIVS_RAISE)) {
@@ -236,7 +242,13 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
                                 __PRETTY_FUNCTION__, mp->pim->vrf->name);
                        return -1;
                }
-               pim_socket_bind(mp->fd, ifp);
+               if (pim_socket_bind(mp->fd, ifp)) {
+                       zlog_err("%s: Unable to bind to socket: %s",
+                                __PRETTY_FUNCTION__, safe_strerror(errno));
+                       close(mp->fd);
+                       mp->fd = -1;
+                       return -1;
+               }
        }
 
        set_nonblocking(mp->fd);
index 05592992a9515df25a56e794df8566cc45f8282e..e2c411a307bf09a3372cf0470199e32b602d2fa2 100644 (file)
@@ -542,7 +542,9 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
        }
        pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info);
 
-       str2prefix("224.0.0.0/4", &g_all);
+       if (!str2prefix("224.0.0.0/4", &g_all))
+               return PIM_RP_BAD_ADDRESS;
+
        rp_all = pim_rp_find_match_group(pim, &g_all);
 
        if (rp_all == rp_info) {
index a4d3d7e4b36566f4a86e09134e0af8f6e1411956..a5a842ceee8a2d1e7e92d26b920d48037a728c79 100644 (file)
@@ -65,22 +65,21 @@ int pim_socket_raw(int protocol)
        return fd;
 }
 
-int pim_socket_ip_hdr(int fd)
+void pim_socket_ip_hdr(int fd)
 {
        const int on = 1;
-       int ret;
 
        if (pimd_privs.change(ZPRIVS_RAISE))
                zlog_err("%s: could not raise privs, %s", __PRETTY_FUNCTION__,
                         safe_strerror(errno));
 
-       ret = setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
+       if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)))
+               zlog_err("%s: Could not turn on IP_HDRINCL option: %s",
+                        __PRETTY_FUNCTION__, safe_strerror(errno));
 
        if (pimd_privs.change(ZPRIVS_LOWER))
                zlog_err("%s: could not lower privs, %s", __PRETTY_FUNCTION__,
                         safe_strerror(errno));
-
-       return ret;
 }
 
 /*
index aa46cd620072e19aefa380cd821228b2e5778f9c..358dd39a44de01167693a48e621915f8e3e5b7a1 100644 (file)
@@ -36,7 +36,7 @@
 #define PIM_SOCK_ERR_BIND    (-11) /* Can't bind to interface */
 
 int pim_socket_bind(int fd, struct interface *ifp);
-int pim_socket_ip_hdr(int fd);
+void pim_socket_ip_hdr(int fd);
 int pim_socket_raw(int protocol);
 int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp,
                     u_char loop);
index 8d270e620563fc8fbb8d0d9e754ec65b54329d3e..71bb6f2abd346be5a85d04b37f54a547970e75d1 100644 (file)
@@ -71,7 +71,10 @@ static int pim_is_grp_standard_ssm(struct prefix *group)
        static struct prefix group_ssm;
 
        if (first) {
-               str2prefix(PIM_SSM_STANDARD_RANGE, &group_ssm);
+               if (!str2prefix(PIM_SSM_STANDARD_RANGE, &group_ssm))
+                       zlog_err("%s: Failure to Read Group Address: %s",
+                                __PRETTY_FUNCTION__, PIM_SSM_STANDARD_RANGE);
+
                first = 0;
        }
 
index 96b9568c61cd426c8eaa51a9c595b0eff7c3d480..0bf2ce5d562e46f3523b566180a4424d93ea7368 100644 (file)
@@ -1364,7 +1364,7 @@ static int pim_upstream_register_stop_timer(struct thread *t)
                pim_upstream_start_register_stop_timer(up, 1);
 
                if (((up->channel_oil->cc.lastused / 100)
-                    > PIM_KEEPALIVE_PERIOD)
+                    > pim->keep_alive_time)
                    && (I_am_RP(pim_ifp->pim, up->sg.grp))) {
                        if (PIM_DEBUG_TRACE)
                                zlog_debug(
index 8914f6eb00518107788dd9c8994136cf25b30856..7607bdf13b2d6ba81d23da114258c407de14f67f 100644 (file)
@@ -255,10 +255,10 @@ int pim_interface_config_write(struct vty *vty)
 
                        /* IF name */
                        if (vrf->vrf_id == VRF_DEFAULT)
-                               vty_out(vty, "interface %s\n", ifp->name);
+                               vty_frame(vty, "interface %s\n", ifp->name);
                        else
-                               vty_out(vty, "interface %s vrf %s\n", ifp->name,
-                                       vrf->name);
+                               vty_frame(vty, "interface %s vrf %s\n",
+                                         ifp->name, vrf->name);
                        ++writes;
 
                        if (ifp->info) {
@@ -363,7 +363,7 @@ int pim_interface_config_write(struct vty *vty)
                                        pim_static_write_mroute(pim, vty, ifp);
                                pim_bfd_write_config(vty, ifp);
                        }
-                       vty_out(vty, "!\n");
+                       vty_endframe(vty, "!\n");
                        ++writes;
                }
        }
index 7b060aef4b6d5e06fe6deec7b3af688188ad2867..a1107e2424886628f97b9aed4aa3572a06ab7fb6 100644 (file)
@@ -184,6 +184,13 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient,
                            && (ifp->vrf_id != vrf->vrf_id)) {
                                struct interface *master = if_lookup_by_name(
                                        vrf->name, vrf->vrf_id);
+
+                               if (!master) {
+                                       zlog_debug("%s: Unable to find Master interface for %s",
+                                                  __PRETTY_FUNCTION__,
+                                                  vrf->name);
+                                       return 0;
+                               }
                                zclient_interface_set_master(zclient, master,
                                                             ifp);
                        }
index 3d104e7c7c606f4f64aed295203a027f9a30a5b1..bf44f3c94a47949f745cc1152f3598613a87b3ae 100644 (file)
@@ -139,7 +139,7 @@ int main(int argc, const char *argv[])
        printf("%s: waiting...\n", prog_name);
 
        if (getchar() == EOF)
-         fprintf(stderr, "getchar failure\n");
+               fprintf(stderr, "getchar failure\n");
 
        close(fd);
 
index cc0632b56252035f42cfab193f0ba3e88e506ad2..ea8a31236484bdc81eeaad3c7812cc848cedd6dc 100644 (file)
@@ -326,7 +326,7 @@ rm -f %{buildroot}%{_libdir}/frr/modules/*.la
 # install /etc sources
 %if "%{initsystem}" == "systemd"
 mkdir -p %{buildroot}%{_unitdir}
-install %{zeb_rh_src}/frr.service \
+install -m644 %{zeb_rh_src}/frr.service \
     %{buildroot}%{_unitdir}/frr.service
 install %{zeb_rh_src}/frr.init \
     %{buildroot}%{_sbindir}/frr
index 00b6d1cadd2aaafc3ed15d9e7b523fc2583eaf3c..1b2cbb61c32c7d0aae466a4f6423dbaf22261f6c 100644 (file)
@@ -1751,7 +1751,7 @@ static int rip_interface_config_write(struct vty *vty)
                    && (!ri->auth_str) && (!ri->key_chain))
                        continue;
 
-               vty_out(vty, "interface %s\n", ifp->name);
+               vty_frame(vty, "interface %s\n", ifp->name);
 
                if (ifp->desc)
                        vty_out(vty, " description %s\n", ifp->desc);
@@ -1807,7 +1807,7 @@ static int rip_interface_config_write(struct vty *vty)
                        vty_out(vty, " ip rip authentication key-chain %s\n",
                                ri->key_chain);
 
-               vty_out(vty, "!\n");
+               vty_endframe(vty, "!\n");
        }
        return 0;
 }
index cab25814c7bb2859a0828d7871fdf0b9186a6622..6d6d0b92fd2e54f8f7943e7b370ea7739c183d4c 100644 (file)
@@ -1685,6 +1685,7 @@ int rip_recvmsg(int sock, u_char *buf, int size, struct sockaddr_in *from,
        struct cmsghdr *ptr;
        char adata[1024];
 
+       memset(&msg, 0, sizeof(msg));
        msg.msg_name = (void *)from;
        msg.msg_namelen = sizeof(struct sockaddr_in);
        msg.msg_iov = &iov;
index 02fab6825483b48a77449e905063ec0e7c9ee78a..5c65f522ef826445e231bfba01dcb43bcedcfce4 100644 (file)
@@ -1084,7 +1084,7 @@ static int interface_config_write(struct vty *vty)
                    && (ri->split_horizon == ri->split_horizon_default))
                        continue;
 
-               vty_out(vty, "interface %s\n", ifp->name);
+               vty_frame(vty, "interface %s\n", ifp->name);
                if (ifp->desc)
                        vty_out(vty, " description %s\n", ifp->desc);
 
@@ -1105,7 +1105,7 @@ static int interface_config_write(struct vty *vty)
                        }
                }
 
-               vty_out(vty, "!\n");
+               vty_endframe(vty, "!\n");
 
                write++;
        }
index 926adf101dbd68de3e7f5cfd0dbdddcf04cc4377..e4368c9f9f51653bf95cf411e2a8603221637ffe 100644 (file)
@@ -176,6 +176,7 @@ int ripng_send_packet(caddr_t buf, int bufsize, struct sockaddr_in6 *to,
                addr.sin6_port = htons(RIPNG_PORT_DEFAULT);
        }
 
+       memset(&msg, 0, sizeof(msg));
        msg.msg_name = (void *)&addr;
        msg.msg_namelen = sizeof(struct sockaddr_in6);
        msg.msg_iov = &iov;
@@ -228,6 +229,7 @@ static int ripng_recv_packet(int sock, u_char *buf, int bufsize,
        char adata[1024];
 
        /* Fill in message and iovec. */
+       memset(&msg, 0, sizeof(msg));
        msg.msg_name = (void *)from;
        msg.msg_namelen = sizeof(struct sockaddr_in6);
        msg.msg_iov = &iov;
index 604ffaa8b63f30ffdc54cb30e4b84176c7c1d515..41349cce24b7fd93d506b4b5ab2567cf99680b14 100644 (file)
@@ -45,4 +45,5 @@ __pycache__
 /lib/test_timer_correctness
 /lib/test_timer_performance
 /lib/test_ttable
+/lib/test_zmq
 /ospf6d/test_lsdb
index 59ea3c4c6998a0b0bcf2008dd124ee208ef45a18..8a8918dcb428304ee9197a8ed0f06a4b263f4026 100644 (file)
@@ -72,6 +72,12 @@ check_PROGRAMS = \
        $(TESTS_OSPF6D) \
        # end
 
+if ZEROMQ
+check_PROGRAMS += \
+       lib/test_zmq \
+       # end
+endif
+
 ../vtysh/vtysh_cmd.c:
        $(MAKE) -C ../vtysh vtysh_cmd.c
 
@@ -112,6 +118,8 @@ lib_test_timer_correctness_SOURCES = lib/test_timer_correctness.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 \
@@ -147,6 +155,7 @@ 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)
index bda0bbac44ebdf0cdf1ea8c9cfc68988818b62bc..d55345186a2f18f1b5a7299a2c916d3096a004ae 100644 (file)
@@ -8,4 +8,4 @@ class TestCommands(frrtest.TestRefOut):
     @pytest.mark.skipif('QUAGGA_TEST_COMMANDS' not in os.environ,
                         reason='QUAGGA_TEST_COMMANDS not set')
     def test_refout(self):
-        return super(TestCommands, self).test_refout(self)
+        return super(TestCommands, self).test_refout()
diff --git a/tests/lib/test_zmq.c b/tests/lib/test_zmq.c
new file mode 100644 (file)
index 0000000..c270ec3
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * ZeroMQ event test
+ * Copyright (C) 2017  David Lamparter, for NetDEF, Inc.
+ *
+ * This program 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 of the License, or (at your option)
+ * any later version.
+ *
+ * This program 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 "sigevent.h"
+#include "frr_zmq.h"
+
+DEFINE_MTYPE_STATIC(LIB, TESTBUF, "zmq test buffer")
+
+static struct thread_master *master;
+
+static void msg_buf_free(void *data, void *hint)
+{
+       XFREE(MTYPE_TESTBUF, data);
+}
+
+static void run_client(int syncfd)
+{
+       int i, j;
+       char buf[32];
+       char dummy;
+       void *zmqctx = NULL;
+       void *zmqsock;
+
+       read(syncfd, &dummy, 1);
+
+       zmqctx = zmq_ctx_new();
+       zmq_ctx_set(zmqctx, ZMQ_IPV6, 1);
+
+       zmqsock = zmq_socket(zmqctx, ZMQ_REQ);
+       if (zmq_connect(zmqsock, "tcp://127.0.0.1:17171")) {
+               perror("zmq_connect");
+               exit(1);
+       }
+
+       /* single-part */
+       for (i = 0; i < 8; i++) {
+               snprintf(buf, sizeof(buf), "msg #%d %c%c%c",
+                        i, 'a' + i, 'b' + i, 'c' + i);
+               printf("client send: %s\n", buf);
+               fflush(stdout);
+               zmq_send(zmqsock, buf, strlen(buf) + 1, 0);
+               zmq_recv(zmqsock, buf, sizeof(buf), 0);
+               printf("client recv: %s\n", buf);
+       }
+
+       /* multipart */
+       for (i = 2; i < 5; i++) {
+               int more;
+
+               printf("---\n");
+               for (j = 1; j <= i; j++) {
+                       zmq_msg_t part;
+                       char *dyn = XMALLOC(MTYPE_TESTBUF, 32);
+
+                       snprintf(dyn, 32, "part %d/%d", j, i);
+                       printf("client send: %s\n", dyn);
+                       fflush(stdout);
+
+                       zmq_msg_init_data(&part, dyn, strlen(dyn) + 1,
+                                         msg_buf_free, NULL);
+                       zmq_msg_send(&part, zmqsock, j < i ? ZMQ_SNDMORE : 0);
+               }
+
+               zmq_msg_t part;
+               do {
+                       char *data;
+
+                       zmq_msg_recv(&part, zmqsock, 0);
+                       data = zmq_msg_data(&part);
+                       more = zmq_msg_more(&part);
+                       printf("client recv (more: %d): %s\n", more, data);
+               } while (more);
+               zmq_msg_close(&part);
+       }
+       zmq_close(zmqsock);
+       zmq_ctx_term(zmqctx);
+}
+
+static struct frrzmq_cb *cb;
+
+static void serverpartfn(void *arg, void *zmqsock, zmq_msg_t *msg,
+                       unsigned partnum)
+{
+       int more = zmq_msg_more(msg);
+       char *in = zmq_msg_data(msg);
+       size_t i;
+       zmq_msg_t reply;
+       char *out;
+
+       printf("server recv part %u (more: %d): %s\n", partnum, more, in);
+       fflush(stdout);
+       /* REQ-REP doesn't allow sending a reply here */
+       if (more)
+               return;
+
+       out = XMALLOC(MTYPE_TESTBUF, strlen(in) + 1);
+       for (i = 0; i < strlen(in); i++)
+               out[i] = toupper(in[i]);
+       out[i] = '\0';
+       zmq_msg_init_data(&reply, out, strlen(out) + 1, msg_buf_free, NULL);
+       zmq_msg_send(&reply, zmqsock, ZMQ_SNDMORE);
+
+       out = XMALLOC(MTYPE_TESTBUF, 32);
+       snprintf(out, 32, "msg# was %u", partnum);
+       zmq_msg_init_data(&reply, out, strlen(out) + 1, msg_buf_free, NULL);
+       zmq_msg_send(&reply, zmqsock, 0);
+}
+
+static void serverfn(void *arg, void *zmqsock)
+{
+       static int num = 0;
+
+       char buf[32];
+       size_t i;
+       zmq_recv(zmqsock, buf, sizeof(buf), 0);
+
+       printf("server recv: %s\n", buf);
+       fflush(stdout);
+       for (i = 0; i < strlen(buf); i++)
+               buf[i] = toupper(buf[i]);
+       zmq_send(zmqsock, buf, strlen(buf) + 1, 0);
+
+       if (++num < 4)
+               return;
+
+       /* change to multipart callback */
+       frrzmq_thread_cancel(cb);
+
+       cb = frrzmq_thread_add_read_part(master, serverpartfn, NULL, zmqsock);
+}
+
+static void sigchld(void)
+{
+       printf("child exited.\n");
+       frrzmq_thread_cancel(cb);
+}
+
+static struct quagga_signal_t sigs[] = {
+       {
+               .signal = SIGCHLD,
+               .handler = sigchld,
+       },
+};
+
+static void run_server(int syncfd)
+{
+       void *zmqsock;
+       char dummy = 0;
+       struct thread t;
+
+       master = thread_master_create(NULL);
+       signal_init(master, array_size(sigs), sigs);
+       frrzmq_init();
+
+       zmqsock = zmq_socket(frrzmq_context, ZMQ_REP);
+       if (zmq_bind(zmqsock, "tcp://*:17171")) {
+               perror("zmq_bind");
+               exit(1);
+       }
+
+       cb = frrzmq_thread_add_read_msg(master, serverfn, NULL, zmqsock);
+
+       write(syncfd, &dummy, sizeof(dummy));
+       while (thread_fetch(master, &t))
+               thread_call(&t);
+
+       zmq_close(zmqsock);
+       frrzmq_finish();
+       thread_master_free(master);
+       log_memstats_stderr("test");
+}
+
+int main(void)
+{
+       int syncpipe[2];
+       pid_t child;
+
+       if (pipe(syncpipe)) {
+               perror("pipe");
+               exit(1);
+       }
+
+       child = fork();
+       if (child < 0) {
+               perror("fork");
+               exit(1);
+       } else if (child == 0) {
+               run_client(syncpipe[0]);
+               exit(0);
+       }
+
+       run_server(syncpipe[1]);
+       exit(0);
+}
diff --git a/tests/lib/test_zmq.py b/tests/lib/test_zmq.py
new file mode 100644 (file)
index 0000000..1f8ee54
--- /dev/null
@@ -0,0 +1,11 @@
+import frrtest
+import pytest
+import os
+
+class TestZMQ(frrtest.TestRefOut):
+    program = './test_zmq'
+
+    @pytest.mark.skipif('S["ZEROMQ_TRUE"]=""\n' not in open('../config.status').readlines(),
+                        reason='ZEROMQ not enabled')
+    def test_refout(self):
+        return super(TestZMQ, self).test_refout()
diff --git a/tests/lib/test_zmq.refout b/tests/lib/test_zmq.refout
new file mode 100644 (file)
index 0000000..61f45f0
--- /dev/null
@@ -0,0 +1,50 @@
+client send: msg #0 abc
+server recv: msg #0 abc
+client recv: MSG #0 ABC
+client send: msg #1 bcd
+server recv: msg #1 bcd
+client recv: MSG #1 BCD
+client send: msg #2 cde
+server recv: msg #2 cde
+client recv: MSG #2 CDE
+client send: msg #3 def
+server recv: msg #3 def
+client recv: MSG #3 DEF
+client send: msg #4 efg
+server recv part 0 (more: 0): msg #4 efg
+client recv: MSG #4 EFG
+client send: msg #5 fgh
+client recv: msg# was 0
+client send: msg #6 ghi
+server recv part 0 (more: 0): msg #6 ghi
+client recv: MSG #6 GHI
+client send: msg #7 hij
+client recv: msg# was 0
+---
+client send: part 1/2
+client send: part 2/2
+server recv part 0 (more: 1): part 1/2
+server recv part 1 (more: 0): part 2/2
+client recv (more: 1): PART 2/2
+client recv (more: 0): msg# was 1
+---
+client send: part 1/3
+client send: part 2/3
+client send: part 3/3
+server recv part 0 (more: 1): part 1/3
+server recv part 1 (more: 1): part 2/3
+server recv part 2 (more: 0): part 3/3
+client recv (more: 1): PART 3/3
+client recv (more: 0): msg# was 2
+---
+client send: part 1/4
+client send: part 2/4
+client send: part 3/4
+client send: part 4/4
+server recv part 0 (more: 1): part 1/4
+server recv part 1 (more: 1): part 2/4
+server recv part 2 (more: 1): part 3/4
+server recv part 3 (more: 0): part 4/4
+client recv (more: 1): PART 4/4
+client recv (more: 0): msg# was 3
+child exited.
index 85cbcae4dfa4db8b10b84e980a8c4e2b0cca1513..cbfdf4112784f4d9e77c6a9908548d71a0f7721d 100644 (file)
@@ -2295,12 +2295,12 @@ int vtysh_write_config_integrated(void)
 
        fprintf(stdout, "Building Configuration...\n");
 
-       backup_config_file(quagga_config);
-       fp = fopen(quagga_config, "w");
+       backup_config_file(frr_config);
+       fp = fopen(frr_config, "w");
        if (fp == NULL) {
                fprintf(stdout,
                        "%% Error: failed to open configuration file %s: %s\n",
-                       quagga_config, safe_strerror(errno));
+                       frr_config, safe_strerror(errno));
                return CMD_WARNING_CONFIG_FAILED;
        }
        fd = fileno(fp);
@@ -2313,7 +2313,7 @@ int vtysh_write_config_integrated(void)
 
        if (fchmod(fd, CONFIGFILE_MASK) != 0) {
                printf("%% Warning: can't chmod configuration file %s: %s\n",
-                      quagga_config, safe_strerror(errno));
+                      frr_config, safe_strerror(errno));
                err++;
        }
 
@@ -2345,18 +2345,18 @@ int vtysh_write_config_integrated(void)
                if ((uid != (uid_t)-1 || gid != (gid_t)-1)
                    && fchown(fd, uid, gid)) {
                        printf("%% Warning: can't chown configuration file %s: %s\n",
-                              quagga_config, safe_strerror(errno));
+                              frr_config, safe_strerror(errno));
                        err++;
                }
        } else {
-               printf("%% Warning: stat() failed on %s: %s\n", quagga_config,
+               printf("%% Warning: stat() failed on %s: %s\n", frr_config,
                       safe_strerror(errno));
                err++;
        }
 
        fclose(fp);
 
-       printf("Integrated configuration saved to %s\n", quagga_config);
+       printf("Integrated configuration saved to %s\n", frr_config);
        if (err)
                return CMD_WARNING;
 
@@ -2370,7 +2370,7 @@ static bool want_config_integrated(void)
 
        switch (vtysh_write_integrated) {
        case WRITE_INTEGRATED_UNSPECIFIED:
-               if (stat(quagga_config, &s) && errno == ENOENT)
+               if (stat(frr_config, &s) && errno == ENOENT)
                        return false;
                return true;
        case WRITE_INTEGRATED_NO:
@@ -2712,7 +2712,7 @@ static int vtysh_connect(struct vtysh_client *vclient)
 
        if (!vclient->path[0])
                snprintf(vclient->path, sizeof(vclient->path), "%s/%s.vty",
-                        vty_sock_path, vclient->name);
+                        vtydir, vclient->name);
        path = vclient->path;
 
        /* Stat socket to see if we have permission to access it. */
@@ -2806,7 +2806,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client)
                return;
 
        /* ls vty_sock_dir and look for all files ending in .vty */
-       dir = opendir(vty_sock_path);
+       dir = opendir(vtydir);
        if (dir) {
                while ((file = readdir(dir)) != NULL) {
                        if (begins_with(file->d_name, "ospfd-")
@@ -2814,7 +2814,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client)
                                if (n == MAXIMUM_INSTANCES) {
                                        fprintf(stderr,
                                                "Parsing %s, client limit(%d) reached!\n",
-                                               vty_sock_path, n);
+                                               vtydir, n);
                                        break;
                                }
                                client = (struct vtysh_client *)malloc(
@@ -2823,7 +2823,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client)
                                client->name = "ospfd";
                                client->flag = VTYSH_OSPFD;
                                snprintf(client->path, sizeof(client->path),
-                                        "%s/%s", vty_sock_path, file->d_name);
+                                        "%s/%s", vtydir, file->d_name);
                                client->next = NULL;
                                vtysh_client_sorted_insert(head_client, client);
                                n++;
@@ -2891,21 +2891,9 @@ void vtysh_readline_init(void)
 
 char *vtysh_prompt(void)
 {
-       static struct utsname names;
        static char buf[100];
-       const char *hostname;
-       extern struct host host;
-
-       hostname = host.name;
-
-       if (!hostname) {
-               if (!names.nodename[0])
-                       uname(&names);
-               hostname = names.nodename;
-       }
-
-       snprintf(buf, sizeof buf, cmd_prompt(vty->node), hostname);
 
+       snprintf(buf, sizeof buf, cmd_prompt(vty->node), cmd_hostname_get());
        return buf;
 }
 
index b0866ec7f3fa20e22ce051041a6c79755e700229..9d6ea4bda440df6c43e9b3f6deea0b22ca6b122c 100644 (file)
@@ -49,10 +49,6 @@ DECLARE_MGROUP(MVTYSH)
 #define VTYSH_NS          VTYSH_ZEBRA
 #define VTYSH_VRF        VTYSH_ZEBRA|VTYSH_PIMD
 
-/* vtysh local configuration file. */
-#define VTYSH_DEFAULT_CONFIG "vtysh.conf"
-#define FRR_DEFAULT_CONFIG "frr.conf"
-
 enum vtysh_write_integrated {
        WRITE_INTEGRATED_UNSPECIFIED,
        WRITE_INTEGRATED_NO,
@@ -61,7 +57,8 @@ enum vtysh_write_integrated {
 
 extern enum vtysh_write_integrated vtysh_write_integrated;
 
-extern char *quagga_config;
+extern char frr_config[];
+extern char vtydir[];
 
 void vtysh_init_vty(void);
 void vtysh_init_cmd(void);
@@ -93,11 +90,12 @@ void vtysh_config_init(void);
 
 void vtysh_pager_init(void);
 
+void suid_on(void);
+void suid_off(void);
+
 /* Child process execution flag. */
 extern int execute_flag;
 
 extern struct vty *vty;
 
-extern const char *vty_sock_path;
-
 #endif /* VTYSH_H */
index c561b5222f2bd77ea5b9d8b62c2cf95f3f12aace..d7e79d6b2cc1660758a8d279d1c55f3f014d7b1c 100644 (file)
@@ -245,7 +245,10 @@ void vtysh_config_parse_line(void *arg, const char *line)
                                 == 0
                         || strncmp(line, "ip extcommunity-list",
                                    strlen("ip extcommunity-list"))
-                                   == 0)
+                                == 0
+                        || strncmp(line, "ip large-community-list",
+                                   strlen("ip large-community-list"))
+                                == 0)
                        config = config_get(COMMUNITY_LIST_NODE, line);
                else if (strncmp(line, "ip route", strlen("ip route")) == 0)
                        config = config_get(IP_NODE, line);
@@ -420,10 +423,9 @@ int vtysh_read_config(const char *config_default_dir)
 void vtysh_config_write()
 {
        char line[81];
-       extern struct host host;
 
-       if (host.name) {
-               sprintf(line, "hostname %s", host.name);
+       if (cmd_hostname_get()) {
+               sprintf(line, "hostname %s", cmd_hostname_get());
                vtysh_config_parse_line(NULL, line);
        }
        if (vtysh_write_integrated == WRITE_INTEGRATED_NO)
index 8145bf364115bd9abfc3897f4b42acccdb852f7d..f4c21e69cd904eed61fe8c90ee6adf6861a3d061 100644 (file)
 /* VTY shell program name. */
 char *progname;
 
+/* SUID mode */
+static uid_t elevuid, realuid;
+static gid_t elevgid, realgid;
+
+#define VTYSH_CONFIG_NAME "vtysh.conf"
+#define FRR_CONFIG_NAME "frr.conf"
+
 /* Configuration file name and directory. */
-static char vtysh_config_always[MAXPATHLEN] = SYSCONFDIR VTYSH_DEFAULT_CONFIG;
-static char quagga_config_default[MAXPATHLEN] = SYSCONFDIR FRR_DEFAULT_CONFIG;
-char *quagga_config = quagga_config_default;
-char history_file[MAXPATHLEN];
+static char vtysh_config[MAXPATHLEN];
+char frr_config[MAXPATHLEN];
+char vtydir[MAXPATHLEN];
+static char history_file[MAXPATHLEN];
 
 /* Flag for indicate executing child command. */
 int execute_flag = 0;
 
-/* VTY Socket prefix */
-const char *vty_sock_path = NULL;
-
 /* For sigsetjmp() & siglongjmp(). */
 static sigjmp_buf jmpbuf;
 
@@ -145,6 +149,7 @@ static void usage(int status)
                       "-m, --markfile           Mark input file with context end\n"
                       "    --vty_socket         Override vty socket path\n"
                       "    --config_dir         Override config directory path\n"
+                      "-N  --pathspace          Insert prefix into config & socket paths\n"
                       "-w, --writeconfig        Write integrated config (frr.conf) and exit\n"
                       "-h, --help               Display this help and exit\n\n"
                       "Note that multiple commands may be executed from the command\n"
@@ -174,6 +179,7 @@ struct option longopts[] = {
        {"noerror", no_argument, NULL, 'n'},
        {"mark", no_argument, NULL, 'm'},
        {"writeconfig", no_argument, NULL, 'w'},
+       {"pathspace", no_argument, NULL, 'N'},
        {0}};
 
 /* Read a string, and return a pointer to it.  Returns NULL on EOF. */
@@ -249,6 +255,30 @@ static void vtysh_unflock_config(void)
        close(flock_fd);
 }
 
+void suid_on(void)
+{
+       if (elevuid != realuid && seteuid(elevuid)) {
+               perror("seteuid(on)");
+               exit(1);
+       }
+       if (elevgid != realgid && setegid(elevgid)) {
+               perror("setegid(on)");
+               exit(1);
+       }
+}
+
+void suid_off(void)
+{
+       if (elevuid != realuid && seteuid(realuid)) {
+               perror("seteuid(off)");
+               exit(1);
+       }
+       if (elevgid != realgid && setegid(realgid)) {
+               perror("setegid(off)");
+               exit(1);
+       }
+}
+
 /* VTY shell main routine. */
 int main(int argc, char **argv, char **env)
 {
@@ -258,7 +288,6 @@ int main(int argc, char **argv, char **env)
        int boot_flag = 0;
        const char *daemon_name = NULL;
        const char *inputfile = NULL;
-       const char *vtysh_configfile_name;
        struct cmd_rec {
                char *line;
                struct cmd_rec *next;
@@ -270,16 +299,22 @@ int main(int argc, char **argv, char **env)
        int writeconfig = 0;
        int ret = 0;
        char *homedir = NULL;
+       int ditch_suid = 0;
+       char sysconfdir[MAXPATHLEN];
+       char pathspace[MAXPATHLEN] = "";
 
-       /* check for restricted functionality if vtysh is run setuid */
-       int restricted = (getuid() != geteuid()) || (getgid() != getegid());
+       /* SUID: drop down to calling user & go back up when needed */
+       elevuid = geteuid();
+       elevgid = getegid();
+       realuid = getuid();
+       realgid = getgid();
+       suid_off();
 
        /* Preserve name of myself. */
        progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]);
 
-       /* if logging open now */
-       if ((p = getenv("VTYSH_LOG")) != NULL)
-               logfile = fopen(p, "a");
+       strlcpy(sysconfdir, frr_sysconfdir, sizeof(sysconfdir));
+       strlcpy(vtydir, frr_vtydir, sizeof(vtydir));
 
        /* Option handling. */
        while (1) {
@@ -307,63 +342,20 @@ int main(int argc, char **argv, char **env)
                        tail = cr;
                } break;
                case OPTION_VTYSOCK:
-                       vty_sock_path = optarg;
+                       ditch_suid = 1; /* option disables SUID */
+                       strlcpy(vtydir, optarg, sizeof(vtydir));
                        break;
                case OPTION_CONFDIR:
-                       /*
-                        * Skip option for Config Directory if setuid
-                        */
-                       if (restricted) {
+                       ditch_suid = 1; /* option disables SUID */
+                       strlcpy(sysconfdir, optarg, sizeof(sysconfdir));
+                       break;
+               case 'N':
+                       if (strchr(optarg, '/') || strchr(optarg, '.')) {
                                fprintf(stderr,
-                                       "Overriding of Config Directory blocked for vtysh with setuid");
-                               return 1;
+                                       "slashes or dots are not permitted in the --pathspace option.\n");
+                               exit(1);
                        }
-                       /*
-                        * Overwrite location for vtysh.conf
-                        */
-                       vtysh_configfile_name =
-                               strrchr(VTYSH_DEFAULT_CONFIG, '/');
-                       if (vtysh_configfile_name)
-                               /* skip '/' */
-                               vtysh_configfile_name++;
-                       else
-                               /*
-                                * VTYSH_DEFAULT_CONFIG configured with relative
-                                * path
-                                * during config? Should really never happen for
-                                * sensible config
-                                */
-                               vtysh_configfile_name =
-                                       (char *)VTYSH_DEFAULT_CONFIG;
-                       strlcpy(vtysh_config_always, optarg,
-                               sizeof(vtysh_config_always));
-                       strlcat(vtysh_config_always, "/",
-                               sizeof(vtysh_config_always));
-                       strlcat(vtysh_config_always, vtysh_configfile_name,
-                               sizeof(vtysh_config_always));
-                       /*
-                        * Overwrite location for frr.conf
-                        */
-                       vtysh_configfile_name =
-                               strrchr(FRR_DEFAULT_CONFIG, '/');
-                       if (vtysh_configfile_name)
-                               /* skip '/' */
-                               vtysh_configfile_name++;
-                       else
-                               /*
-                                * FRR_DEFAULT_CONFIG configured with relative
-                                * path
-                                * during config? Should really never happen for
-                                * sensible config
-                                */
-                               vtysh_configfile_name =
-                                       (char *)FRR_DEFAULT_CONFIG;
-                       strlcpy(quagga_config_default, optarg,
-                               sizeof(vtysh_config_always));
-                       strlcat(quagga_config_default, "/",
-                               sizeof(vtysh_config_always));
-                       strlcat(quagga_config_default, vtysh_configfile_name,
-                               sizeof(quagga_config_default));
+                       snprintf(pathspace, sizeof(pathspace), "/%s", optarg);
                        break;
                case 'd':
                        daemon_name = optarg;
@@ -395,8 +387,10 @@ int main(int argc, char **argv, char **env)
                }
        }
 
-       if (!vty_sock_path)
-               vty_sock_path = frr_vtydir;
+       if (ditch_suid) {
+               elevuid = realuid;
+               elevgid = realgid;
+       }
 
        if (markfile + writeconfig + dryrun + boot_flag > 1) {
                fprintf(stderr,
@@ -410,6 +404,12 @@ int main(int argc, char **argv, char **env)
                        "NOT SUPPORTED since its\nresults are inconsistent!\n");
        }
 
+       snprintf(vtysh_config, sizeof(vtysh_config), "%s%s/%s", sysconfdir,
+                pathspace, VTYSH_CONFIG_NAME);
+       snprintf(frr_config, sizeof(frr_config), "%s%s/%s", sysconfdir,
+                pathspace, FRR_CONFIG_NAME);
+       strlcat(vtydir, pathspace, sizeof(vtydir));
+
        /* Initialize user input buffer. */
        line_read = NULL;
        setlinebuf(stdout);
@@ -425,8 +425,11 @@ int main(int argc, char **argv, char **env)
 
        vty_init_vtysh();
 
-       /* Read vtysh configuration file before connecting to daemons. */
-       vtysh_read_config(vtysh_config_always);
+       /* Read vtysh configuration file before connecting to daemons.
+        * (file may not be readable to calling user in SUID mode) */
+       suid_on();
+       vtysh_read_config(vtysh_config);
+       suid_off();
 
        if (markfile) {
                if (!inputfile) {
@@ -442,7 +445,7 @@ int main(int argc, char **argv, char **env)
                if (inputfile) {
                        ret = vtysh_read_config(inputfile);
                } else {
-                       ret = vtysh_read_config(quagga_config_default);
+                       ret = vtysh_read_config(frr_config);
                }
 
                exit(ret);
@@ -486,6 +489,9 @@ int main(int argc, char **argv, char **env)
                }
        }
 
+       /* SUID: go back up elevated privs */
+       suid_on();
+
        /* Make sure we pass authentication before proceeding. */
        vtysh_auth();
 
@@ -498,6 +504,9 @@ int main(int argc, char **argv, char **env)
                        exit(1);
        }
 
+       /* SUID: back down, don't need privs further on */
+       suid_off();
+
        if (writeconfig) {
                vtysh_execute("enable");
                return vtysh_write_config_integrated();
@@ -531,6 +540,17 @@ int main(int argc, char **argv, char **env)
                }
        }
 
+       if (getenv("VTYSH_LOG")) {
+               const char *logpath = getenv("VTYSH_LOG");
+
+               logfile = fopen(logpath, "a");
+               if (!logfile) {
+                       fprintf(stderr, "Failed to open logfile (%s): %s\n",
+                               logpath, strerror(errno));
+                       exit(1);
+               }
+       }
+
        /* If eval mode. */
        if (cmd) {
                /* Enter into enable node. */
@@ -592,13 +612,13 @@ int main(int argc, char **argv, char **env)
 
        /* Boot startup configuration file. */
        if (boot_flag) {
-               vtysh_flock_config(quagga_config);
-               int ret = vtysh_read_config(quagga_config);
+               vtysh_flock_config(frr_config);
+               int ret = vtysh_read_config(frr_config);
                vtysh_unflock_config();
                if (ret) {
                        fprintf(stderr,
                                "Configuration file[%s] processing failure: %d\n",
-                               quagga_config, ret);
+                               frr_config, ret);
                        if (no_error)
                                exit(0);
                        else
index 701314f2461acd56423217b842712ecd3d7577b1..7176ce70bd0c29e8168e16bf8370b680fdfaf27e 100644 (file)
@@ -100,8 +100,10 @@ static void connected_announce(struct interface *ifp, struct connected *ifc)
 }
 
 /* If same interface address is already exist... */
-struct connected *connected_check(struct interface *ifp, struct prefix *p)
+struct connected *connected_check(struct interface *ifp,
+                                 union prefixconstptr pu)
 {
+       const struct prefix *p = pu.p;
        struct connected *ifc;
        struct listnode *node;
 
@@ -112,6 +114,33 @@ struct connected *connected_check(struct interface *ifp, struct prefix *p)
        return NULL;
 }
 
+/* same, but with peer address */
+struct connected *connected_check_ptp(struct interface *ifp,
+                                     union prefixconstptr pu,
+                                     union prefixconstptr du)
+{
+       const struct prefix *p = pu.p;
+       const struct prefix *d = du.p;
+       struct connected *ifc;
+       struct listnode *node;
+
+       /* ignore broadcast addresses */
+       if (p->prefixlen != IPV4_MAX_PREFIXLEN)
+               d = NULL;
+
+       for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
+               if (!prefix_same(ifc->address, p))
+                       continue;
+               if (!CONNECTED_PEER(ifc) && !d)
+                       return ifc;
+               if (CONNECTED_PEER(ifc) && d
+                   && prefix_same(ifc->destination, d))
+                       return ifc;
+       }
+
+       return NULL;
+}
+
 /* Check if two ifc's describe the same address in the same state */
 static int connected_same(struct connected *ifc1, struct connected *ifc2)
 {
@@ -145,7 +174,8 @@ static void connected_update(struct interface *ifp, struct connected *ifc)
        struct connected *current;
 
        /* Check same connected route. */
-       if ((current = connected_check(ifp, (struct prefix *)ifc->address))) {
+       current = connected_check_ptp(ifp, ifc->address, ifc->destination);
+       if (current) {
                if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
                        SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
 
@@ -177,6 +207,9 @@ static void connected_update(struct interface *ifp, struct connected *ifc)
 void connected_up_ipv4(struct interface *ifp, struct connected *ifc)
 {
        struct prefix p;
+       struct nexthop nh = {
+               .type = NEXTHOP_TYPE_IFINDEX, .ifindex = ifp->ifindex,
+       };
 
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
                return;
@@ -192,12 +225,10 @@ void connected_up_ipv4(struct interface *ifp, struct connected *ifc)
                return;
 
        rib_add(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
-               &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric,
-               0, 0);
+               &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
 
        rib_add(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
-               &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric,
-               0, 0);
+               &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
 
        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                zlog_debug(
@@ -238,7 +269,8 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
        p = prefix_ipv4_new();
        p->family = AF_INET;
        p->prefix = *addr;
-       p->prefixlen = prefixlen;
+       p->prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
+                                                        : prefixlen;
        ifc->address = (struct prefix *)p;
 
        /* If there is broadcast or peer address. */
@@ -306,6 +338,9 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
 void connected_down_ipv4(struct interface *ifp, struct connected *ifc)
 {
        struct prefix p;
+       struct nexthop nh = {
+               .type = NEXTHOP_TYPE_IFINDEX, .ifindex = ifp->ifindex,
+       };
 
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
                return;
@@ -323,10 +358,10 @@ void connected_down_ipv4(struct interface *ifp, struct connected *ifc)
        /* Same logic as for connected_up_ipv4(): push the changes into the
         * head. */
        rib_delete(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
-                  &p, NULL, NULL, ifp->ifindex, 0, 0);
+                  &p, NULL, &nh, 0, 0);
 
        rib_delete(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
-                  0, &p, NULL, NULL, ifp->ifindex, 0, 0);
+                  0, &p, NULL, &nh, 0, 0);
 
        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                zlog_debug(
@@ -350,15 +385,25 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
                           struct in_addr *addr, u_char prefixlen,
                           struct in_addr *broad)
 {
-       struct prefix_ipv4 p;
+       struct prefix_ipv4 p, d;
        struct connected *ifc;
 
        memset(&p, 0, sizeof(struct prefix_ipv4));
        p.family = AF_INET;
        p.prefix = *addr;
-       p.prefixlen = prefixlen;
+       p.prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
+                                                       : prefixlen;
+
+       if (broad) {
+               memset(&d, 0, sizeof(struct prefix_ipv4));
+               d.family = AF_INET;
+               d.prefix = *broad;
+               d.prefixlen = prefixlen;
+               ifc = connected_check_ptp(ifp, (struct prefix *)&p,
+                                         (struct prefix *)&d);
+       } else
+               ifc = connected_check_ptp(ifp, (struct prefix *)&p, NULL);
 
-       ifc = connected_check(ifp, (struct prefix *)&p);
        if (!ifc)
                return;
 
@@ -384,6 +429,9 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
 void connected_up_ipv6(struct interface *ifp, struct connected *ifc)
 {
        struct prefix p;
+       struct nexthop nh = {
+               .type = NEXTHOP_TYPE_IFINDEX, .ifindex = ifp->ifindex,
+       };
 
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
                return;
@@ -400,8 +448,7 @@ void connected_up_ipv6(struct interface *ifp, struct connected *ifc)
 #endif
 
        rib_add(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
-               &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric,
-               0, 0);
+               &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
 
        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                zlog_debug(
@@ -422,8 +469,7 @@ void connected_up_ipv6(struct interface *ifp, struct connected *ifc)
 
 /* Add connected IPv6 route to the interface. */
 void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
-                       u_char prefixlen, struct in6_addr *broad,
-                       const char *label)
+                       u_char prefixlen, const char *label)
 {
        struct prefix_ipv6 *p;
        struct connected *ifc;
@@ -446,29 +492,6 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
        p->prefixlen = prefixlen;
        ifc->address = (struct prefix *)p;
 
-       /* If there is broadcast or peer address. */
-       if (broad) {
-               if (IN6_IS_ADDR_UNSPECIFIED(broad))
-                       zlog_warn(
-                               "warning: %s called for interface %s with unspecified "
-                               "destination address; ignoring!",
-                               __func__, ifp->name);
-               else {
-                       p = prefix_ipv6_new();
-                       p->family = AF_INET6;
-                       IPV6_ADDR_COPY(&p->prefix, broad);
-                       p->prefixlen = prefixlen;
-                       ifc->destination = (struct prefix *)p;
-               }
-       }
-       if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination) {
-               zlog_warn(
-                       "warning: %s called for interface %s "
-                       "with peer flag set, but no peer address supplied",
-                       __func__, ifp->name);
-               UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
-       }
-
        /* Label of this address. */
        if (label)
                ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
@@ -489,6 +512,9 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
 void connected_down_ipv6(struct interface *ifp, struct connected *ifc)
 {
        struct prefix p;
+       struct nexthop nh = {
+               .type = NEXTHOP_TYPE_IFINDEX, .ifindex = ifp->ifindex,
+       };
 
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
                return;
@@ -501,7 +527,7 @@ void connected_down_ipv6(struct interface *ifp, struct connected *ifc)
                return;
 
        rib_delete(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
-                  0, &p, NULL, NULL, ifp->ifindex, 0, 0);
+                  0, &p, NULL, &nh, 0, 0);
 
        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                zlog_debug(
@@ -521,7 +547,7 @@ void connected_down_ipv6(struct interface *ifp, struct connected *ifc)
 }
 
 void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
-                          u_char prefixlen, struct in6_addr *broad)
+                          u_char prefixlen)
 {
        struct prefix_ipv6 p;
        struct connected *ifc;
index eaf79fe9aadd5b3a00501c9764a954ebb8d2188b..c6da36956d52892936b54b368d87b634fa792d40 100644 (file)
 #define _ZEBRA_CONNECTED_H
 
 extern struct connected *connected_check(struct interface *ifp,
-                                        struct prefix *p);
+                                        union prefixconstptr p);
+extern struct connected *connected_check_ptp(struct interface *ifp,
+                                            union prefixconstptr p,
+                                            union prefixconstptr d);
 
 extern void connected_add_ipv4(struct interface *ifp, int flags,
                               struct in_addr *addr, u_char prefixlen,
@@ -40,10 +43,9 @@ extern void connected_down_ipv4(struct interface *, struct connected *);
 
 extern void connected_add_ipv6(struct interface *ifp, int flags,
                               struct in6_addr *address, u_char prefixlen,
-                              struct in6_addr *broad, const char *label);
+                              const char *label);
 extern void connected_delete_ipv6(struct interface *ifp,
-                                 struct in6_addr *address, u_char prefixlen,
-                                 struct in6_addr *broad);
+                                 struct in6_addr *address, u_char prefixlen);
 
 extern void connected_up_ipv6(struct interface *, struct connected *);
 extern void connected_down_ipv6(struct interface *ifp, struct connected *);
index a65fcb2b8c20eb91d74007d64fd2704ca7bdde76..6396911e1b9c8d2db48ad27e2c36e35004c6fa7a 100644 (file)
@@ -214,7 +214,7 @@ static int if_getaddrs(void)
 
                        dest_pnt = NULL;
 
-                       if (ifap->ifa_dstaddr
+                       if (if_is_pointopoint(ifp) && ifap->ifa_dstaddr
                            && !IPV4_ADDR_SAME(&addr->sin_addr,
                                               &((struct sockaddr_in *)
                                                         ifap->ifa_dstaddr)
@@ -239,35 +239,12 @@ static int if_getaddrs(void)
                if (ifap->ifa_addr->sa_family == AF_INET6) {
                        struct sockaddr_in6 *addr;
                        struct sockaddr_in6 *mask;
-                       struct sockaddr_in6 *dest;
-                       struct in6_addr *dest_pnt;
                        int flags = 0;
 
                        addr = (struct sockaddr_in6 *)ifap->ifa_addr;
                        mask = (struct sockaddr_in6 *)ifap->ifa_netmask;
                        prefixlen = ip6_masklen(mask->sin6_addr);
 
-                       dest_pnt = NULL;
-
-                       if (ifap->ifa_dstaddr
-                           && !IPV6_ADDR_SAME(&addr->sin6_addr,
-                                              &((struct sockaddr_in6 *)
-                                                        ifap->ifa_dstaddr)
-                                                       ->sin6_addr)) {
-                               dest = (struct sockaddr_in6 *)ifap->ifa_dstaddr;
-                               dest_pnt = &dest->sin6_addr;
-                               flags = ZEBRA_IFA_PEER;
-                       } else if (ifap->ifa_broadaddr
-                                  && !IPV6_ADDR_SAME(
-                                             &addr->sin6_addr,
-                                             &((struct sockaddr_in6 *)
-                                                       ifap->ifa_broadaddr)
-                                                      ->sin6_addr)) {
-                               dest = (struct sockaddr_in6 *)
-                                              ifap->ifa_broadaddr;
-                               dest_pnt = &dest->sin6_addr;
-                       }
-
 #if defined(KAME)
                        if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
                                addr->sin6_scope_id =
@@ -279,7 +256,7 @@ static int if_getaddrs(void)
 #endif
 
                        connected_add_ipv6(ifp, flags, &addr->sin6_addr,
-                                          prefixlen, dest_pnt, NULL);
+                                          prefixlen, NULL);
                }
        }
 
index 3d53194593c640a432b9737cf58512f3de967b06..9ec575b5b01d7be6197250bb6c8a7c916f67a4e9 100644 (file)
@@ -317,8 +317,7 @@ static int if_get_addr(struct interface *ifp, struct sockaddr *addr,
                                   (struct in_addr *)dest_pnt, label);
        else if (af == AF_INET6)
                connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr,
-                                  prefixlen, (struct in6_addr *)dest_pnt,
-                                  label);
+                                  prefixlen, label);
 
        return 0;
 }
index 0d081551785b47c64474b6afacd33fabf4fa5ef8..5a42e0c8f1b0b45ed9d61d5bf2faabb02ca77b51 100644 (file)
@@ -393,7 +393,7 @@ static int get_iflink_speed(const char *ifname)
        memset(&ifdata, 0, sizeof(ifdata));
 
        /* set interface name */
-       strcpy(ifdata.ifr_name, ifname);
+       strlcpy(ifdata.ifr_name, ifname, sizeof(ifdata.ifr_name));
 
        /* initialize ethtool interface */
        memset(&ecmd, 0, sizeof(ecmd));
@@ -830,18 +830,24 @@ static int netlink_address(int cmd, int family, struct interface *ifp,
        req.ifa.ifa_family = family;
 
        req.ifa.ifa_index = ifp->ifindex;
-       req.ifa.ifa_prefixlen = p->prefixlen;
 
        addattr_l(&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
 
-       if (family == AF_INET && cmd == RTM_NEWADDR) {
-               if (!CONNECTED_PEER(ifc) && ifc->destination) {
+       if (family == AF_INET) {
+               if (CONNECTED_PEER(ifc)) {
+                       p = ifc->destination;
+                       addattr_l(&req.n, sizeof req, IFA_ADDRESS, &p->u.prefix,
+                                 bytelen);
+               } else if (cmd == RTM_NEWADDR && ifc->destination) {
                        p = ifc->destination;
                        addattr_l(&req.n, sizeof req, IFA_BROADCAST,
                                  &p->u.prefix, bytelen);
                }
        }
 
+       /* p is now either ifc->address or ifc->destination */
+       req.ifa.ifa_prefixlen = p->prefixlen;
+
        if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
                SET_FLAG(req.ifa.ifa_flags, IFA_F_SECONDARY);
 
@@ -993,14 +999,12 @@ int netlink_interface_addr(struct sockaddr_nl *snl, struct nlmsghdr *h,
                         */
                        if (!(ifa->ifa_flags
                              & (IFA_F_DADFAILED | IFA_F_TENTATIVE)))
-                               connected_add_ipv6(
-                                       ifp, flags, (struct in6_addr *)addr,
-                                       ifa->ifa_prefixlen,
-                                       (struct in6_addr *)broad, label);
+                               connected_add_ipv6(ifp, flags,
+                                                  (struct in6_addr *)addr,
+                                                  ifa->ifa_prefixlen, label);
                } else
                        connected_delete_ipv6(ifp, (struct in6_addr *)addr,
-                                             ifa->ifa_prefixlen,
-                                             (struct in6_addr *)broad);
+                                             ifa->ifa_prefixlen);
        }
 
        return 0;
index c17e408ea0e062903fb19ec91a3969228f57854d..5668590fdcf914c53dc898065357803e3b57fbed 100644 (file)
@@ -242,7 +242,7 @@ int if_subnet_add(struct interface *ifp, struct connected *ifc)
        /* Get address derived subnet node and associated address list, while
           marking
           address secondary attribute appropriately. */
-       cp = *ifc->address;
+       cp = *CONNECTED_PREFIX(ifc);
        apply_mask(&cp);
        rn = route_node_get(zebra_if->ipv4_subnets, &cp);
 
@@ -267,12 +267,16 @@ int if_subnet_delete(struct interface *ifp, struct connected *ifc)
        struct route_node *rn;
        struct zebra_if *zebra_if;
        struct list *addr_list;
+       struct prefix cp;
 
        assert(ifp && ifp->info && ifc);
        zebra_if = ifp->info;
 
+       cp = *CONNECTED_PREFIX(ifc);
+       apply_mask(&cp);
+
        /* Get address derived subnet node. */
-       rn = route_node_lookup(zebra_if->ipv4_subnets, ifc->address);
+       rn = route_node_lookup(zebra_if->ipv4_subnets, &cp);
        if (!(rn && rn->info)) {
                zlog_warn(
                        "Trying to remove an address from an unknown subnet."
@@ -493,7 +497,7 @@ void if_add_update(struct interface *ifp)
        if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
                SET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
 
-               if (if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) {
+               if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) {
                        if (IS_ZEBRA_DEBUG_KERNEL)
                                zlog_debug(
                                        "interface %s vrf %u index %d is shutdown. "
@@ -565,7 +569,7 @@ static void if_uninstall_connected(struct interface *ifp)
 static void if_delete_connected(struct interface *ifp)
 {
        struct connected *ifc;
-       struct prefix *p;
+       struct prefix cp;
        struct route_node *rn;
        struct zebra_if *zebra_if;
 
@@ -578,11 +582,13 @@ static void if_delete_connected(struct interface *ifp)
                while ((node = (last ? last->next
                                     : listhead(ifp->connected)))) {
                        ifc = listgetdata(node);
-                       p = ifc->address;
 
-                       if (p->family == AF_INET
+                       cp = *CONNECTED_PREFIX(ifc);
+                       apply_mask(&cp);
+
+                       if (cp.family == AF_INET
                            && (rn = route_node_lookup(zebra_if->ipv4_subnets,
-                                                      p))) {
+                                                      &cp))) {
                                struct listnode *anode;
                                struct listnode *next;
                                struct listnode *first;
@@ -635,7 +641,7 @@ static void if_delete_connected(struct interface *ifp)
                                list_delete(addr_list);
                                rn->info = NULL;
                                route_unlock_node(rn);
-                       } else if (p->family == AF_INET6) {
+                       } else if (cp.family == AF_INET6) {
                                connected_down_ipv6(ifp, ifc);
 
                                zebra_interface_address_delete_update(ifp, ifc);
@@ -873,7 +879,8 @@ void if_up(struct interface *ifp)
                link_if = ifp;
                zebra_vxlan_svi_up(ifp, link_if);
        } else if (IS_ZEBRA_IF_VLAN(ifp)) {
-               link_if = zif->link;
+               link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+                                                   zif->link_ifindex);
                if (link_if)
                        zebra_vxlan_svi_up(ifp, link_if);
        }
@@ -901,7 +908,8 @@ void if_down(struct interface *ifp)
                link_if = ifp;
                zebra_vxlan_svi_down(ifp, link_if);
        } else if (IS_ZEBRA_IF_VLAN(ifp)) {
-               link_if = zif->link;
+               link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+                                                   zif->link_ifindex);
                if (link_if)
                        zebra_vxlan_svi_down(ifp, link_if);
        }
@@ -966,6 +974,8 @@ static void connected_dump_vty(struct vty *vty, struct connected *connected)
                vty_out(vty,
                        (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
                prefix_vty_out(vty, connected->destination);
+               if (CONNECTED_PEER(connected))
+                       vty_out(vty, "/%d", connected->destination->prefixlen);
        }
 
        if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))
@@ -2365,38 +2375,56 @@ static int ip_address_install(struct vty *vty, struct interface *ifp,
                              const char *label)
 {
        struct zebra_if *if_data;
-       struct prefix_ipv4 cp;
+       struct prefix_ipv4 lp, pp;
        struct connected *ifc;
        struct prefix_ipv4 *p;
        int ret;
 
        if_data = ifp->info;
 
-       ret = str2prefix_ipv4(addr_str, &cp);
+       ret = str2prefix_ipv4(addr_str, &lp);
        if (ret <= 0) {
                vty_out(vty, "%% Malformed address \n");
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       if (ipv4_martian(&cp.prefix)) {
+       if (ipv4_martian(&lp.prefix)) {
                vty_out(vty, "%% Invalid address\n");
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       ifc = connected_check(ifp, (struct prefix *)&cp);
+       if (peer_str) {
+               if (lp.prefixlen != 32) {
+                       vty_out(vty,
+                               "%% Local prefix length for P-t-P address must be /32\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+
+               ret = str2prefix_ipv4(peer_str, &pp);
+               if (ret <= 0) {
+                       vty_out(vty, "%% Malformed peer address\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+       }
+
+       ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
        if (!ifc) {
                ifc = connected_new();
                ifc->ifp = ifp;
 
                /* Address. */
                p = prefix_ipv4_new();
-               *p = cp;
+               *p = lp;
                ifc->address = (struct prefix *)p;
 
-               /* Broadcast. */
-               if (p->prefixlen <= IPV4_MAX_PREFIXLEN - 2) {
+               if (peer_str) {
+                       SET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
+                       p = prefix_ipv4_new();
+                       *p = pp;
+                       ifc->destination = (struct prefix *)p;
+               } else if (p->prefixlen <= IPV4_MAX_PREFIXLEN - 2) {
                        p = prefix_ipv4_new();
-                       *p = cp;
+                       *p = lp;
                        p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,
                                                               p->prefixlen);
                        ifc->destination = (struct prefix *)p;
@@ -2445,19 +2473,33 @@ static int ip_address_uninstall(struct vty *vty, struct interface *ifp,
                                const char *addr_str, const char *peer_str,
                                const char *label)
 {
-       struct prefix_ipv4 cp;
+       struct prefix_ipv4 lp, pp;
        struct connected *ifc;
        int ret;
 
        /* Convert to prefix structure. */
-       ret = str2prefix_ipv4(addr_str, &cp);
+       ret = str2prefix_ipv4(addr_str, &lp);
        if (ret <= 0) {
                vty_out(vty, "%% Malformed address \n");
                return CMD_WARNING_CONFIG_FAILED;
        }
 
+       if (peer_str) {
+               if (lp.prefixlen != 32) {
+                       vty_out(vty,
+                               "%% Local prefix length for P-t-P address must be /32\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+
+               ret = str2prefix_ipv4(peer_str, &pp);
+               if (ret <= 0) {
+                       vty_out(vty, "%% Malformed peer address\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+       }
+
        /* Check current interface address. */
-       ifc = connected_check(ifp, (struct prefix *)&cp);
+       ifc = connected_check_ptp(ifp, &lp, peer_str ? &pp : NULL);
        if (!ifc) {
                vty_out(vty, "%% Can't find address\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -2517,6 +2559,32 @@ DEFUN (no_ip_address,
                                    NULL, NULL);
 }
 
+DEFUN(ip_address_peer,
+      ip_address_peer_cmd,
+      "ip address A.B.C.D peer A.B.C.D/M",
+      "Interface Internet Protocol config commands\n"
+      "Set the IP address of an interface\n"
+      "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
+      "Specify P-t-P address\n"
+      "Peer IP address (e.g. 10.0.0.1/8)\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       return ip_address_install(vty, ifp, argv[2]->arg, argv[4]->arg, NULL);
+}
+
+DEFUN(no_ip_address_peer,
+      no_ip_address_peer_cmd,
+      "no ip address A.B.C.D peer A.B.C.D/M",
+      NO_STR
+      "Interface Internet Protocol config commands\n"
+      "Set the IP address of an interface\n"
+      "Local IP (e.g. 10.0.0.1) for P-t-P address\n"
+      "Specify P-t-P address\n"
+      "Peer IP address (e.g. 10.0.0.1/8)\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       return ip_address_uninstall(vty, ifp, argv[3]->arg, argv[5]->arg, NULL);
+}
 
 #ifdef HAVE_NETLINK
 DEFUN (ip_address_label,
@@ -2791,7 +2859,7 @@ static int if_config_write(struct vty *vty)
                vrf = vrf_lookup_by_id(ifp->vrf_id);
 
                if (ifp->vrf_id == VRF_DEFAULT)
-                       vty_out(vty, "interface %s\n", ifp->name);
+                       vty_frame(vty, "interface %s\n", ifp->name);
                else
                        vty_out(vty, "interface %s vrf %s\n", ifp->name,
                                vrf->name);
@@ -2820,7 +2888,16 @@ static int if_config_write(struct vty *vty)
                                p = ifc->address;
                                vty_out(vty, " ip%s address %s",
                                        p->family == AF_INET ? "" : "v6",
-                                       prefix2str(p, buf, sizeof(buf)));
+                                       inet_ntop(p->family, &p->u.prefix, buf,
+                                                 sizeof(buf)));
+                               if (CONNECTED_PEER(ifc)) {
+                                       p = ifc->destination;
+                                       vty_out(vty, " peer %s",
+                                               inet_ntop(p->family,
+                                                         &p->u.prefix, buf,
+                                                         sizeof(buf)));
+                               }
+                               vty_out(vty, "/%d", p->prefixlen);
 
                                if (ifc->label)
                                        vty_out(vty, " label %s", ifc->label);
@@ -2842,7 +2919,7 @@ static int if_config_write(struct vty *vty)
 
                link_params_config_write(vty, ifp);
 
-               vty_out(vty, "!\n");
+               vty_endframe(vty, "!\n");
        }
        return 0;
 }
@@ -2876,6 +2953,8 @@ void zebra_if_init(void)
        install_element(INTERFACE_NODE, &no_bandwidth_if_cmd);
        install_element(INTERFACE_NODE, &ip_address_cmd);
        install_element(INTERFACE_NODE, &no_ip_address_cmd);
+       install_element(INTERFACE_NODE, &ip_address_peer_cmd);
+       install_element(INTERFACE_NODE, &no_ip_address_peer_cmd);
        install_element(INTERFACE_NODE, &ipv6_address_cmd);
        install_element(INTERFACE_NODE, &no_ipv6_address_cmd);
 #ifdef HAVE_NETLINK
index 7b56dcd4a40c7263f1b1ba1052963153df1fc4d3..6bc05e21c5d08c9da870416cada92a11c7f03273 100644 (file)
@@ -183,12 +183,12 @@ struct rtadvconf {
 
 /* Zebra interface type - ones of interest. */
 typedef enum {
-       ZEBRA_IF_VXLAN,   /* VxLAN interface */
-       ZEBRA_IF_VRF,     /* VRF device */
-       ZEBRA_IF_BRIDGE,  /* bridge device */
-       ZEBRA_IF_VLAN,    /* VLAN sub-interface */
-       ZEBRA_IF_MACVLAN, /* MAC VLAN interface*/
-       ZEBRA_IF_OTHER,   /* Anything else */
+       ZEBRA_IF_OTHER = 0, /* Anything else */
+       ZEBRA_IF_VXLAN,     /* VxLAN interface */
+       ZEBRA_IF_VRF,       /* VRF device */
+       ZEBRA_IF_BRIDGE,    /* bridge device */
+       ZEBRA_IF_VLAN,      /* VLAN sub-interface */
+       ZEBRA_IF_MACVLAN,   /* MAC VLAN interface*/
 } zebra_iftype_t;
 
 /* Zebra "slave" interface type */
index 835f1f4934c826edac851036b0889c9f6a1d7251..58118ce006f014c9306b82e16816450e0c6abf96 100644 (file)
@@ -44,7 +44,7 @@ extern struct zebra_privs_t zserv_privs;
 /* clear and set interface name string */
 void ifreq_set_name(struct ifreq *ifreq, struct interface *ifp)
 {
-       strncpy(ifreq->ifr_name, ifp->name, IFNAMSIZ);
+       strlcpy(ifreq->ifr_name, ifp->name, sizeof(ifreq->ifr_name));
 }
 
 /* call ioctl system call */
@@ -179,10 +179,15 @@ int if_set_prefix(struct interface *ifp, struct connected *ifc)
 {
        int ret;
        struct ifaliasreq addreq;
-       struct sockaddr_in addr;
-       struct sockaddr_in mask;
+       struct sockaddr_in addr, mask, peer;
        struct prefix_ipv4 *p;
 
+       /* don't configure PtP addresses on broadcast ifs or reverse */
+       if (!(ifp->flags & IFF_POINTOPOINT) != !CONNECTED_PEER(ifc)) {
+               errno = EINVAL;
+               return -1;
+       }
+
        p = (struct prefix_ipv4 *)ifc->address;
        rib_lookup_and_pushup(p, ifp->vrf_id);
 
@@ -197,6 +202,18 @@ int if_set_prefix(struct interface *ifp, struct connected *ifc)
 #endif
        memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
 
+       if (CONNECTED_PEER(ifc)) {
+               p = (struct prefix_ipv4 *)ifc->destination;
+               memset(&mask, 0, sizeof(struct sockaddr_in));
+               peer.sin_addr = p->prefix;
+               peer.sin_family = p->family;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+               peer.sin_len = sizeof(struct sockaddr_in);
+#endif
+               memcpy(&addreq.ifra_broadaddr, &peer,
+                      sizeof(struct sockaddr_in));
+       }
+
        memset(&mask, 0, sizeof(struct sockaddr_in));
        masklen2ip(p->prefixlen, &mask.sin_addr);
        mask.sin_family = p->family;
@@ -217,10 +234,15 @@ int if_unset_prefix(struct interface *ifp, struct connected *ifc)
 {
        int ret;
        struct ifaliasreq addreq;
-       struct sockaddr_in addr;
-       struct sockaddr_in mask;
+       struct sockaddr_in addr, mask, peer;
        struct prefix_ipv4 *p;
 
+       /* this would probably wreak havoc */
+       if (!(ifp->flags & IFF_POINTOPOINT) != !CONNECTED_PEER(ifc)) {
+               errno = EINVAL;
+               return -1;
+       }
+
        p = (struct prefix_ipv4 *)ifc->address;
 
        memset(&addreq, 0, sizeof addreq);
@@ -234,6 +256,18 @@ int if_unset_prefix(struct interface *ifp, struct connected *ifc)
 #endif
        memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
 
+       if (CONNECTED_PEER(ifc)) {
+               p = (struct prefix_ipv4 *)ifc->destination;
+               memset(&mask, 0, sizeof(struct sockaddr_in));
+               peer.sin_addr = p->prefix;
+               peer.sin_family = p->family;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+               peer.sin_len = sizeof(struct sockaddr_in);
+#endif
+               memcpy(&addreq.ifra_broadaddr, &peer,
+                      sizeof(struct sockaddr_in));
+       }
+
        memset(&mask, 0, sizeof(struct sockaddr_in));
        masklen2ip(p->prefixlen, &mask.sin_addr);
        mask.sin_family = p->family;
index 08322455368fde4b1e3104bceb48a898b5a88f97..11bc9b0440c30d80d21d0825a63be2e998fcc398 100644 (file)
@@ -182,6 +182,7 @@ static int irdp_recvmsg(int sock, u_char *buf, int size, int *ifindex)
        char adata[CMSG_SPACE(SOPT_SIZE_CMSG_PKTINFO_IPV4())];
        int ret;
 
+       memset(&msg, 0, sizeof(msg));
        msg.msg_name = (void *)0;
        msg.msg_namelen = 0;
        msg.msg_iov = &iov;
index e2a1deb9ac691e11d16fe08446250e2f0c6a1166..df8cdb3ab3213f162a5e691bbc01a3532bf5097b 100644 (file)
@@ -441,6 +441,12 @@ int ifm_read(struct if_msghdr *ifm)
        RTA_ADDR_GET(NULL, RTA_IFA, ifm->ifm_addrs, cp);
        RTA_ADDR_GET(NULL, RTA_AUTHOR, ifm->ifm_addrs, cp);
        RTA_ADDR_GET(NULL, RTA_BRD, ifm->ifm_addrs, cp);
+#ifdef RTA_LABEL
+       RTA_ATTR_GET(NULL, RTA_LABEL, ifm->ifm_addrs, cp);
+#endif
+#ifdef RTA_SRC
+       RTA_ADDR_GET(NULL, RTA_SRC, ifm->ifm_addrs, cp);
+#endif
 
        if (IS_ZEBRA_DEBUG_KERNEL)
                zlog_debug("%s: sdl ifname %s", __func__,
@@ -661,6 +667,12 @@ static void ifam_read_mesg(struct ifa_msghdr *ifm, union sockunion *addr,
        RTA_ADDR_GET(addr, RTA_IFA, ifm->ifam_addrs, pnt);
        RTA_ADDR_GET(NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt);
        RTA_ADDR_GET(brd, RTA_BRD, ifm->ifam_addrs, pnt);
+#ifdef RTA_LABEL
+       RTA_ATTR_GET(NULL, RTA_LABEL, ifm->ifam_addrs, pnt);
+#endif
+#ifdef RTA_SRC
+       RTA_ADDR_GET(NULL, RTA_SRC, ifm->ifam_addrs, pnt);
+#endif
 
        if (IS_ZEBRA_DEBUG_KERNEL) {
                int family = sockunion_family(addr);
@@ -762,12 +774,10 @@ int ifam_read(struct ifa_msghdr *ifam)
                if (ifam->ifam_type == RTM_NEWADDR)
                        connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr,
                                           ip6_masklen(mask.sin6.sin6_addr),
-                                          &brd.sin6.sin6_addr,
                                           (isalias ? ifname : NULL));
                else
                        connected_delete_ipv6(ifp, &addr.sin6.sin6_addr,
-                                             ip6_masklen(mask.sin6.sin6_addr),
-                                             &brd.sin6.sin6_addr);
+                                             ip6_masklen(mask.sin6.sin6_addr));
                break;
        default:
                /* Unsupported family silently ignore... */
@@ -829,6 +839,17 @@ static int rtm_read_mesg(struct rt_msghdr *rtm, union sockunion *dest,
        RTA_ADDR_GET(NULL, RTA_IFA, rtm->rtm_addrs, pnt);
        RTA_ADDR_GET(NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt);
        RTA_ADDR_GET(NULL, RTA_BRD, rtm->rtm_addrs, pnt);
+#ifdef RTA_LABEL
+#if 0
+       union sockunion label;
+       memset(&label, 0, sizeof(label));
+       RTA_ATTR_GET(&label, RTA_LABEL, rtm->rtm_addrs, pnt);
+#endif
+       RTA_ATTR_GET(NULL, RTA_LABEL, rtm->rtm_addrs, pnt);
+#endif
+#ifdef RTA_SRC
+       RTA_ADDR_GET(NULL, RTA_SRC, rtm->rtm_addrs, pnt);
+#endif
 
        /* If there is netmask information set it's family same as
           destination family*/
@@ -849,6 +870,7 @@ void rtm_read(struct rt_msghdr *rtm)
        union sockunion dest, mask, gate;
        char ifname[INTERFACE_NAMSIZ + 1];
        short ifnlen = 0;
+       struct nexthop nh;
 
        zebra_flags = 0;
 
@@ -886,11 +908,15 @@ void rtm_read(struct rt_msghdr *rtm)
        if (flags & RTF_STATIC)
                SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC);
 
+       memset(&nh, 0, sizeof(nh));
        /* This is a reject or blackhole route */
-       if (flags & RTF_REJECT)
-               SET_FLAG(zebra_flags, ZEBRA_FLAG_REJECT);
-       if (flags & RTF_BLACKHOLE)
-               SET_FLAG(zebra_flags, ZEBRA_FLAG_BLACKHOLE);
+       if (flags & RTF_REJECT) {
+               nh.type = NEXTHOP_TYPE_BLACKHOLE;
+               nh.bh_type = BLACKHOLE_REJECT;
+       } else if (flags & RTF_BLACKHOLE) {
+               nh.type = NEXTHOP_TYPE_BLACKHOLE;
+               nh.bh_type = BLACKHOLE_NULL;
+       }
 
        if (dest.sa.sa_family == AF_INET) {
                struct prefix p;
@@ -1016,18 +1042,22 @@ void rtm_read(struct rt_msghdr *rtm)
                if (rtm->rtm_type == RTM_CHANGE)
                        rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
                                   ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                                  NULL, 0, 0, 0);
+                                  NULL, 0, 0);
+
+               if (!nh.type) {
+                       nh.type = NEXTHOP_TYPE_IPV4;
+                       nh.gate.ipv4 = gate.sin.sin_addr;
+               }
 
-               union g_addr ggate = {.ipv4 = gate.sin.sin_addr};
                if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
                    || rtm->rtm_type == RTM_CHANGE)
                        rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
                                ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                               &ggate, NULL, 0, 0, 0, 0, 0);
+                               &nh, 0, 0, 0, 0);
                else
                        rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
                                   ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                                  &ggate, 0, 0, 0);
+                                  &nh, 0, 0);
        }
        if (dest.sa.sa_family == AF_INET6) {
                /* One day we might have a debug section here like one in the
@@ -1058,18 +1088,24 @@ void rtm_read(struct rt_msghdr *rtm)
                if (rtm->rtm_type == RTM_CHANGE)
                        rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
                                   ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                                  NULL, 0, 0, 0);
+                                  NULL, 0, 0);
+
+               if (!nh.type) {
+                       nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
+                                         : NEXTHOP_TYPE_IPV6;
+                       nh.gate.ipv6 = gate.sin6.sin6_addr;
+                       nh.ifindex = ifindex;
+               }
 
-               union g_addr ggate = {.ipv6 = gate.sin6.sin6_addr};
                if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
                    || rtm->rtm_type == RTM_CHANGE)
                        rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
                                ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                               &ggate, NULL, ifindex, 0, 0, 0, 0);
+                               &nh, 0, 0, 0, 0);
                else
                        rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
                                   ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
-                                  &ggate, ifindex, 0, 0);
+                                  &nh, 0, 0);
        }
 }
 
@@ -1079,7 +1115,7 @@ void rtm_read(struct rt_msghdr *rtm)
  */
 int rtm_write(int message, union sockunion *dest, union sockunion *mask,
              union sockunion *gate, union sockunion *mpls, unsigned int index,
-             int zebra_flags, int metric)
+             enum blackhole_type bh_type, int metric)
 {
        int ret;
        caddr_t pnt;
@@ -1169,11 +1205,16 @@ int rtm_write(int message, union sockunion *dest, union sockunion *mask,
        /* Tagging route with flags */
        msg.rtm.rtm_flags |= (RTF_PROTO1);
 
-       /* Additional flags. */
-       if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
-               msg.rtm.rtm_flags |= RTF_BLACKHOLE;
-       if (zebra_flags & ZEBRA_FLAG_REJECT)
+       switch (bh_type) {
+       case BLACKHOLE_UNSPEC:
+               break;
+       case BLACKHOLE_REJECT:
                msg.rtm.rtm_flags |= RTF_REJECT;
+               break;
+       default:
+               msg.rtm.rtm_flags |= RTF_BLACKHOLE;
+               break;
+       }
 
 
 #define SOCKADDRSET(X, R)                                                      \
index 41b322185f5d0fc11b0c9021a8305a73cb50a05a..096a21f78238cb8181fe6097f6ccab40639167f8 100644 (file)
@@ -34,8 +34,8 @@ extern void rtm_read(struct rt_msghdr *);
 extern int ifam_read(struct ifa_msghdr *);
 extern int ifm_read(struct if_msghdr *);
 extern int rtm_write(int, union sockunion *, union sockunion *,
-                    union sockunion *, union sockunion *, unsigned int, int,
-                    int);
+                    union sockunion *, union sockunion *, unsigned int,
+                    enum blackhole_type, int);
 extern const struct message rtm_type_str[];
 
 #endif /* __ZEBRA_KERNEL_SOCKET_H */
index 9b21eb4d8c1a9c0b81daa353240c6a589a474c39..4edc15aeb243060109d9e3de442b66bc858ab975 100644 (file)
@@ -52,6 +52,12 @@ static u_int32_t zebra_import_table_distance[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
 
 int is_zebra_import_table_enabled(afi_t afi, u_int32_t table_id)
 {
+       /*
+        * Make sure that what we are called with actualy makes sense
+        */
+       if (afi == AFI_MAX)
+               return 0;
+
        if (is_zebra_valid_kernel_table(table_id))
                return zebra_import_table_used[afi][table_id];
        return 0;
@@ -496,8 +502,6 @@ int zebra_add_import_table_entry(struct route_node *rn, struct route_entry *re,
        struct route_entry *newre;
        struct route_entry *same;
        struct prefix p;
-       struct nexthop *nhop;
-       union g_addr *gate;
        route_map_result_t ret = RMAP_MATCH;
 
        if (rmap_name)
@@ -529,18 +533,11 @@ int zebra_add_import_table_entry(struct route_node *rn, struct route_entry *re,
 
 
                        if (re->nexthop_num == 1) {
-                               nhop = re->nexthop;
-                               if (nhop->type == NEXTHOP_TYPE_IFINDEX)
-                                       gate = NULL;
-                               else
-                                       gate = (union g_addr *)&nhop->gate.ipv4;
-
                                rib_add(AFI_IP, SAFI_UNICAST, re->vrf_id,
                                        ZEBRA_ROUTE_TABLE, re->table, 0, &p,
-                                       NULL, gate,
-                                       (union g_addr *)&nhop->src.ipv4,
-                                       nhop->ifindex, zebrad.rtm_table_default,
-                                       re->metric, re->mtu,
+                                       NULL, re->nexthop,
+                                       zebrad.rtm_table_default, re->metric,
+                                       re->mtu,
                                        zebra_import_table_distance[AFI_IP]
                                                                   [re->table]);
                        } else if (re->nexthop_num > 1) {
@@ -580,7 +577,7 @@ int zebra_del_import_table_entry(struct route_node *rn, struct route_entry *re)
                p.u.prefix4 = rn->p.u.prefix4;
 
                rib_delete(AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE,
-                          re->table, re->flags, &p, NULL, NULL, 0,
+                          re->table, re->flags, &p, NULL, NULL,
                           zebrad.rtm_table_default, re->metric);
        }
        /* DD: Add IPv6 code */
index 495b731e885a973a28cafce6246e66e50da7ec91..9b1ce23b082e3ca4f19895cac08f47f7308df82b 100644 (file)
@@ -231,7 +231,8 @@ typedef enum {
 
 extern struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *,
                                                       ifindex_t);
-extern struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *);
+extern struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *,
+                                                        enum blackhole_type);
 extern struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *,
                                                    struct in_addr *,
                                                    struct in_addr *);
@@ -294,18 +295,17 @@ extern int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re);
  * also implicitly withdraw equal prefix of same type. */
 extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                   u_short instance, int flags, struct prefix *p,
-                  struct prefix_ipv6 *src_p, union g_addr *gate,
-                  union g_addr *src, ifindex_t ifindex, u_int32_t table_id,
-                  u_int32_t metric, u_int32_t mtu, u_char distance);
+                  struct prefix_ipv6 *src_p, const struct nexthop *nh,
+                  u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
+                  u_char distance);
 
 extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *,
                             struct prefix_ipv6 *src_p, struct route_entry *);
 
 extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                       u_short instance, int flags, struct prefix *p,
-                      struct prefix_ipv6 *src_p, union g_addr *gate,
-                      ifindex_t ifindex, u_int32_t table_id,
-                      u_int32_t metric);
+                      struct prefix_ipv6 *src_p, const struct nexthop *nh,
+                      u_int32_t table_id, u_int32_t metric);
 
 extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t,
                                     union g_addr *,
index e28fe5630aeeb53360bc073599f099e2259c498b..2f03982e42c2a84d0c44213fe6baed336e0dcd0d 100644 (file)
@@ -240,13 +240,27 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
        void *gate = NULL;
        void *prefsrc = NULL; /* IPv4 preferred source host address */
        void *src = NULL;     /* IPv6 srcdest   source prefix */
+       enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
 
        rtm = NLMSG_DATA(h);
 
        if (startup && h->nlmsg_type != RTM_NEWROUTE)
                return 0;
-       if (startup && rtm->rtm_type != RTN_UNICAST)
+       switch (rtm->rtm_type) {
+       case RTN_UNICAST:
+               break;
+       case RTN_BLACKHOLE:
+               bh_type = BLACKHOLE_NULL;
+               break;
+       case RTN_UNREACHABLE:
+               bh_type = BLACKHOLE_REJECT;
+               break;
+       case RTN_PROHIBIT:
+               bh_type = BLACKHOLE_ADMINPROHIB;
+               break;
+       default:
                return 0;
+       }
 
        len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
        if (len < 0)
@@ -365,11 +379,32 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
                afi = AFI_IP6;
 
        if (h->nlmsg_type == RTM_NEWROUTE) {
-               if (!tb[RTA_MULTIPATH])
+               if (!tb[RTA_MULTIPATH]) {
+                       struct nexthop nh;
+                       size_t sz = (afi == AFI_IP) ? 4 : 16;
+
+                       memset(&nh, 0, sizeof(nh));
+                       if (index && !gate)
+                               nh.type = NEXTHOP_TYPE_IFINDEX;
+                       else if (index && gate)
+                               nh.type = (afi == AFI_IP)
+                                                 ? NEXTHOP_TYPE_IPV4_IFINDEX
+                                                 : NEXTHOP_TYPE_IPV6_IFINDEX;
+                       else if (!index && gate)
+                               nh.type = (afi == AFI_IP) ? NEXTHOP_TYPE_IPV4
+                                                         : NEXTHOP_TYPE_IPV6;
+                       else {
+                               nh.type = NEXTHOP_TYPE_BLACKHOLE;
+                               nh.bh_type = bh_type;
+                       }
+                       nh.ifindex = index;
+                       if (prefsrc)
+                               memcpy(&nh.src, prefsrc, sz);
+                       if (gate)
+                               memcpy(&nh.gate, gate, sz);
                        rib_add(afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
-                               0, flags, &p, NULL, gate, prefsrc, index, table,
-                               metric, mtu, 0);
-               else {
+                               0, flags, &p, NULL, &nh, table, metric, mtu, 0);
+               } else {
                        /* This is a multipath route */
 
                        struct route_entry *re;
@@ -444,41 +479,34 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
                                                  NULL, re);
                }
        } else {
-               if (!tb[RTA_MULTIPATH])
+               if (!tb[RTA_MULTIPATH]) {
+                       struct nexthop nh;
+                       size_t sz = (afi == AFI_IP) ? 4 : 16;
+
+                       memset(&nh, 0, sizeof(nh));
+                       if (index && !gate)
+                               nh.type = NEXTHOP_TYPE_IFINDEX;
+                       else if (index && gate)
+                               nh.type = (afi == AFI_IP)
+                                                 ? NEXTHOP_TYPE_IPV4_IFINDEX
+                                                 : NEXTHOP_TYPE_IPV6_IFINDEX;
+                       else if (!index && gate)
+                               nh.type = (afi == AFI_IP) ? NEXTHOP_TYPE_IPV4
+                                                         : NEXTHOP_TYPE_IPV6;
+                       else
+                               nh.type = NEXTHOP_TYPE_BLACKHOLE;
+                       nh.ifindex = index;
+                       if (gate)
+                               memcpy(&nh.gate, gate, sz);
                        rib_delete(afi, SAFI_UNICAST, vrf_id,
-                                  ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, gate,
-                                  index, table, metric);
-               else {
-                       struct rtnexthop *rtnh =
-                               (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
-
-                       len = RTA_PAYLOAD(tb[RTA_MULTIPATH]);
-
-                       for (;;) {
-                               if (len < (int)sizeof(*rtnh)
-                                   || rtnh->rtnh_len > len)
-                                       break;
-
-                               gate = NULL;
-                               if (rtnh->rtnh_len > sizeof(*rtnh)) {
-                                       memset(tb, 0, sizeof(tb));
-                                       netlink_parse_rtattr(
-                                               tb, RTA_MAX, RTNH_DATA(rtnh),
-                                               rtnh->rtnh_len - sizeof(*rtnh));
-                                       if (tb[RTA_GATEWAY])
-                                               gate = RTA_DATA(
-                                                       tb[RTA_GATEWAY]);
-                               }
-
-                               if (gate)
-                                       rib_delete(afi, SAFI_UNICAST, vrf_id,
-                                                  ZEBRA_ROUTE_KERNEL, 0, flags,
-                                                  &p, NULL, gate, index,
-                                                  table, metric);
-
-                               len -= NLMSG_ALIGN(rtnh->rtnh_len);
-                               rtnh = RTNH_NEXT(rtnh);
-                       }
+                                  ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, &nh,
+                                  table, metric);
+               } else {
+                       /* XXX: need to compare the entire list of nexthops
+                        * here for NLM_F_APPEND stupidity */
+                       rib_delete(afi, SAFI_UNICAST, vrf_id,
+                                  ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, NULL,
+                                  table, metric);
                }
        }
 
@@ -558,8 +586,8 @@ static int netlink_route_change_read_multicast(struct sockaddr_nl *snl,
 
        if (IS_ZEBRA_DEBUG_KERNEL) {
                struct interface *ifp;
-               strcpy(sbuf, inet_ntoa(m->sg.src));
-               strcpy(gbuf, inet_ntoa(m->sg.grp));
+               strlcpy(sbuf, inet_ntoa(m->sg.src), sizeof(sbuf));
+               strlcpy(gbuf, inet_ntoa(m->sg.grp), sizeof(gbuf));
                for (count = 0; count < oif_count; count++) {
                        ifp = if_lookup_by_index(oif[count], vrf);
                        char temp[256];
@@ -609,18 +637,10 @@ int netlink_route_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
        if (len < 0)
                return -1;
 
-       switch (rtm->rtm_type) {
-       case RTN_UNICAST:
-               netlink_route_change_read_unicast(snl, h, ns_id, startup);
-               break;
-       case RTN_MULTICAST:
+       if (rtm->rtm_type == RTN_MULTICAST)
                netlink_route_change_read_multicast(snl, h, ns_id, startup);
-               break;
-       default:
-               return 0;
-               break;
-       }
-
+       else
+               netlink_route_change_read_unicast(snl, h, ns_id, startup);
        return 0;
 }
 
@@ -1207,7 +1227,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
        struct sockaddr_nl snl;
        struct nexthop *nexthop = NULL;
        unsigned int nexthop_num;
-       int discard;
+       int discard = 0;
        int family = PREFIX_FAMILY(p);
        const char *routedesc;
        int setsrc = 0;
@@ -1238,24 +1258,23 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
        req.r.rtm_src_len = src_p ? src_p->prefixlen : 0;
        req.r.rtm_protocol = get_rt_proto(re->type);
        req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+       req.r.rtm_type = RTN_UNICAST;
 
-       if ((re->flags & ZEBRA_FLAG_BLACKHOLE)
-           || (re->flags & ZEBRA_FLAG_REJECT))
+       if (re->nexthop_num == 1
+           && re->nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
                discard = 1;
-       else
-               discard = 0;
-
-       if (cmd == RTM_NEWROUTE) {
-               if (discard) {
-                       if (re->flags & ZEBRA_FLAG_BLACKHOLE)
-                               req.r.rtm_type = RTN_BLACKHOLE;
-                       else if (re->flags & ZEBRA_FLAG_REJECT)
-                               req.r.rtm_type = RTN_UNREACHABLE;
-                       else
-                               assert(RTN_BLACKHOLE
-                                      != RTN_UNREACHABLE); /* false */
-               } else
-                       req.r.rtm_type = RTN_UNICAST;
+
+               switch (re->nexthop->bh_type) {
+               case BLACKHOLE_ADMINPROHIB:
+                       req.r.rtm_type = RTN_PROHIBIT;
+                       break;
+               case BLACKHOLE_REJECT:
+                       req.r.rtm_type = RTN_UNREACHABLE;
+                       break;
+               default:
+                       req.r.rtm_type = RTN_BLACKHOLE;
+                       break;
+               }
        }
 
        addattr_l(&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
@@ -1280,6 +1299,9 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
                addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
        }
 
+       if (discard)
+               goto skip;
+
        if (re->mtu || re->nexthop_mtu) {
                char buf[NL_PKT_BUF_SIZE];
                struct rtattr *rta = (void *)buf;
@@ -1293,21 +1315,6 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
                          RTA_PAYLOAD(rta));
        }
 
-       if (discard) {
-               if (cmd == RTM_NEWROUTE)
-                       for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
-                               /* We shouldn't encounter recursive nexthops on
-                                * discard routes,
-                                * but it is probably better to handle that case
-                                * correctly anyway.
-                                */
-                               if (CHECK_FLAG(nexthop->flags,
-                                              NEXTHOP_FLAG_RECURSIVE))
-                                       continue;
-                       }
-               goto skip;
-       }
-
        /* Count overall nexthops so we can decide whether to use singlepath
         * or multipath case. */
        nexthop_num = 0;
@@ -1553,6 +1560,8 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
 int kernel_route_rib(struct prefix *p, struct prefix *src_p,
                     struct route_entry *old, struct route_entry *new)
 {
+       assert(old || new);
+
        if (!old && new)
                return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0);
        if (old && !new)
@@ -2005,7 +2014,8 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
         * itself
         */
        if (IS_ZEBRA_IF_VLAN(ifp)) {
-               link_if = zif->link;
+               link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+                                                   zif->link_ifindex);
                if (!link_if)
                        return 0;
        } else if (IS_ZEBRA_IF_BRIDGE(ifp))
index 32ae41b917cd77496efd9a4e7cc63561bba311b5..d8e37a10c310ef2b19300b9bc9b15ee8eb5c9a40 100644 (file)
 
 extern struct zebra_privs_t zserv_privs;
 
-/* kernel socket export */
-extern int rtm_write(int message, union sockunion *dest, union sockunion *mask,
-                    union sockunion *gate, union sockunion *mpls,
-                    unsigned int index, int zebra_flags, int metric);
-
 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
 /* Adjust netmask socket length. Return value is a adjusted sin_len
    value. */
@@ -108,6 +103,7 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
        int gate = 0;
        int error;
        char prefix_buf[PREFIX_STRLEN];
+       enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
 
        if (IS_ZEBRA_DEBUG_RIB)
                prefix2str(p, prefix_buf, sizeof(prefix_buf));
@@ -155,6 +151,7 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
                                struct in_addr loopback;
                                loopback.s_addr = htonl(INADDR_LOOPBACK);
                                sin_gate.sin_addr = loopback;
+                               bh_type = nexthop->bh_type;
                                gate = 1;
                        }
 
@@ -178,11 +175,11 @@ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re)
                        smplsp = (union sockunion *)&smpls;
 #endif
 
-                       error = rtm_write(
-                               cmd, (union sockunion *)&sin_dest,
-                               (union sockunion *)mask,
-                               gate ? (union sockunion *)&sin_gate : NULL,
-                               smplsp, ifindex, re->flags, re->metric);
+                       error = rtm_write(cmd, (union sockunion *)&sin_dest,
+                                         (union sockunion *)mask,
+                                         gate ? (union sockunion *)&sin_gate
+                                              : NULL,
+                                         smplsp, ifindex, bh_type, re->metric);
 
                        if (IS_ZEBRA_DEBUG_RIB) {
                                if (!gate) {
@@ -292,6 +289,7 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
        ifindex_t ifindex = 0;
        int gate = 0;
        int error;
+       enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
 
        memset(&sin_dest, 0, sizeof(struct sockaddr_in6));
        sin_dest.sin6_family = AF_INET6;
@@ -331,6 +329,9 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
                            || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
                                ifindex = nexthop->ifindex;
 
+                       if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
+                               bh_type = nexthop->bh_type;
+
                        if (cmd == RTM_ADD)
                                SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
                }
@@ -369,7 +370,7 @@ static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re)
                error = rtm_write(cmd, (union sockunion *)&sin_dest,
                                  (union sockunion *)mask,
                                  gate ? (union sockunion *)&sin_gate : NULL,
-                                 smplsp, ifindex, re->flags, re->metric);
+                                 smplsp, ifindex, bh_type, re->metric);
 
 #if 0
       if (error)
index 2182d6618ce4a33fa4a24c0b19a387424119cd1d..88836af72e4480abfc166222c48fcca421628e6f 100644 (file)
@@ -107,6 +107,7 @@ static int rtadv_recv_packet(struct zebra_ns *zns, int sock, u_char *buf,
        char adata[1024];
 
        /* Fill in message and iovec. */
+       memset(&msg, 0, sizeof(msg));
        msg.msg_name = (void *)from;
        msg.msg_namelen = sizeof(struct sockaddr_in6);
        msg.msg_iov = &iov;
@@ -629,7 +630,6 @@ static int rtadv_make_socket(void)
                         safe_strerror(errno));
 
        if (sock < 0) {
-               close(sock);
                return -1;
        }
 
index 1bba003a0a084820637d5b813cbc73706d0362a7..62f3224b6e874db7c120b91dbb352dcb9b6a0b99 100644 (file)
@@ -75,8 +75,8 @@
 static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry)
 {
        struct prefix prefix;
-       struct in_addr tmpaddr, gateway;
-       union g_addr *ggateway;
+       struct in_addr tmpaddr;
+       struct nexthop nh;
        u_char zebra_flags = 0;
 
        if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE)
@@ -93,11 +93,12 @@ static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry)
        tmpaddr.s_addr = routeEntry->ipRouteMask;
        prefix.prefixlen = ip_masklen(tmpaddr);
 
-       gateway.s_addr = routeEntry->ipRouteNextHop;
-       ggateway = (union g_addr *)&gateway;
+       memset(&nh, 0, sizeof(nh));
+       nh.type = NEXTHOP_TYPE_IPV4;
+       nh.gate.ipv4.s_addr = routeEntry->ipRouteNextHop;
 
        rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
-               zebra_flags, &prefix, NULL, ggateway, NULL, 0, 0, 0, 0, 0);
+               zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0);
 }
 
 void route_read(struct zebra_ns *zns)
index 28f795663939aa4250cba15bb3174be33c294266..27c789137263b48533a4d92068d510dbab50d947 100644 (file)
@@ -222,7 +222,6 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
                                   rib_dest_t *dest, struct route_entry *re)
 {
        struct nexthop *nexthop;
-       int discard;
 
        memset(ri, 0, sizeof(*ri));
 
@@ -247,30 +246,9 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
        }
 
        ri->rtm_protocol = netlink_proto_from_route_type(re->type);
-
-       if ((re->flags & ZEBRA_FLAG_BLACKHOLE)
-           || (re->flags & ZEBRA_FLAG_REJECT))
-               discard = 1;
-       else
-               discard = 0;
-
-       if (cmd == RTM_NEWROUTE) {
-               if (discard) {
-                       if (re->flags & ZEBRA_FLAG_BLACKHOLE)
-                               ri->rtm_type = RTN_BLACKHOLE;
-                       else if (re->flags & ZEBRA_FLAG_REJECT)
-                               ri->rtm_type = RTN_UNREACHABLE;
-                       else
-                               assert(0);
-               } else
-                       ri->rtm_type = RTN_UNICAST;
-       }
-
+       ri->rtm_type = RTN_UNICAST;
        ri->metric = &re->metric;
 
-       if (discard)
-               return 1;
-
        for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
                if (ri->num_nhs >= multipath_num)
                        break;
@@ -278,6 +256,22 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
                if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
                        continue;
 
+               if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
+                       switch (nexthop->bh_type) {
+                       case BLACKHOLE_ADMINPROHIB:
+                               ri->rtm_type = RTN_PROHIBIT;
+                               break;
+                       case BLACKHOLE_REJECT:
+                               ri->rtm_type = RTN_UNREACHABLE;
+                               break;
+                       case BLACKHOLE_NULL:
+                       default:
+                               ri->rtm_type = RTN_BLACKHOLE;
+                               break;
+                       }
+                       return 1;
+               }
+
                if ((cmd == RTM_NEWROUTE
                     && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
                    || (cmd == RTM_DELROUTE
index 450ad5b0bffc7bc70ac4e2c2dd1ab84bd0ee848d..b850f1fb1e12f3ad3c862a9199c3c2b700273c93 100644 (file)
@@ -141,7 +141,6 @@ static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator,
                                               struct route_entry *re)
 {
        Fpm__AddRoute *msg;
-       int discard;
        struct nexthop *nexthop;
        uint num_nhs, u;
        struct nexthop *nexthops[MULTIPATH_NUM];
@@ -164,26 +163,7 @@ static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator,
        msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST;
        msg->key = fpm_route_key_create(allocator, rib_dest_prefix(dest));
        qpb_protocol_set(&msg->protocol, re->type);
-
-       if ((re->flags & ZEBRA_FLAG_BLACKHOLE)
-           || (re->flags & ZEBRA_FLAG_REJECT))
-               discard = 1;
-       else
-               discard = 0;
-
-       if (discard) {
-               if (re->flags & ZEBRA_FLAG_BLACKHOLE) {
-                       msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE;
-               } else if (re->flags & ZEBRA_FLAG_REJECT) {
-                       msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE;
-               } else {
-                       assert(0);
-               }
-               return msg;
-       } else {
-               msg->route_type = FPM__ROUTE_TYPE__NORMAL;
-       }
-
+       msg->route_type = FPM__ROUTE_TYPE__NORMAL;
        msg->metric = re->metric;
 
        /*
@@ -197,6 +177,19 @@ static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator,
                if (num_nhs >= ZEBRA_NUM_OF(nexthops))
                        break;
 
+               if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
+                       switch (nexthop->bh_type) {
+                       case BLACKHOLE_REJECT:
+                               msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE;
+                               break;
+                       case BLACKHOLE_NULL:
+                       default:
+                               msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE;
+                               break;
+                       }
+                       return msg;
+               }
+
                if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
                        continue;
 
index 5d059a4502e691596232a77f9fe14c0464860e8a..3d505857c271dc0a1c8165afaa2261c5ed41ff89 100644 (file)
@@ -224,12 +224,19 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp,
        zif->brslave_info.bridge_ifindex = bridge_ifindex;
 
        /* Set up or remove link with master */
-       if (bridge_ifindex != IFINDEX_INTERNAL)
+       if (bridge_ifindex != IFINDEX_INTERNAL) {
                zebra_l2_map_slave_to_bridge(&zif->brslave_info);
-       else if (old_bridge_ifindex != IFINDEX_INTERNAL)
+               /* In the case of VxLAN, invoke the handler for EVPN. */
+               if (zif->zif_type == ZEBRA_IF_VXLAN)
+                       zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE);
+       } else if (old_bridge_ifindex != IFINDEX_INTERNAL) {
+               /*
+                * In the case of VxLAN, invoke the handler for EVPN.
+                * Note that this should be done *prior*
+                * to unmapping the interface from the bridge.
+                */
+               if (zif->zif_type == ZEBRA_IF_VXLAN)
+                       zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE);
                zebra_l2_unmap_slave_from_bridge(&zif->brslave_info);
-
-       /* In the case of VxLAN, invoke the handler for EVPN. */
-       if (zif->zif_type == ZEBRA_IF_VXLAN)
-               zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE);
+       }
 }
index cee3a03858b1d6e8f34c7e73f9a05866f558308e..3c4de40db3d4b756c2020ff5889bd8ee0c30ff4d 100644 (file)
@@ -840,7 +840,7 @@ static void lsp_schedule(struct hash_backet *backet, void *ctxt)
        zebra_lsp_t *lsp;
 
        lsp = (zebra_lsp_t *)backet->data;
-       lsp_processq_add(lsp);
+       (void)lsp_processq_add(lsp);
 }
 
 /*
@@ -2718,10 +2718,10 @@ int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf)
        for (ALL_LIST_ELEMENTS_RO(slsp_list, node, slsp)) {
                for (snhlfe = slsp->snhlfe_list; snhlfe;
                     snhlfe = snhlfe->next) {
-                       char buf[INET6_ADDRSTRLEN];
+                       char buf[BUFSIZ];
                        char lstr[30];
 
-                       snhlfe2str(snhlfe, buf, BUFSIZ);
+                       snhlfe2str(snhlfe, buf, sizeof(buf));
                        switch (snhlfe->out_label) {
                        case MPLS_V4_EXP_NULL_LABEL:
                        case MPLS_V6_EXP_NULL_LABEL:
index c4d674df23b43c9078d3baca6d5f92795135ae9a..75d5d5d6276c0167a06e9ad2a473751237301215 100644 (file)
@@ -48,8 +48,8 @@ int zebra_ipmr_route_stats(struct zserv *client, int fd, u_short length,
                char sbuf[40];
                char gbuf[40];
 
-               strcpy(sbuf, inet_ntoa(mroute.sg.src));
-               strcpy(gbuf, inet_ntoa(mroute.sg.grp));
+               strlcpy(sbuf, inet_ntoa(mroute.sg.src), sizeof(sbuf));
+               strlcpy(gbuf, inet_ntoa(mroute.sg.grp), sizeof(gbuf));
 
                zlog_debug("Asking for (%s,%s) mroute information", sbuf, gbuf);
        }
index 1bf672d4a1cb3bc3d25c66273c41b80edf0af4d8..b18b3e74293e2fc455985b615f4f2116fcab4f4e 100644 (file)
@@ -156,7 +156,7 @@ void zebra_ptm_finish(void)
        if (ptm_cb.wb)
                buffer_free(ptm_cb.wb);
 
-       if (ptm_cb.ptm_sock != -1)
+       if (ptm_cb.ptm_sock >= 0)
                close(ptm_cb.ptm_sock);
 }
 
index 0b6263fac5241b2ce4b82f3d16fd493f060568d2..ce9f19c3cc22f26b471a9eacdb28c64bbbbb9c2d 100644 (file)
@@ -328,6 +328,7 @@ DEFUN_NOSH (pseudowire_if,
                if (!pw)
                        return CMD_SUCCESS;
                zebra_pw_del(zvrf, pw);
+               return CMD_SUCCESS;
        }
 
        if (!pw)
index dc61ea5e40c14a3211c89af7b8ba7393071af4e0..bcf21783ae490e35754f19b5432105c0fceef524 100644 (file)
@@ -291,13 +291,14 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
        return nexthop;
 }
 
-struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re)
+struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re,
+                                                 enum blackhole_type bh_type)
 {
        struct nexthop *nexthop;
 
        nexthop = nexthop_new();
        nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
-       SET_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE);
+       nexthop->bh_type = bh_type;
 
        route_entry_nexthop_add(re, nexthop);
 
@@ -471,12 +472,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
                        continue;
                }
 
-               /* If the longest prefix match for the nexthop yields
-                * a blackhole, mark it as inactive. */
-               if (CHECK_FLAG(match->flags, ZEBRA_FLAG_BLACKHOLE)
-                   || CHECK_FLAG(match->flags, ZEBRA_FLAG_REJECT))
-                       return 0;
-
                if (match->type == ZEBRA_ROUTE_CONNECT) {
                        /* Directly point connected route. */
                        newhop = match->nexthop;
@@ -488,41 +483,46 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
                        return 1;
                } else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_INTERNAL)) {
                        resolved = 0;
-                       for (ALL_NEXTHOPS(match->nexthop, newhop))
-                               if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_FIB)
-                                   && !CHECK_FLAG(newhop->flags,
-                                                  NEXTHOP_FLAG_RECURSIVE)) {
-                                       if (set) {
-                                               SET_FLAG(
-                                                       nexthop->flags,
-                                                       NEXTHOP_FLAG_RECURSIVE);
-                                               SET_FLAG(
-                                                       re->status,
-                                                       ROUTE_ENTRY_NEXTHOPS_CHANGED);
-
-                                               nexthop_set_resolved(
-                                                       afi, newhop, nexthop);
-                                       }
-                                       resolved = 1;
+                       for (ALL_NEXTHOPS(match->nexthop, newhop)) {
+                               if (newhop->type == NEXTHOP_TYPE_BLACKHOLE)
+                                       continue;
+                               if (!CHECK_FLAG(newhop->flags,
+                                               NEXTHOP_FLAG_FIB))
+                                       continue;
+                               if (CHECK_FLAG(newhop->flags,
+                                              NEXTHOP_FLAG_RECURSIVE))
+                                       continue;
+
+                               if (set) {
+                                       SET_FLAG(nexthop->flags,
+                                                NEXTHOP_FLAG_RECURSIVE);
+                                       SET_FLAG(re->status,
+                                                ROUTE_ENTRY_NEXTHOPS_CHANGED);
+                                       nexthop_set_resolved(afi, newhop,
+                                                            nexthop);
                                }
+                               resolved = 1;
+                       }
                        if (resolved && set)
                                re->nexthop_mtu = match->mtu;
                        return resolved;
                } else if (re->type == ZEBRA_ROUTE_STATIC) {
                        resolved = 0;
-                       for (ALL_NEXTHOPS(match->nexthop, newhop))
-                               if (CHECK_FLAG(newhop->flags,
-                                              NEXTHOP_FLAG_FIB)) {
-                                       if (set) {
-                                               SET_FLAG(
-                                                       nexthop->flags,
-                                                       NEXTHOP_FLAG_RECURSIVE);
+                       for (ALL_NEXTHOPS(match->nexthop, newhop)) {
+                               if (newhop->type == NEXTHOP_TYPE_BLACKHOLE)
+                                       continue;
+                               if (!CHECK_FLAG(newhop->flags,
+                                               NEXTHOP_FLAG_FIB))
+                                       continue;
 
-                                               nexthop_set_resolved(
-                                                       afi, newhop, nexthop);
-                                       }
-                                       resolved = 1;
+                               if (set) {
+                                       SET_FLAG(nexthop->flags,
+                                                NEXTHOP_FLAG_RECURSIVE);
+                                       nexthop_set_resolved(afi, newhop,
+                                                            nexthop);
                                }
+                               resolved = 1;
+                       }
                        if (resolved && set)
                                re->nexthop_mtu = match->mtu;
                        return resolved;
@@ -2273,16 +2273,15 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
 
 void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                u_short instance, int flags, struct prefix *p,
-               struct prefix_ipv6 *src_p, union g_addr *gate,
-               ifindex_t ifindex, u_int32_t table_id,
-               u_int32_t metric)
+               struct prefix_ipv6 *src_p, const struct nexthop *nh,
+               u_int32_t table_id, u_int32_t metric)
 {
        struct route_table *table;
        struct route_node *rn;
        struct route_entry *re;
        struct route_entry *fib = NULL;
        struct route_entry *same = NULL;
-       struct nexthop *nexthop;
+       struct nexthop *rtnh;
        char buf2[INET6_ADDRSTRLEN];
 
        assert(!src_p || afi == AFI_IP6);
@@ -2332,9 +2331,9 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                if (re->type == ZEBRA_ROUTE_KERNEL &&
                    re->metric != metric)
                        continue;
-               if (re->type == ZEBRA_ROUTE_CONNECT && (nexthop = re->nexthop)
-                   && nexthop->type == NEXTHOP_TYPE_IFINDEX) {
-                       if (nexthop->ifindex != ifindex)
+               if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = re->nexthop)
+                   && rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
+                       if (rtnh->ifindex != nh->ifindex)
                                continue;
                        if (re->refcnt) {
                                re->refcnt--;
@@ -2347,14 +2346,12 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                }
                /* Make sure that the route found has the same gateway. */
                else {
-                       if (gate == NULL) {
+                       if (nh == NULL) {
                                same = re;
                                break;
                        }
-                       for (ALL_NEXTHOPS(re->nexthop, nexthop))
-                               if (IPV4_ADDR_SAME(&nexthop->gate.ipv4, &gate->ipv4)
-                                   || IPV6_ADDR_SAME(&nexthop->gate.ipv6,
-                                                     gate)) {
+                       for (ALL_NEXTHOPS(re->nexthop, rtnh))
+                               if (nexthop_same_no_recurse(rtnh, nh)) {
                                        same = re;
                                        break;
                                }
@@ -2375,9 +2372,9 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                        }
                        if (allow_delete) {
                                /* Unset flags. */
-                               for (nexthop = fib->nexthop; nexthop;
-                                    nexthop = nexthop->next)
-                                       UNSET_FLAG(nexthop->flags,
+                               for (rtnh = fib->nexthop; rtnh;
+                                    rtnh = rtnh->next)
+                                       UNSET_FLAG(rtnh->flags,
                                                   NEXTHOP_FLAG_FIB);
 
                                UNSET_FLAG(fib->status,
@@ -2391,22 +2388,22 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                        }
                } else {
                        if (IS_ZEBRA_DEBUG_RIB) {
-                               if (gate)
+                               if (nh)
                                        rnode_debug(
                                                rn, vrf_id,
                                                "via %s ifindex %d type %d "
                                                "doesn't exist in rib",
                                                inet_ntop(
-                                                       family2afi(afi), gate,
-                                                       buf2,
+                                                       family2afi(afi),
+                                                       &nh->gate, buf2,
                                                        INET_ADDRSTRLEN), /* FIXME
                                                                             */
-                                               ifindex, type);
+                                               nh->ifindex, type);
                                else
                                        rnode_debug(
                                                rn, vrf_id,
-                                               "ifindex %d type %d doesn't exist in rib",
-                                               ifindex, type);
+                                               "type %d doesn't exist in rib",
+                                               type);
                        }
                        route_unlock_node(rn);
                        return;
@@ -2423,15 +2420,14 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
 
 int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
            int flags, struct prefix *p, struct prefix_ipv6 *src_p,
-           union g_addr *gate, union g_addr *src, ifindex_t ifindex,
-           u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
-           u_char distance)
+           const struct nexthop *nh, u_int32_t table_id, u_int32_t metric,
+           u_int32_t mtu, u_char distance)
 {
        struct route_entry *re;
        struct route_entry *same = NULL;
        struct route_table *table;
        struct route_node *rn;
-       struct nexthop *nexthop;
+       struct nexthop *rtnh;
 
        assert(!src_p || afi == AFI_IP6);
 
@@ -2480,9 +2476,9 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
                        break;
                }
                /* Duplicate system route comes in. */
-               else if ((nexthop = re->nexthop)
-                        && nexthop->type == NEXTHOP_TYPE_IFINDEX
-                        && nexthop->ifindex == ifindex
+               else if ((rtnh = re->nexthop)
+                        && rtnh->type == NEXTHOP_TYPE_IFINDEX
+                        && rtnh->ifindex == nh->ifindex
                         && !CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
                        re->refcnt++;
                        return 0;
@@ -2503,29 +2499,14 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
        re->nexthop_num = 0;
        re->uptime = time(NULL);
 
-       /* Nexthop settings. */
-       if (gate) {
-               if (afi == AFI_IP6) {
-                       if (ifindex)
-                               route_entry_nexthop_ipv6_ifindex_add(
-                                       re, &gate->ipv6, ifindex);
-                       else
-                               route_entry_nexthop_ipv6_add(re, &gate->ipv6);
-               } else {
-                       if (ifindex)
-                               route_entry_nexthop_ipv4_ifindex_add(
-                                       re, &gate->ipv4, &src->ipv4, ifindex);
-                       else
-                               route_entry_nexthop_ipv4_add(re, &gate->ipv4,
-                                                            &src->ipv4);
-               }
-       } else
-               route_entry_nexthop_ifindex_add(re, ifindex);
+       rtnh = nexthop_new();
+       *rtnh = *nh;
+       route_entry_nexthop_add(re, rtnh);
 
        /* If this route is kernel route, set FIB flag to the route. */
        if (RIB_SYSTEM_ROUTE(re))
-               for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next)
-                       SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+               for (rtnh = re->nexthop; rtnh; rtnh = rtnh->next)
+                       SET_FLAG(rtnh->flags, NEXTHOP_FLAG_FIB);
 
        /* Link new rib to node.*/
        if (IS_ZEBRA_DEBUG_RIB) {
@@ -2745,23 +2726,27 @@ unsigned long rib_score_proto(u_char proto, u_short instance)
 void rib_close_table(struct route_table *table)
 {
        struct route_node *rn;
-       rib_table_info_t *info = table->info;
+       rib_table_info_t *info;
        struct route_entry *re;
 
-       if (table)
-               for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
-                       RNODE_FOREACH_RE(rn, re)
-                       {
-                               if (!CHECK_FLAG(re->status,
-                                               ROUTE_ENTRY_SELECTED_FIB))
-                                       continue;
+       if (!table)
+               return;
 
-                               if (info->safi == SAFI_UNICAST)
-                                       hook_call(rib_update, rn, NULL);
+       info = table->info;
 
-                               if (!RIB_SYSTEM_ROUTE(re))
-                                       rib_uninstall_kernel(rn, re);
-                       }
+       for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
+               RNODE_FOREACH_RE(rn, re)
+               {
+                       if (!CHECK_FLAG(re->status,
+                                       ROUTE_ENTRY_SELECTED_FIB))
+                               continue;
+
+                       if (info->safi == SAFI_UNICAST)
+                               hook_call(rib_update, rn, NULL);
+
+                       if (!RIB_SYSTEM_ROUTE(re))
+                               rib_uninstall_kernel(rn, re);
+               }
 }
 
 /* Routing information base initialize. */
index c738cde0ac540f5b292fbd7b6c2f9b5451818136..0fa616bef9b2ec75193b6b8e1cd9fa0703fb6280 100644 (file)
@@ -62,23 +62,26 @@ static int zebra_route_match_add(struct vty *vty, const char *command,
 {
        VTY_DECLVAR_CONTEXT(route_map_index, index);
        int ret;
+       int retval = CMD_SUCCESS;
 
        ret = route_map_add_match(index, command, arg);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% Zebra Can't find rule.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty, "%% Zebra Argument is malformed.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% Zebra Can't find rule.\n");
+               retval = CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty, "%% Zebra Argument is malformed.\n");
+               retval = CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               if (type != RMAP_EVENT_MATCH_ADDED) {
+                       route_map_upd8_dependency(type, arg, index->map->name);
                }
+               break;
        }
 
-       if (type != RMAP_EVENT_MATCH_ADDED) {
-               route_map_upd8_dependency(type, arg, index->map->name);
-       }
-       return CMD_SUCCESS;
+       return retval;
 }
 
 /* Delete zebra route map rule. */
@@ -87,6 +90,7 @@ static int zebra_route_match_delete(struct vty *vty, const char *command,
 {
        VTY_DECLVAR_CONTEXT(route_map_index, index);
        int ret;
+       int retval = CMD_SUCCESS;
        char *dep_name = NULL;
        const char *tmpstr;
        char *rmap_name = NULL;
@@ -105,26 +109,27 @@ static int zebra_route_match_delete(struct vty *vty, const char *command,
        }
 
        ret = route_map_delete_match(index, command, arg);
-       if (ret) {
-               switch (ret) {
-               case RMAP_RULE_MISSING:
-                       vty_out(vty, "%% Zebra Can't find rule.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               case RMAP_COMPILE_ERROR:
-                       vty_out(vty, "%% Zebra Argument is malformed.\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
+       switch (ret) {
+       case RMAP_RULE_MISSING:
+               vty_out(vty, "%% Zebra Can't find rule.\n");
+               retval = CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_ERROR:
+               vty_out(vty, "%% Zebra Argument is malformed.\n");
+               retval = CMD_WARNING_CONFIG_FAILED;
+               break;
+       case RMAP_COMPILE_SUCCESS:
+               if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
+                       route_map_upd8_dependency(type, dep_name, rmap_name);
+               break;
        }
 
-       if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
-               route_map_upd8_dependency(type, dep_name, rmap_name);
-
        if (dep_name)
                XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
        if (rmap_name)
                XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
 
-       return CMD_SUCCESS;
+       return retval;
 }
 
 /* 'match tag TAG'
index 6815916faf8d08b91e232f6b0d80be2b30e8d51f..ec6d4063255554049cba3e91f31c76a4526cf3ad 100644 (file)
@@ -91,7 +91,8 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
                                                                  si->ifindex);
                        break;
                case STATIC_BLACKHOLE:
-                       nexthop = route_entry_nexthop_blackhole_add(re);
+                       nexthop = route_entry_nexthop_blackhole_add(
+                               re, si->bh_type);
                        break;
                case STATIC_IPV6_GATEWAY:
                        nexthop = route_entry_nexthop_ipv6_add(re,
@@ -166,7 +167,8 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
                                                                  si->ifindex);
                        break;
                case STATIC_BLACKHOLE:
-                       nexthop = route_entry_nexthop_blackhole_add(re);
+                       nexthop = route_entry_nexthop_blackhole_add(
+                               re, si->bh_type);
                        break;
                case STATIC_IPV6_GATEWAY:
                        nexthop = route_entry_nexthop_ipv6_add(re,
@@ -187,9 +189,6 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
                                           si->snh_label.num_labels,
                                           &si->snh_label.label[0]);
 
-               /* Save the flags of this static routes (reject, blackhole) */
-               re->flags = si->flags;
-
                if (IS_ZEBRA_DEBUG_RIB) {
                        char buf[INET6_ADDRSTRLEN];
                        if (IS_ZEBRA_DEBUG_RIB) {
@@ -364,7 +363,7 @@ void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
 
 int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
                     struct prefix_ipv6 *src_p, union g_addr *gate,
-                    const char *ifname, u_char flags,
+                    const char *ifname, enum blackhole_type bh_type,
                     route_tag_t tag, u_char distance, struct zebra_vrf *zvrf,
                     struct static_nh_label *snh_label)
 {
@@ -405,7 +404,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
                        if ((distance == si->distance) && (tag == si->tag)
                            && !memcmp(&si->snh_label, snh_label,
                                       sizeof(struct static_nh_label))
-                           && si->flags == flags) {
+                           && si->bh_type == bh_type) {
                                route_unlock_node(rn);
                                return 0;
                        } else
@@ -424,7 +423,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
 
        si->type = type;
        si->distance = distance;
-       si->flags = flags;
+       si->bh_type = bh_type;
        si->tag = tag;
        si->vrf_id = zvrf_id(zvrf);
        if (ifname)
index ff9f0f59e7da5d55ab90584a6a73f34ae77d607b..458594a28951edea3cbae5c8971ee9c8fa7ed995 100644 (file)
@@ -61,18 +61,12 @@ struct static_route {
        /*
         * Nexthop value.
         */
+       enum blackhole_type bh_type;
        union g_addr addr;
        ifindex_t ifindex;
 
        char ifname[INTERFACE_NAMSIZ + 1];
 
-       /* bit flags */
-       u_char flags;
-       /*
-        see ZEBRA_FLAG_REJECT
-            ZEBRA_FLAG_BLACKHOLE
-        */
-
        /* Label information */
        struct static_nh_label snh_label;
 };
@@ -86,7 +80,7 @@ extern void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
 
 extern int static_add_route(afi_t, safi_t safi, u_char type, struct prefix *p,
                            struct prefix_ipv6 *src_p, union g_addr *gate,
-                           const char *ifname, u_char flags,
+                           const char *ifname, enum blackhole_type bh_type,
                            route_tag_t tag, u_char distance,
                            struct zebra_vrf *zvrf,
                            struct static_nh_label *snh_label);
index ff140bad676835739325aa1fd059b407162843d2..0a26ac6ad79d5ade6c4dd76f364159fa12a27606 100644 (file)
@@ -470,7 +470,11 @@ static int vrf_config_write(struct vty *vty)
        RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
        {
                zvrf = vrf->info;
-               if (!zvrf || strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) {
+
+               if (!zvrf)
+                       continue;
+
+               if (strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) {
                        vty_out(vty, "vrf %s\n", zvrf_name(zvrf));
                        vty_out(vty, "!\n");
                }
index 9f887e840189428045cfb4d16fd7cd34a3556571..98ce98534492795d4cdf0d8e5af31b499cfd3682 100644 (file)
@@ -74,7 +74,7 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
        union g_addr gate;
        union g_addr *gatep = NULL;
        struct in_addr mask;
-       u_char flag = 0;
+       enum blackhole_type bh_type = 0;
        route_tag_t tag = 0;
        struct zebra_vrf *zvrf;
        u_char type;
@@ -165,28 +165,18 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
                }
        }
 
-       /* Null0 static route.  */
-       if ((ifname != NULL)
-           && (strncasecmp(ifname, "Null0", strlen(ifname)) == 0)) {
-               if (flag_str) {
-                       vty_out(vty, "%% can not have flag %s with Null0\n",
-                               flag_str);
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE);
-               ifname = NULL;
-       }
-
        /* Route flags */
        if (flag_str) {
                switch (flag_str[0]) {
                case 'r':
                case 'R': /* XXX */
-                       SET_FLAG(flag, ZEBRA_FLAG_REJECT);
+                       bh_type = BLACKHOLE_REJECT;
                        break;
+               case 'n':
+               case 'N' /* XXX */:
                case 'b':
                case 'B': /* XXX */
-                       SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE);
+                       bh_type = BLACKHOLE_NULL;
                        break;
                default:
                        vty_out(vty, "%% Malformed flag %s \n", flag_str);
@@ -221,7 +211,7 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
 
        if (!negate)
                static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
-                                   flag, tag, distance, zvrf, &snh_label);
+                                bh_type, tag, distance, zvrf, &snh_label);
        else
                static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
                                    tag, distance, zvrf, &snh_label);
@@ -340,14 +330,12 @@ DEFUN (show_ip_rpf_addr,
 }
 
 /* Static route configuration.  */
-DEFPY (ip_route,
-       ip_route_cmd,
-       "[no] ip route\
+DEFPY(ip_route, ip_route_cmd,
+      "[no] ip route\
           <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>\
           <\
             {A.B.C.D$gate|INTERFACE$ifname}\
-            |null0$ifname\
-            |<reject|blackhole>$flag\
+            |<null0|reject|blackhole>$flag\
           >\
           [{\
             tag (1-4294967295)\
@@ -355,22 +343,21 @@ DEFPY (ip_route,
             |vrf NAME\
             |label WORD\
           }]",
-       NO_STR
-       IP_STR
-       "Establish static routes\n"
-       "IP destination prefix (e.g. 10.0.0.0/8)\n"
-       "IP destination prefix\n"
-       "IP destination prefix mask\n"
-       "IP gateway address\n"
-       "IP gateway interface name\n"
-       "Null interface\n"
-       "Emit an ICMP unreachable when matched\n"
-       "Silently discard pkts when matched\n"
-       "Set tag for this route\n"
-       "Tag value\n"
-       "Distance value for this route\n"
-       VRF_CMD_HELP_STR
-       MPLS_LABEL_HELPSTR)
+      NO_STR IP_STR
+      "Establish static routes\n"
+      "IP destination prefix (e.g. 10.0.0.0/8)\n"
+      "IP destination prefix\n"
+      "IP destination prefix mask\n"
+      "IP gateway address\n"
+      "IP gateway interface name\n"
+      "Null interface\n"
+      "Emit an ICMP unreachable when matched\n"
+      "Silently discard pkts when matched\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this route\n"
+      VRF_CMD_HELP_STR
+      MPLS_LABEL_HELPSTR)
 {
        return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
                                  mask_str, NULL, gate_str, ifname, flag,
@@ -417,10 +404,6 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
                        vty_out(vty, ", best");
                if (re->refcnt)
                        vty_out(vty, ", refcnt %ld", re->refcnt);
-               if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
-                       vty_out(vty, ", blackhole");
-               if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
-                       vty_out(vty, ", reject");
                vty_out(vty, "\n");
 
                if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
@@ -485,7 +468,21 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
                                                       re->vrf_id));
                                break;
                        case NEXTHOP_TYPE_BLACKHOLE:
-                               vty_out(vty, " directly connected, Null0");
+                               vty_out(vty, " unreachable");
+                               switch (nexthop->bh_type) {
+                               case BLACKHOLE_REJECT:
+                                       vty_out(vty, " (ICMP unreachable)");
+                                       break;
+                               case BLACKHOLE_ADMINPROHIB:
+                                       vty_out(vty,
+                                               " (ICMP admin-prohibited)");
+                                       break;
+                               case BLACKHOLE_NULL:
+                                       vty_out(vty, " (blackhole)");
+                                       break;
+                               case BLACKHOLE_UNSPEC:
+                                       break;
+                               }
                                break;
                        default:
                                break;
@@ -580,12 +577,6 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
                        json_object_int_add(json_route, "metric", re->metric);
                }
 
-               if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
-                       json_object_boolean_true_add(json_route, "blackhole");
-
-               if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
-                       json_object_boolean_true_add(json_route, "reject");
-
                if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
                    || re->type == ZEBRA_ROUTE_ISIS
                    || re->type == ZEBRA_ROUTE_NHRP
@@ -671,7 +662,24 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
                                break;
                        case NEXTHOP_TYPE_BLACKHOLE:
                                json_object_boolean_true_add(json_nexthop,
-                                                            "blackhole");
+                                                            "unreachable");
+                               switch (nexthop->bh_type) {
+                               case BLACKHOLE_REJECT:
+                                       json_object_boolean_true_add(
+                                               json_nexthop, "reject");
+                                       break;
+                               case BLACKHOLE_ADMINPROHIB:
+                                       json_object_boolean_true_add(
+                                               json_nexthop,
+                                               "admin-prohibited");
+                                       break;
+                               case BLACKHOLE_NULL:
+                                       json_object_boolean_true_add(
+                                               json_nexthop, "blackhole");
+                                       break;
+                               case BLACKHOLE_UNSPEC:
+                                       break;
+                               }
                                break;
                        default:
                                break;
@@ -796,7 +804,20 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
                                ifindex2ifname(nexthop->ifindex, re->vrf_id));
                        break;
                case NEXTHOP_TYPE_BLACKHOLE:
-                       vty_out(vty, " is directly connected, Null0");
+                       vty_out(vty, " unreachable");
+                       switch (nexthop->bh_type) {
+                       case BLACKHOLE_REJECT:
+                               vty_out(vty, " (ICMP unreachable)");
+                               break;
+                       case BLACKHOLE_ADMINPROHIB:
+                               vty_out(vty, " (ICMP admin-prohibited)");
+                               break;
+                       case BLACKHOLE_NULL:
+                               vty_out(vty, " (blackhole)");
+                               break;
+                       case BLACKHOLE_UNSPEC:
+                               break;
+                       }
                        break;
                default:
                        break;
@@ -839,11 +860,6 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
                                               sizeof buf, 1));
                }
 
-               if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
-                       vty_out(vty, ", bh");
-               if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
-                       vty_out(vty, ", rej");
-
                if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
                    || re->type == ZEBRA_ROUTE_ISIS
                    || re->type == ZEBRA_ROUTE_NHRP
@@ -1181,7 +1197,10 @@ DEFUN (show_ip_route,
                tag = strtoul(argv[idx + 1]->arg, NULL, 10);
 
        else if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
-               str2prefix(argv[idx]->arg, &p);
+               if (str2prefix(argv[idx]->arg, &p) <= 0) {
+                       vty_out(vty, "%% Malformed prefix\n");
+                       return CMD_WARNING;
+               }
                longer_prefixes = true;
        }
 
@@ -1693,12 +1712,15 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
                                case STATIC_IFNAME:
                                        vty_out(vty, " %s", si->ifname);
                                        break;
-                               /* blackhole and Null0 mean the same thing */
                                case STATIC_BLACKHOLE:
-                                       if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT))
+                                       switch (si->bh_type) {
+                                       case BLACKHOLE_REJECT:
                                                vty_out(vty, " reject");
-                                       else
-                                               vty_out(vty, " Null0");
+                                               break;
+                                       default:
+                                               vty_out(vty, " blackhole");
+                                               break;
+                                       }
                                        break;
                                case STATIC_IPV4_GATEWAY_IFNAME:
                                        vty_out(vty, " %s %s",
@@ -1716,19 +1738,6 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
                                        break;
                                }
 
-                               /* flags are incompatible with STATIC_BLACKHOLE
-                                */
-                               if (si->type != STATIC_BLACKHOLE) {
-                                       if (CHECK_FLAG(si->flags,
-                                                      ZEBRA_FLAG_REJECT))
-                                               vty_out(vty, " %s", "reject");
-
-                                       if (CHECK_FLAG(si->flags,
-                                                      ZEBRA_FLAG_BLACKHOLE))
-                                               vty_out(vty, " %s",
-                                                       "blackhole");
-                               }
-
                                if (si->tag)
                                        vty_out(vty, " tag %" ROUTE_TAG_PRI,
                                                si->tag);
@@ -1758,13 +1767,12 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
        return write;
 }
 
-DEFPY (ipv6_route,
-       ipv6_route_cmd,
-       "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M]\
+DEFPY(ipv6_route,
+      ipv6_route_cmd,
+      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M]\
           <\
             {X:X::X:X$gate|INTERFACE$ifname}\
-            |null0$ifname\
-            |<reject|blackhole>$flag\
+            |<null0|reject|blackhole>$flag\
           >\
           [{\
             tag (1-4294967295)\
@@ -1772,22 +1780,22 @@ DEFPY (ipv6_route,
             |vrf NAME\
             |label WORD\
           }]",
-       NO_STR
-       IPV6_STR
-       "Establish static routes\n"
-       "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
-       "IPv6 source-dest route\n"
-       "IPv6 source prefix\n"
-       "IPv6 gateway address\n"
-       "IPv6 gateway interface name\n"
-       "Null interface\n"
-       "Emit an ICMP unreachable when matched\n"
-       "Silently discard pkts when matched\n"
-       "Set tag for this route\n"
-       "Tag value\n"
-       "Distance value for this prefix\n"
-       VRF_CMD_HELP_STR
-       MPLS_LABEL_HELPSTR)
+      NO_STR
+      IPV6_STR
+      "Establish static routes\n"
+      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+      "IPv6 source-dest route\n"
+      "IPv6 source prefix\n"
+      "IPv6 gateway address\n"
+      "IPv6 gateway interface name\n"
+      "Null interface\n"
+      "Emit an ICMP unreachable when matched\n"
+      "Silently discard pkts when matched\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this prefix\n"
+      VRF_CMD_HELP_STR
+      MPLS_LABEL_HELPSTR)
 {
        return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
                                  NULL, from_str, gate_str, ifname, flag,
@@ -1834,7 +1842,10 @@ DEFUN (show_ipv6_route,
                tag = strtoul(argv[idx + 1]->arg, NULL, 10);
 
        else if (argv_find(argv, argc, "X:X::X:X/M", &idx)) {
-               str2prefix(argv[idx]->arg, &p);
+               if (str2prefix(argv[idx]->arg, &p) <= 0) {
+                       vty_out(vty, "%% Malformed prefix\n");
+                       return CMD_WARNING;
+               }
                longer_prefixes = true;
        }
 
@@ -2572,6 +2583,8 @@ DEFUN (ip_zebra_import_table_distance,
                vty_out(vty,
                        "Invalid routing table ID, %d. Must be in range 1-252\n",
                        table_id);
+               if (rmap)
+                       XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
                return CMD_WARNING;
        }
 
@@ -2579,6 +2592,8 @@ DEFUN (ip_zebra_import_table_distance,
                vty_out(vty,
                        "Invalid routing table ID, %d. Must be non-default table\n",
                        table_id);
+               if (rmap)
+                       XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
                return CMD_WARNING;
        }
 
index f99c16ae91a8586a9a256fefab5a2a94f328275d..a3f43f947a2a30a7dc8c2f62aad2951e62eb0785 100644 (file)
@@ -204,13 +204,18 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
                if (json == NULL) {
                        vty_out(vty, " Remote VTEP: %s",
                                inet_ntoa(n->r_vtep_ip));
-                       vty_out(vty, " State: %s", IS_ZEBRA_NEIGH_ACTIVE(n)
-                                                          ? "Active"
-                                                          : "Inactive");
                } else
                        json_object_string_add(json, "remoteVtep",
                                               inet_ntoa(n->r_vtep_ip));
        }
+       if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
+               if (!json) {
+                       vty_out(vty, "\n");
+                       vty_out(vty, " State: %s",
+                               IS_ZEBRA_NEIGH_ACTIVE(n) ? "Active"
+                                                        : "Inactive");
+               }
+       }
        if (json == NULL)
                vty_out(vty, "\n");
 }
@@ -384,8 +389,8 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
        } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
                vty_out(vty, " Auto Mac ");
        }
-       vty_out(vty, " ARP ref: %u\n", mac->neigh_refcnt);
 
+       vty_out(vty, "\n");
        /* print all the associated neigh */
        vty_out(vty, " Neighbors:\n");
        if (!listcount(mac->neigh_list))
@@ -1155,14 +1160,15 @@ static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n)
        if (!(n->flags & ZEBRA_NEIGH_REMOTE))
                return 0;
 
-       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
-       assert(zvrf);
        if (!zvni->vxlan_if) {
                zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
                         zvni->vni, zvni);
                return -1;
        }
 
+       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
+       assert(zvrf);
+
        zif = zvni->vxlan_if->info;
        if (!zif)
                return -1;
@@ -1343,8 +1349,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
                        zlog_err(
                                "%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
                                ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
-                               prefix_mac2str(macaddr, NULL,
-                                              ETHER_ADDR_STRLEN),
+                               prefix_mac2str(macaddr, buf, sizeof(buf)),
                                ifp->name, ifp->ifindex, zvni->vni);
                        return -1;
                }
@@ -1355,14 +1360,11 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
        memcpy(&n->emac, macaddr, ETH_ALEN);
        n->ifindex = ifp->ifindex;
 
-       /* We have a neigh associated to mac increment the refcnt*/
-       mac->neigh_refcnt++;
-
        if (IS_ZEBRA_DEBUG_VXLAN)
                zlog_debug(
                        "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s add to BGP",
                        ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
-                       prefix_mac2str(macaddr, NULL, ETHER_ADDR_STRLEN),
+                       prefix_mac2str(macaddr, buf, sizeof(buf)),
                        ipaddr2str(ip, buf2, sizeof(buf2)));
 
        zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip, macaddr,
@@ -1380,6 +1382,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
        struct zebra_vrf *zvrf = NULL;
        zebra_neigh_t *n = NULL;
        zebra_mac_t *mac = NULL;
+       char buf1[ETHER_ADDR_STRLEN];
        char buf2[INET6_ADDRSTRLEN];
 
        zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
@@ -1393,11 +1396,13 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
 
        /* mac entry should be present */
        mac = zvni_mac_lookup(zvni, &n->emac);
-       if (!mac)
-               zlog_err("%u: MAC %s doesnt exsists for neigh %s on VNI %u",
+       if (!mac) {
+               zlog_err("%u: MAC %s doesnt exists for neigh %s on VNI %u",
                         ifp->vrf_id,
-                        prefix_mac2str(&n->emac, NULL, ETHER_ADDR_STRLEN),
+                        prefix_mac2str(&n->emac, buf1, sizeof(buf1)),
                         ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
+               return -1;
+       }
 
        /* If the entry is not local nothing to do*/
        if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
@@ -1407,7 +1412,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
                zlog_debug(
                        "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
                        ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
-                       prefix_mac2str(&(n->emac), NULL, ETHER_ADDR_STRLEN),
+                       prefix_mac2str(&(n->emac), buf1, sizeof(buf1)),
                        ipaddr2str(ip, buf2, sizeof(buf2)));
 
        /* Remove neighbor from BGP. */
@@ -1418,7 +1423,8 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
        zvni_neigh_del(zvni, n);
 
        /* see if the mac needs to be deleted as well*/
-       zvni_deref_ip2mac(zvni, mac, 0);
+       if (mac)
+               zvni_deref_ip2mac(zvni, mac, 0);
 
        return 0;
 }
@@ -1431,13 +1437,22 @@ static void zvni_gw_macip_del_for_vni_hash(struct hash_backet *backet,
        struct zebra_l2info_vxlan zl2_info;
        struct interface *vlan_if = NULL;
        struct interface *vrr_if = NULL;
+       struct interface *ifp;
 
        /* Add primary SVI MAC*/
        zvni = (zebra_vni_t *)backet->data;
        if (!zvni)
                return;
 
-       zif = zvni->vxlan_if->info;
+       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(zvrf, zl2_info.access_vlan,
@@ -1464,6 +1479,7 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
        struct zebra_l2info_vxlan zl2_info;
        struct interface *vlan_if = NULL;
        struct interface *vrr_if = NULL;
+       struct interface *ifp = NULL;
 
        zvni = (zebra_vni_t *)backet->data;
        if (!zvni)
@@ -1472,7 +1488,14 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
        if (!advertise_gw_macip_enabled(zvrf, zvni))
                return;
 
-       zif = zvni->vxlan_if->info;
+       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(zvrf, zl2_info.access_vlan,
@@ -1758,6 +1781,9 @@ static zebra_vni_t *zvni_map_svi(struct interface *ifp, struct interface *br_if)
        vlanid_t vid = 0;
        zebra_vni_t *zvni;
 
+       if (!br_if)
+               return NULL;
+
        /* Make sure the linked interface is a bridge. */
        if (!IS_ZEBRA_IF_BRIDGE(br_if))
                return NULL;
@@ -1827,6 +1853,10 @@ static struct interface *zvni_map_to_svi(struct zebra_vrf *zvrf, vlanid_t vid,
        struct zebra_l2info_vlan *vl;
        u_char bridge_vlan_aware;
 
+       /* Defensive check, caller expected to invoke only with valid bridge. */
+       if (!br_if)
+               return NULL;
+
        /* Determine if bridge is VLAN-aware or not */
        zif = br_if->info;
        assert(zif);
@@ -1943,10 +1973,8 @@ static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt)
 static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
                              int uninstall)
 {
-       if (mac->neigh_refcnt)
-               mac->neigh_refcnt--;
-
-       if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) || mac->neigh_refcnt > 0)
+       if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)
+           || !list_isempty(mac->neigh_list))
                return;
 
        if (uninstall)
@@ -2853,7 +2881,7 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
 
        /* see if the AUTO mac needs to be deleted */
        if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
-           || !listcount(zmac->neigh_list))
+           && !listcount(zmac->neigh_list))
                zvni_mac_del(zvni, zmac);
 
        return 0;
@@ -2872,10 +2900,9 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
        zebra_vni_t *zvni;
        zebra_neigh_t *n;
        struct zebra_vrf *zvrf;
-       zebra_mac_t *zmac;
+       zebra_mac_t *zmac, *old_zmac;
        char buf[ETHER_ADDR_STRLEN];
        char buf2[INET6_ADDRSTRLEN];
-       int send_upd = 1, send_del = 0;
 
        /* We are only interested in neighbors on an SVI that resides on top
         * of a VxLAN bridge.
@@ -2930,19 +2957,33 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
                        if (memcmp(n->emac.octet, macaddr->octet,
                                   ETH_ALEN)
                            == 0) {
-                               if (n->ifindex == ifp->ifindex)
-                                       /* we're not interested in whatever has
-                                        * changed. */
-                                       return 0;
-                               /* client doesn't care about a purely local
-                                * change. */
-                               send_upd = 0;
-                       } else
-                               /* If the MAC has changed, issue a delete first
-                                * as this means a
-                                * different MACIP route.
+                               /* Update any params and return - client doesn't
+                                * care about a purely local change.
                                 */
-                               send_del = 1;
+                               n->ifindex = ifp->ifindex;
+                               return 0;
+                       }
+
+                       /* If the MAC has changed,
+                        * need to issue a delete first
+                        * as this means a different MACIP route.
+                        * Also, need to do some unlinking/relinking.
+                        */
+                       zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip,
+                                                     &n->emac, 0);
+                       old_zmac = zvni_mac_lookup(zvni, &n->emac);
+                       if (old_zmac) {
+                               listnode_delete(old_zmac->neigh_list, n);
+                               zvni_deref_ip2mac(zvni, old_zmac, 0);
+                       }
+
+                       /* Set "local" forwarding info. */
+                       SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
+                       n->ifindex = ifp->ifindex;
+                       memcpy(&n->emac, macaddr, ETH_ALEN);
+
+                       /* Link to new MAC */
+                       listnode_add_sort(zmac->neigh_list, n);
                } else if (ext_learned)
                /* The neighbor is remote and that is the notification we got.
                   */
@@ -2954,6 +2995,8 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
                {
                        UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
                        n->r_vtep_ip.s_addr = 0;
+                       SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
+                       n->ifindex = ifp->ifindex;
                }
        } else {
                n = zvni_neigh_add(zvni, ip, macaddr);
@@ -2965,17 +3008,11 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
                                ifp->name, ifp->ifindex, zvni->vni);
                        return -1;
                }
+               /* Set "local" forwarding info. */
+               SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
+               n->ifindex = ifp->ifindex;
        }
 
-       /* Issue delete for older info, if needed. */
-       if (send_del)
-               zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac,
-                                             0);
-
-       /* Set "local" forwarding info. */
-       SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
-       n->ifindex = ifp->ifindex;
-
        /* Before we program this in BGP, we need to check if MAC is locally
         * learnt as well */
        if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
@@ -2989,23 +3026,18 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
                return 0;
        }
 
-       /* Inform BGP if required. */
-       if (send_upd) {
-               if (IS_ZEBRA_DEBUG_VXLAN)
-                       zlog_debug(
-                               "%u: neigh %s (MAC %s) is now ACTIVE on VNI %u",
-                               ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
-                               prefix_mac2str(macaddr, buf, sizeof(buf)),
-                               zvni->vni);
-
-               ZEBRA_NEIGH_SET_ACTIVE(n);
-               return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip,
-                                                    macaddr, 0);
-       }
+       /* Inform BGP. */
+       if (IS_ZEBRA_DEBUG_VXLAN)
+               zlog_debug("%u: neigh %s (MAC %s) is now ACTIVE on VNI %u",
+                          ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
+                          prefix_mac2str(macaddr, buf, sizeof(buf)),
+                          zvni->vni);
 
-       return 0;
+       ZEBRA_NEIGH_SET_ACTIVE(n);
+       return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip, macaddr, 0);
 }
 
+
 /*
  * Handle message from client to delete a remote MACIP for a VNI.
  */
@@ -3023,6 +3055,8 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
        u_short l = 0, ipa_len;
        char buf[ETHER_ADDR_STRLEN];
        char buf1[INET6_ADDRSTRLEN];
+       struct interface *ifp = NULL;
+       struct zebra_if *zif = NULL;
 
        s = client->ibuf;
 
@@ -3065,12 +3099,18 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
                                        zvrf_id(zvrf), vni);
                        continue;
                }
-               if (!zvni->vxlan_if) {
+               ifp = zvni->vxlan_if;
+               if (!ifp) {
                        zlog_err(
                                "VNI %u hash %p doesn't have intf upon remote MACIP DEL",
                                vni, zvni);
                        continue;
                }
+               zif = ifp->info;
+
+               /* If down or not mapped to a bridge, we're done. */
+               if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+                       continue;
 
                /* The remote VTEP specified is normally expected to exist, but
                 * it is
@@ -3083,12 +3123,6 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
                if (!zvni_vtep_find(zvni, &vtep_ip))
                        continue;
 
-               /* If the local VxLAN interface is not up (should be a transient
-                * event),  there's nothing more to do.
-                */
-               if (!if_is_operative(zvni->vxlan_if))
-                       continue;
-
                mac = zvni_mac_lookup(zvni, &macaddr);
                if (ipa_len)
                        n = zvni_neigh_lookup(zvni, &ip);
@@ -3132,7 +3166,7 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
                                zvni_process_neigh_on_remote_mac_del(zvrf, zvni,
                                                                     mac);
 
-                               if (!mac->neigh_refcnt) {
+                               if (list_isempty(mac->neigh_list)) {
                                        zvni_mac_uninstall(zvni, mac, 0);
                                        zvni_mac_del(zvni, mac);
                                } else
@@ -3166,6 +3200,8 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
        char buf[ETHER_ADDR_STRLEN];
        char buf1[INET6_ADDRSTRLEN];
        u_char sticky;
+       struct interface *ifp = NULL;
+       struct zebra_if *zif = NULL;
 
        assert(EVPN_ENABLED(zvrf));
 
@@ -3213,16 +3249,17 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
                                zvrf_id(zvrf), vni);
                        continue;
                }
-               if (!zvni->vxlan_if) {
+               ifp = zvni->vxlan_if;
+               if (!ifp) {
                        zlog_err(
                                "VNI %u hash %p doesn't have intf upon remote MACIP add",
                                vni, zvni);
                        continue;
                }
-               /* If the local VxLAN interface is not up (should be a transient
-                * event),  there's nothing more to do.
-                */
-               if (!if_is_operative(zvni->vxlan_if))
+               zif = ifp->info;
+
+               /* If down or not mapped to a bridge, we're done. */
+               if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
                        continue;
 
                /* The remote VTEP specified should normally exist, but it is
@@ -3272,9 +3309,6 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
                                /* Is this MAC created for a MACIP? */
                                if (ipa_len)
                                        SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
-                       } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
-                               /* Moving from local to remote, issue delete. */
-                               zvni_mac_uninstall(zvni, mac, 1);
                        }
 
                        /* Set "auto" and "remote" forwarding info. */
@@ -3326,16 +3360,16 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
                                        return -1;
                                }
 
-                               /* New neighbor referring to this MAC. */
-                               mac->neigh_refcnt++;
                        } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
                                   != 0) {
-                               /* MAC change, update ref counts for old and new
-                                * MAC. */
+                               /* MAC change, update neigh list for old and new
+                                * mac */
                                old_mac = zvni_mac_lookup(zvni, &n->emac);
-                               if (old_mac)
+                               if (old_mac) {
+                                       listnode_delete(old_mac->neigh_list, n);
                                        zvni_deref_ip2mac(zvni, old_mac, 1);
-                               mac->neigh_refcnt++;
+                               }
+                               listnode_add_sort(mac->neigh_list, n);
                                memcpy(&n->emac, &macaddr, ETH_ALEN);
                        }
 
@@ -3687,6 +3721,8 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length,
        struct in_addr vtep_ip;
        zebra_vni_t *zvni;
        zebra_vtep_t *zvtep;
+       struct interface *ifp;
+       struct zebra_if *zif;
 
        s = client->ibuf;
 
@@ -3713,6 +3749,19 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length,
                        continue;
                }
 
+               ifp = zvni->vxlan_if;
+               if (!ifp) {
+                       zlog_err(
+                               "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
+                               zvni->vni, zvni);
+                       continue;
+               }
+               zif = ifp->info;
+
+               /* If down or not mapped to a bridge, we're done. */
+               if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+                       continue;
+
                /* If the remote VTEP does not exist, there's nothing more to
                 * do.
                 * Otherwise, uninstall any remote MACs pointing to this VTEP
@@ -3743,6 +3792,8 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length,
        vni_t vni;
        struct in_addr vtep_ip;
        zebra_vni_t *zvni;
+       struct interface *ifp;
+       struct zebra_if *zif;
 
        assert(EVPN_ENABLED(zvrf));
 
@@ -3768,24 +3819,24 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length,
                                zvrf_id(zvrf), vni);
                        continue;
                }
-               if (!zvni->vxlan_if) {
+
+               ifp = zvni->vxlan_if;
+               if (!ifp) {
                        zlog_err(
                                "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
                                zvni->vni, zvni);
                        continue;
                }
 
+               zif = ifp->info;
 
-               /* If the remote VTEP already exists, or the local VxLAN
-                * interface is
-                * not up (should be a transient event),  there's nothing more
-                * to do.
-                * Otherwise, add and install the entry.
-                */
-               if (zvni_vtep_find(zvni, &vtep_ip))
+               /* If down or not mapped to a bridge, we're done. */
+               if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
                        continue;
 
-               if (!if_is_operative(zvni->vxlan_if))
+               /* If the remote VTEP already exists,
+                  there's nothing more to do. */
+               if (zvni_vtep_find(zvni, &vtep_ip))
                        continue;
 
                if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
@@ -3839,7 +3890,11 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
                if (!ifp_zif)
                        return -1;
 
-               svi_if = ifp_zif->link;
+               /*
+                * for a MACVLAN interface the link represents the svi_if
+                */
+               svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+                                                  ifp_zif->link_ifindex);
                if (!svi_if) {
                        zlog_err("%u:MACVLAN %s(%u) without link information",
                                 ifp->vrf_id, ifp->name, ifp->ifindex);
@@ -3847,19 +3902,37 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
                }
 
                if (IS_ZEBRA_IF_VLAN(svi_if)) {
+                       /*
+                        * If it is a vlan aware bridge then the link gives the
+                        * bridge information
+                        */
+                       struct interface *svi_if_link = NULL;
+
                        svi_if_zif = svi_if->info;
-                       if (svi_if_zif)
-                               zvni = zvni_map_svi(svi_if, svi_if_zif->link);
+                       if (svi_if_zif) {
+                               svi_if_link = if_lookup_by_index_per_ns(
+                                       zebra_ns_lookup(NS_DEFAULT),
+                                       svi_if_zif->link_ifindex);
+                               zvni = zvni_map_svi(svi_if, svi_if_link);
+                       }
                } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
+                       /*
+                        * If it is a vlan unaware bridge then svi is the bridge
+                        * itself
+                        */
                        zvni = zvni_map_svi(svi_if, svi_if);
                }
        } else if (IS_ZEBRA_IF_VLAN(ifp)) {
                struct zebra_if *svi_if_zif =
-                       NULL; /* Zebra daemon specific info for SVI*/
+                       NULL; /* Zebra daemon specific info for SVI */
+               struct interface *svi_if_link =
+                       NULL; /* link info for the SVI = bridge info */
 
                svi_if_zif = ifp->info;
-               if (svi_if_zif)
-                       zvni = zvni_map_svi(ifp, svi_if_zif->link);
+               svi_if_link = if_lookup_by_index_per_ns(
+                       zebra_ns_lookup(NS_DEFAULT), svi_if_zif->link_ifindex);
+               if (svi_if_zif && svi_if_link)
+                       zvni = zvni_map_svi(ifp, svi_if_link);
        } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
                zvni = zvni_map_svi(ifp, ifp);
        }
@@ -4141,7 +4214,7 @@ int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
                        vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
                        zif->brslave_info.bridge_ifindex, chgflags);
 
-       /* Removed from bridge? */
+       /* Removed from bridge? Cleanup and return */
        if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
            && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
                /* Delete from client, remove all remote VTEPs */
@@ -4150,7 +4223,11 @@ int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
                zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH);
                zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC);
                zvni_vtep_del_all(zvni, 1);
-       } else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
+               return 0;
+       }
+
+       /* Handle other changes. */
+       if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
                /* Remove all existing local neighbors and MACs for this VNI
                 * (including from BGP)
                 */
@@ -4268,6 +4345,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
        int advertise;
        vni_t vni = 0;
        zebra_vni_t *zvni = NULL;
+       struct interface *ifp = NULL;
 
        s = client->ibuf;
        advertise = stream_getc(s);
@@ -4318,7 +4396,16 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
 
                zvni->advertise_gw_macip = advertise;
 
-               zif = zvni->vxlan_if->info;
+               ifp = zvni->vxlan_if;
+               if (!ifp)
+                       return 0;
+
+               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 0;
+
                zl2_info = zif->l2info.vxl;
 
                vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
index 8539311eabd9babb430f28b41a216719efd1a779..fa7d0e94578f14e57e4ed171db6bcef987142fbc 100644 (file)
@@ -114,8 +114,6 @@ struct zebra_mac_t_ {
                struct in_addr r_vtep_ip;
        } fwd_info;
 
-       u_int32_t neigh_refcnt;
-
        /* List of neigh associated with this mac */
        struct list *neigh_list;
 };
index 0e0cc78bbe3be3267f979a2288b1ff71acef1f33..ef289f3960cf160667af1c838bfb956aa47b4fa2 100644 (file)
@@ -626,6 +626,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
                api_nh->type = nexthop->type;
                switch (nexthop->type) {
                case NEXTHOP_TYPE_BLACKHOLE:
+                       api_nh->bh_type = nexthop->bh_type;
                        break;
                case NEXTHOP_TYPE_IPV4:
                        api_nh->gate.ipv4 = nexthop->gate.ipv4;
@@ -1093,7 +1094,8 @@ static int zread_route_add(struct zserv *client, u_short length,
                                        api_nh->ifindex);
                                break;
                        case NEXTHOP_TYPE_BLACKHOLE:
-                               route_entry_nexthop_blackhole_add(re);
+                               route_entry_nexthop_blackhole_add(
+                                       re, api_nh->bh_type);
                                break;
                        }
 
@@ -1163,7 +1165,7 @@ static int zread_route_del(struct zserv *client, u_short length,
                src_p = &api.src_prefix;
 
        rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance,
-                  api.flags, &api.prefix, src_p, NULL, 0, zvrf->table_id,
+                  api.flags, &api.prefix, src_p, NULL, zvrf->table_id,
                   api.metric);
 
        /* Stats */
@@ -1201,6 +1203,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
        enum lsp_types_t label_type = ZEBRA_LSP_NONE;
        mpls_label_t label;
        struct nexthop *nexthop;
+       enum blackhole_type bh_type = BLACKHOLE_NULL;
 
        /* Get input stream.  */
        s = client->ibuf;
@@ -1264,7 +1267,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
                                stream_forward_getp(s, IPV6_MAX_BYTELEN);
                                break;
                        case NEXTHOP_TYPE_BLACKHOLE:
-                               route_entry_nexthop_blackhole_add(re);
+                               route_entry_nexthop_blackhole_add(re, bh_type);
                                break;
                        }
                }
@@ -1329,7 +1332,7 @@ static int zread_ipv4_delete(struct zserv *client, u_short length,
        table_id = zvrf->table_id;
 
        rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
-                  api.flags, &p, NULL, NULL, 0, table_id, 0);
+                  api.flags, &p, NULL, NULL, table_id, 0);
        client->v4_route_del_cnt++;
        return 0;
 }
@@ -1367,6 +1370,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
        enum lsp_types_t label_type = ZEBRA_LSP_NONE;
        mpls_label_t label;
        struct nexthop *nexthop;
+       enum blackhole_type bh_type = BLACKHOLE_NULL;
 
        /* Get input stream.  */
        s = client->ibuf;
@@ -1434,7 +1438,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
                                }
                                break;
                        case NEXTHOP_TYPE_BLACKHOLE:
-                               route_entry_nexthop_blackhole_add(re);
+                               route_entry_nexthop_blackhole_add(re, bh_type);
                                break;
                        }
                }
@@ -1516,6 +1520,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
        enum lsp_types_t label_type = ZEBRA_LSP_NONE;
        mpls_label_t label;
        struct nexthop *nexthop;
+       enum blackhole_type bh_type = BLACKHOLE_NULL;
 
        /* Get input stream.  */
        s = client->ibuf;
@@ -1594,7 +1599,7 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
                                }
                                break;
                        case NEXTHOP_TYPE_BLACKHOLE:
-                               route_entry_nexthop_blackhole_add(re);
+                               route_entry_nexthop_blackhole_add(re, bh_type);
                                break;
                        }
                }
@@ -1674,7 +1679,7 @@ static int zread_ipv6_delete(struct zserv *client, u_short length,
        api.safi = stream_getw(s);
 
        /* IPv4 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv6));
+       memset(&p, 0, sizeof(struct prefix));
        p.family = AF_INET6;
        p.prefixlen = stream_getc(s);
        stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen));
@@ -1689,7 +1694,7 @@ static int zread_ipv6_delete(struct zserv *client, u_short length,
                src_pp = NULL;
 
        rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
-                  api.flags, &p, src_pp, NULL, 0, client->rtm_table, 0);
+                  api.flags, &p, src_pp, NULL, client->rtm_table, 0);
 
        client->v6_route_del_cnt++;
        return 0;