]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge remote-tracking branch 'upstream/master' into evpn-extended-mobility
authorvivek <vivek@cumulusnetworks.com>
Mon, 27 Aug 2018 22:13:30 +0000 (22:13 +0000)
committervivek <vivek@cumulusnetworks.com>
Mon, 27 Aug 2018 22:13:30 +0000 (22:13 +0000)
Conflicts:
zebra/zebra_vxlan.c

101 files changed:
bgpd/bgp_evpn.c
bgpd/bgp_evpn_private.h
bgpd/bgp_evpn_vty.c
bgpd/bgp_flowspec.c
bgpd/bgp_flowspec_vty.c
bgpd/bgp_network.c
bgpd/bgp_pbr.c
bgpd/bgp_route.c
bgpd/bgp_rpki.c
bgpd/bgp_table.h
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.c
configure.ac
debianpkg/backports/ubuntu12.04/debian/rules
debianpkg/backports/ubuntu14.04/debian/rules
debianpkg/rules
doc/Makefile.am
doc/developer/library.rst
doc/developer/logging.rst [new file with mode: 0644]
doc/developer/zebra.rst
doc/manpages/common-options.rst
doc/manpages/index.rst
doc/user/_static/overrides.css
doc/user/_static/overrides.js [new file with mode: 0644]
doc/user/bfd.rst
doc/user/bgp.rst
doc/user/conf.py
doc/user/overview.rst
doc/user/snmp.rst
isisd/isis_bpf.c
isisd/isis_circuit.c
lib/buffer.c
lib/compiler.h
lib/ferr.c
lib/if.c
lib/if.h
lib/log.c
lib/log.h
lib/smux.c [deleted file]
lib/sockopt.c
lib/spf_backoff.c
lib/stream.c
lib/stream.h
lib/subdir.am
lib/table.h
lib/thread.c
lib/vrf.c
lib/vrf.h
lib/zclient.c
lib/zclient.h
ospfclient/ospf_apiclient.c
ospfd/ospf_apiserver.c
ospfd/ospf_asbr.c
ospfd/ospf_asbr.h
ospfd/ospf_ase.c
ospfd/ospf_ext.c
ospfd/ospf_flood.c
ospfd/ospf_lsa.c
ospfd/ospf_lsa.h
ospfd/ospf_main.c
ospfd/ospf_packet.c
ospfd/ospf_ri.c
ospfd/ospf_snmp.c
ospfd/ospf_te.c
ospfd/ospf_zebra.c
ospfd/ospfd.c
pimd/pim_cmd.c
pimd/pim_iface.c
pimd/pim_iface.h
pimd/pim_ifchannel.c
pimd/pim_oil.c
pimd/pim_pim.c
pimd/pim_upstream.c
snapcraft/README.usage.md
snapcraft/scripts/bgpd-service
snapcraft/scripts/set-options
snapcraft/snapcraft.yaml.in
staticd/static_vty.c
staticd/static_zebra.c
tests/bgpd/test_capability.c
tests/lib/test_stream.c
vtysh/vtysh.c
zebra/GNOME-PRODUCT-ZEBRA-MIB [deleted file]
zebra/GNOME-SMI [deleted file]
zebra/client_main.c [deleted file]
zebra/if_ioctl.c
zebra/kernel_netlink.c
zebra/kernel_netlink.h
zebra/redistribute.c
zebra/redistribute.h
zebra/rib.h
zebra/rt_netlink.c
zebra/subdir.am
zebra/zapi_msg.c
zebra/zebra_rib.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zebra_routemap.c
zebra/zebra_vxlan.c

index fee2e89f8b3aea0a1e6130e503f2c29ae0a0e78a..a104a2e16d669439539cc71bde0ac39606a40825 100644 (file)
@@ -4896,6 +4896,23 @@ void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn)
        UNSET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
 }
 
+/*
+ * Lookup L3-VNI
+ */
+bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni)
+{
+       struct list *inst = bm->bgp;
+       struct listnode *node;
+       struct bgp *bgp_vrf;
+
+       for (ALL_LIST_ELEMENTS_RO(inst, node, bgp_vrf)) {
+               if (bgp_vrf->l3vni == vni)
+                       return true;
+       }
+
+       return false;
+}
+
 /*
  * Lookup VNI.
  */
index 8d71c3123e830af11eb70ac8877101f08bf46b4b..f0017f3533fac2d7f57edc1b752040e1978a48f4 100644 (file)
@@ -503,4 +503,5 @@ extern struct evpnes *bgp_evpn_lookup_es(struct bgp *bgp, esi_t *esi);
 extern struct evpnes *bgp_evpn_es_new(struct bgp *bgp, esi_t *esi,
                                      struct ipaddr *originator_ip);
 extern void bgp_evpn_es_free(struct bgp *bgp, struct evpnes *es);
+extern bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni);
 #endif /* _BGP_EVPN_PRIVATE_H */
index 3828ce216bd24c4df86024089b513bc3ffb86683..b553cb42a5ac4169e748ae015a6449fcb1ba9c4c 100644 (file)
@@ -1888,6 +1888,14 @@ static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
 
        vpn = bgp_evpn_lookup_vni(bgp, vni);
        if (!vpn) {
+               /* Check if this L2VNI is already configured as L3VNI */
+               if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
+                       flog_err(BGP_ERR_VNI,
+                                "%u: Failed to create L2VNI %u, it is configured as L3VNI",
+                                bgp->vrf_id, vni);
+                       return NULL;
+               }
+
                /* tenant vrf will be updated when we get local_vni_add from
                 * zebra
                 */
index 6695596c6f6b372906f7ffecceb7b0a7ae5fad89..e29508bf3680d9e946bb77db9b40cc593a947386 100644 (file)
@@ -148,7 +148,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
 
                if (BGP_DEBUG(flowspec, FLOWSPEC)) {
                        char return_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
-                       char local_string[BGP_FLOWSPEC_NLRI_STRING_MAX * 2];
+                       char local_string[BGP_FLOWSPEC_NLRI_STRING_MAX*2+16];
                        char ec_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
                        char *s = NULL;
 
index f8c06132084eb8b465387d0de98da3aabeff3f26..31d2c540fa524e2d044a299daad914ea6457cfef 100644 (file)
@@ -335,7 +335,7 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
                        struct listnode *node;
                        struct bgp_pbr_match_entry *bpme;
                        struct bgp_pbr_match *bpm;
-                       int unit = 0;
+                       bool list_began = false;
                        struct list *list_bpm;
 
                        list_bpm = list_new();
@@ -347,14 +347,14 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
                                if (listnode_lookup(list_bpm, bpm))
                                        continue;
                                listnode_add(list_bpm, bpm);
-                               if (unit == 0)
+                               if (!list_began) {
                                        vty_out(vty, " (");
-                               else
+                                       list_began = true;
+                               } else
                                        vty_out(vty, ", ");
                                vty_out(vty, "%s", bpm->ipset_name);
-                               unit++;
                        }
-                       if (unit)
+                       if (list_began)
                                vty_out(vty, ")");
                        vty_out(vty, "\n");
                        list_delete_and_null(&list_bpm);
index 0664fdfd1cdd720ebe67b9f2993a8e906b14f847..22d5d35c822160389a59636dbeb1be4f373cf56f 100644 (file)
@@ -672,7 +672,8 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
        listener->fd = sock;
 
        /* this socket needs a change of ns. record bgp back pointer */
-       if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(bgp->vrf_id))
+       if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(
+                                               vrf_lookup_by_id(bgp->vrf_id)))
                listener->bgp = bgp;
 
        memcpy(&listener->su, sa, salen);
index 129c143a64bce6b54eca4e51883bd1a2c851a831..b182fde1e2ec5d0d495be6f7dd152ab993b26623 100644 (file)
@@ -1680,7 +1680,7 @@ static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add)
                         ? "!" : "",
                         bpf->dscp->val);
        }
-       zlog_info("BGP: %s FS PBR from %s to %s, %s %s",
+       zlog_debug("BGP: %s FS PBR from %s to %s, %s %s",
                  add ? "adding" : "removing",
                  bpf->src == NULL ? "<all>" :
                  prefix2str(bpf->src, bufsrc, sizeof(bufsrc)),
@@ -1807,7 +1807,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
                       bgp_pbr_match_alloc_intern);
 
        /* new, then self allocate ipset_name and unique */
-       if (bpm && bpm->unique == 0) {
+       if (bpm->unique == 0) {
                bpm->unique = ++bgp_pbr_match_counter_unique;
                /* 0 value is forbidden */
                sprintf(bpm->ipset_name, "match%p", bpm);
@@ -1838,10 +1838,9 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
        temp2.src_port_max = src_port ? src_port->max_port : 0;
        temp2.dst_port_max = dst_port ? dst_port->max_port : 0;
        temp2.proto = bpf->protocol;
-       if (bpm)
-               bpme = hash_get(bpm->entry_hash, &temp2,
-                               bgp_pbr_match_entry_alloc_intern);
-       if (bpme && bpme->unique == 0) {
+       bpme = hash_get(bpm->entry_hash, &temp2,
+                       bgp_pbr_match_entry_alloc_intern);
+       if (bpme->unique == 0) {
                bpme->unique = ++bgp_pbr_match_entry_counter_unique;
                /* 0 value is forbidden */
                bpme->backpointer = bpm;
@@ -1853,7 +1852,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
                bpme_found = true;
 
        /* already installed */
-       if (bpme_found && bpme) {
+       if (bpme_found) {
                struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
 
                if (extra && extra->bgp_fs_pbr &&
index 041049d05b3f52550db0e72e6cf124030e81d3ce..50c484d7de7b8264eef6f1c1b89b9aba986204f3 100644 (file)
@@ -38,6 +38,7 @@
 #include "queue.h"
 #include "memory.h"
 #include "lib/json.h"
+#include "lib_errors.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_table.h"
@@ -188,8 +189,24 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
        if (e->parent) {
                struct bgp_info *bi = (struct bgp_info *)e->parent;
 
-               if (bi->net)
-                       bi->net = bgp_unlock_node((struct bgp_node *)bi->net);
+               if (bi->net) {
+                       /* FIXME: since multiple e may have the same e->parent
+                        * and e->parent->net is holding a refcount for each
+                        * of them, we need to do some fudging here.
+                        *
+                        * WARNING: if bi->net->lock drops to 0, bi may be
+                        * freed as well (because bi->net was holding the
+                        * last reference to bi) => write after free!
+                        */
+                       unsigned refcount;
+
+                       bi = bgp_info_lock(bi);
+                       refcount = bi->net->lock - 1;
+                       bgp_unlock_node((struct bgp_node *)bi->net);
+                       if (!refcount)
+                               bi->net = NULL;
+                       bgp_info_unlock(bi);
+               }
                bgp_info_unlock(e->parent);
                e->parent = NULL;
        }
@@ -198,8 +215,7 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
                bgp_unlock(e->bgp_orig);
 
        if ((*extra)->bgp_fs_pbr)
-               list_delete_all_node((*extra)->bgp_fs_pbr);
-       (*extra)->bgp_fs_pbr = NULL;
+               list_delete_and_null(&((*extra)->bgp_fs_pbr));
        XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
 
        *extra = NULL;
@@ -338,14 +354,9 @@ static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri)
                /* slight hack, but more robust against errors. */
                if (ri->peer->pcount[table->afi][table->safi])
                        ri->peer->pcount[table->afi][table->safi]--;
-               else {
-                       zlog_warn(
-                               "%s: Asked to decrement 0 prefix count for peer %s",
-                               __func__, ri->peer->host);
-                       zlog_backtrace(LOG_WARNING);
-                       zlog_warn("%s: Please report to Quagga bugzilla",
-                                 __func__);
-               }
+               else
+                       flog_err(LIB_ERR_DEVELOPMENT,
+                                "Asked to decrement 0 prefix count for peer");
        } else if (BGP_INFO_COUNTABLE(ri)
                   && !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
                SET_FLAG(ri->flags, BGP_INFO_COUNTED);
@@ -1039,8 +1050,8 @@ static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p,
 
 #define FILTER_EXIST_WARN(F, f, filter)                                        \
        if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter)))                 \
-               zlog_warn("%s: Could not find configured input %s-list %s!",   \
-                         peer->host, #f, F##_IN_NAME(filter));
+               zlog_debug("%s: Could not find configured input %s-list %s!",  \
+                          peer->host, #f, F##_IN_NAME(filter));
 
        if (DISTRIBUTE_IN_NAME(filter)) {
                FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
@@ -1078,8 +1089,8 @@ static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p,
 
 #define FILTER_EXIST_WARN(F, f, filter)                                        \
        if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter)))               \
-               zlog_warn("%s: Could not find configured output %s-list %s!",  \
-                         peer->host, #f, F##_OUT_NAME(filter));
+               zlog_debug("%s: Could not find configured output %s-list %s!", \
+                          peer->host, #f, F##_OUT_NAME(filter));
 
        if (DISTRIBUTE_OUT_NAME(filter)) {
                FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
@@ -8187,7 +8198,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                        vty_out(vty, " \"routeDistinguishers\" : {");
                        ++*json_header_depth;
                }
-               json_paths = json_object_new_object();
        }
 
        if (use_json && rd) {
@@ -8414,8 +8424,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                *total_cum = total_count;
        }
        if (use_json) {
-               if (json_paths)
-                       json_object_free(json_paths);
                if (rd) {
                        vty_out(vty, " }%s ", (is_last ? "" : ","));
                }
@@ -8573,9 +8581,19 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
        int count = 0;
        int best = 0;
        int suppress = 0;
+       int accept_own = 0;
+       int route_filter_translated_v4 = 0;
+       int route_filter_v4 = 0;
+       int route_filter_translated_v6 = 0;
+       int route_filter_v6 = 0;
+       int llgr_stale = 0;
+       int no_llgr = 0;
+       int accept_own_nexthop = 0;
+       int blackhole = 0;
        int no_export = 0;
        int no_advertise = 0;
        int local_as = 0;
+       int no_peer = 0;
        int first = 1;
        int has_valid_label = 0;
        mpls_label_t label = 0;
@@ -8652,12 +8670,41 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
                } else
                        vty_out(vty, ", no best path");
 
-               if (no_advertise)
-                       vty_out(vty, ", not advertised to any peer");
+               if (accept_own)
+                       vty_out(vty,
+                       ", accept own local route exported and imported in different VRF");
+               else if (route_filter_translated_v4)
+                       vty_out(vty,
+                       ", mark translated RTs for VPNv4 route filtering");
+               else if (route_filter_v4)
+                       vty_out(vty,
+                       ", attach RT as-is for VPNv4 route filtering");
+               else if (route_filter_translated_v6)
+                       vty_out(vty,
+                       ", mark translated RTs for VPNv6 route filtering");
+               else if (route_filter_v6)
+                       vty_out(vty,
+                       ", attach RT as-is for VPNv6 route filtering");
+               else if (llgr_stale)
+                       vty_out(vty,
+                       ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
+               else if (no_llgr)
+                       vty_out(vty,
+                       ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
+               else if (accept_own_nexthop)
+                       vty_out(vty,
+                       ", accept local nexthop");
+               else if (blackhole)
+                       vty_out(vty, ", inform peer to blackhole prefix");
                else if (no_export)
                        vty_out(vty, ", not advertised to EBGP peer");
+               else if (no_advertise)
+                       vty_out(vty, ", not advertised to any peer");
                else if (local_as)
                        vty_out(vty, ", not advertised outside local AS");
+               else if (no_peer)
+                       vty_out(vty,
+                       ", inform EBGP peer not to advertise to their EBGP peers");
 
                if (suppress)
                        vty_out(vty,
@@ -9018,6 +9065,10 @@ DEFUN (show_ip_bgp,
            |prefix-list WORD\
            |filter-list WORD\
            |statistics\
+           |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown\
+           no-peer|blackhole|llgr-stale|no-llgr|accept-own|accept-own-nexthop\
+           route-filter-v6|route-filter-v4|route-filter-translated-v6|\
+           route-filter-translated-v4> [exact-match]\
            |community-list <(1-500)|WORD> [exact-match]\
            |A.B.C.D/M longer-prefixes\
            |X:X::X:X/M longer-prefixes\
@@ -9037,6 +9088,23 @@ DEFUN (show_ip_bgp,
        "Display routes conforming to the filter-list\n"
        "Regular expression access list name\n"
        "BGP RIB advertisement statistics\n"
+       "Display routes matching the communities\n"
+       COMMUNITY_AANN_STR
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Graceful shutdown (well-known community)\n"
+       "Do not export to any peer (well-known community)\n"
+       "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
+       "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
+       "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
+       "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
+       "Should accept VPN route with local nexthop (well-known community)\n"
+       "RT VPNv6 route filtering (well-known community)\n"
+       "RT VPNv4 route filtering (well-known community)\n"
+       "RT translated VPNv6 route filtering (well-known community)\n"
+       "RT translated VPNv4 route filtering (well-known community)\n"
+       "Exact match of the communities\n"
        "Display routes matching the community-list\n"
        "community-list number\n"
        "community-list name\n"
@@ -9797,8 +9865,6 @@ static int bgp_peer_count_walker(struct thread *t)
                                pc->count[PCOUNT_ADJ_IN]++;
 
                for (ri = rn->info; ri; ri = ri->next) {
-                       char buf[SU_ADDRSTRLEN];
-
                        if (ri->peer != peer)
                                continue;
 
@@ -9820,22 +9886,12 @@ static int bgp_peer_count_walker(struct thread *t)
                        if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
                                pc->count[PCOUNT_COUNTED]++;
                                if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
-                                       zlog_warn(
-                                               "%s [pcount] %s/%d is counted but flags 0x%x",
-                                               peer->host,
-                                               inet_ntop(rn->p.family,
-                                                         &rn->p.u.prefix, buf,
-                                                         SU_ADDRSTRLEN),
-                                               rn->p.prefixlen, ri->flags);
+                                       flog_err(LIB_ERR_DEVELOPMENT,
+                                                "Attempting to count but flags say it is unusable");
                        } else {
                                if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
-                                       zlog_warn(
-                                               "%s [pcount] %s/%d not counted but flags 0x%x",
-                                               peer->host,
-                                               inet_ntop(rn->p.family,
-                                                         &rn->p.u.prefix, buf,
-                                                         SU_ADDRSTRLEN),
-                                               rn->p.prefixlen, ri->flags);
+                                       flog_err(LIB_ERR_DEVELOPMENT,
+                                                "Not counted but flags say we should");
                        }
                }
        }
index 52c5dc5e9000f80c5d6fee338466248394a03faa..82b268c31d8b487b5d01d2abb5205f379d9fedce 100644 (file)
@@ -47,6 +47,7 @@
 #include "bgpd/bgp_attr.h"
 #include "bgpd/bgp_aspath.h"
 #include "bgpd/bgp_route.h"
+#include "lib/network.h"
 #include "lib/thread.h"
 #include "rtrlib/rtrlib.h"
 #include "rtrlib/rtr_mgr.h"
@@ -131,12 +132,14 @@ static route_map_result_t route_match(void *rule, const struct prefix *prefix,
 static void *route_match_compile(const char *arg);
 static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
                                safi_t safi);
+static void revalidate_all_routes(void);
 
 static struct rtr_mgr_config *rtr_config;
 static struct list *cache_list;
 static int rtr_is_running;
 static int rtr_is_stopping;
 static int rtr_is_starting;
+static _Atomic int rtr_update_overflow;
 static int rpki_debug;
 static unsigned int polling_period;
 static unsigned int expire_interval;
@@ -229,7 +232,7 @@ static void *route_match_compile(const char *arg)
 {
        int *rpki_status;
 
-       rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
+       rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
 
        if (strcmp(arg, "valid") == 0)
                *rpki_status = RPKI_VALID;
@@ -345,6 +348,19 @@ static int bgpd_sync_callback(struct thread *thread)
 
        thread_add_read(bm->master, bgpd_sync_callback, NULL,
                        rpki_sync_socket_bgpd, NULL);
+
+       if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) {
+               while (read(rpki_sync_socket_bgpd, &rec,
+                           sizeof(struct pfx_record))
+                      != -1)
+                       ;
+
+               atomic_store_explicit(&rtr_update_overflow, 0,
+                                     memory_order_seq_cst);
+               revalidate_all_routes();
+               return 0;
+       }
+
        int retval =
                read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
        if (retval != sizeof(struct pfx_record)) {
@@ -356,26 +372,36 @@ static int bgpd_sync_callback(struct thread *thread)
        afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
 
        for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
-               safi_t safi;
+               struct peer *peer;
+               struct listnode *peer_listnode;
+
+               for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
+                       safi_t safi;
 
-               for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
-                       if (!bgp->rib[afi][safi])
-                               continue;
+                       for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+                               if (!peer->bgp->rib[afi][safi])
+                                       continue;
 
-                       struct list *matches = list_new();
+                               struct list *matches = list_new();
 
-                       matches->del = (void (*)(void *))bgp_unlock_node;
+                               matches->del =
+                                       (void (*)(void *))bgp_unlock_node;
 
-                       bgp_table_range_lookup(bgp->rib[afi][safi], prefix,
-                                              rec.max_len, matches);
+                               bgp_table_range_lookup(
+                                       peer->bgp->rib[afi][safi], prefix,
+                                       rec.max_len, matches);
 
 
-                       struct bgp_node *bgp_node;
+                               struct bgp_node *bgp_node;
+                               struct listnode *bgp_listnode;
 
-                       for (ALL_LIST_ELEMENTS_RO(matches, node, bgp_node))
-                               revalidate_bgp_node(bgp_node, afi, safi);
+                               for (ALL_LIST_ELEMENTS_RO(matches, bgp_listnode,
+                                                         bgp_node))
+                                       revalidate_bgp_node(bgp_node, afi,
+                                                           safi);
 
-                       list_delete_and_null(&matches);
+                               list_delete_and_null(&matches);
+                       }
                }
        }
 
@@ -398,14 +424,13 @@ static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
                        label = bgp_info->extra->label;
                        num_labels = bgp_info->extra->num_labels;
                }
-               ret = bgp_update(ain->peer, &bgp_node->p, 0, ain->attr, afi,
-                                safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
-                                label, num_labels, 1, NULL);
+               ret = bgp_update(ain->peer, &bgp_node->p, ain->addpath_rx_id,
+                                ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
+                                BGP_ROUTE_NORMAL, NULL, label, num_labels, 1,
+                                NULL);
 
-               if (ret < 0) {
-                       bgp_unlock_node(bgp_node);
+               if (ret < 0)
                        return;
-               }
        }
 }
 
@@ -413,25 +438,23 @@ static void revalidate_all_routes(void)
 {
        struct bgp *bgp;
        struct listnode *node;
-       struct bgp_node *bgp_node;
 
        for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
-               for (size_t i = 0; i < 2; i++) {
-                       safi_t safi;
-                       afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
+               struct peer *peer;
+               struct listnode *peer_listnode;
 
-                       for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
-                               if (!bgp->rib[afi][safi])
-                                       continue;
+               for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
+
+                       for (size_t i = 0; i < 2; i++) {
+                               safi_t safi;
+                               afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
 
-                               for (bgp_node =
-                                            bgp_table_top(bgp->rib[afi][safi]);
-                                    bgp_node;
-                                    bgp_node = bgp_route_next(bgp_node)) {
-                                       if (bgp_node->info != NULL) {
-                                               revalidate_bgp_node(bgp_node,
-                                                                   afi, safi);
-                                       }
+                               for (safi = SAFI_UNICAST; safi < SAFI_MAX;
+                                    safi++) {
+                                       if (!peer->bgp->rib[afi][safi])
+                                               continue;
+
+                                       bgp_soft_reconfig_in(peer, afi, safi);
                                }
                        }
                }
@@ -442,28 +465,53 @@ static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
                                    const struct pfx_record rec,
                                    const bool added __attribute__((unused)))
 {
-       if (rtr_is_stopping || rtr_is_starting)
+       if (rtr_is_stopping || rtr_is_starting
+           || atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst))
                return;
 
        int retval =
                write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
-       if (retval != sizeof(struct pfx_record))
+       if (retval == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+               atomic_store_explicit(&rtr_update_overflow, 1,
+                                     memory_order_seq_cst);
+
+       else if (retval != sizeof(struct pfx_record))
                RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
 }
 
 static void rpki_init_sync_socket(void)
 {
        int fds[2];
+       const char *msg;
 
        RPKI_DEBUG("initializing sync socket");
        if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
-               RPKI_DEBUG("Could not open rpki sync socket");
-               return;
+               msg = "could not open rpki sync socketpair";
+               goto err;
        }
        rpki_sync_socket_rtr = fds[0];
        rpki_sync_socket_bgpd = fds[1];
+
+       if (set_nonblocking(rpki_sync_socket_rtr) != 0) {
+               msg = "could not set rpki_sync_socket_rtr to non blocking";
+               goto err;
+       }
+
+       if (set_nonblocking(rpki_sync_socket_bgpd) != 0) {
+               msg = "could not set rpki_sync_socket_bgpd to non blocking";
+               goto err;
+       }
+
+
        thread_add_read(bm->master, bgpd_sync_callback, NULL,
                        rpki_sync_socket_bgpd, NULL);
+
+       return;
+
+err:
+       zlog_err("RPKI: %s", msg);
+       abort();
+
 }
 
 static int bgp_rpki_init(struct thread_master *master)
@@ -514,6 +562,7 @@ static int start(void)
 
        rtr_is_stopping = 0;
        rtr_is_starting = 1;
+       rtr_update_overflow = 0;
 
        if (list_isempty(cache_list)) {
                RPKI_DEBUG(
@@ -1210,10 +1259,10 @@ DEFUN_NOSH (rpki_exit,
            "exit",
            "Exit rpki configuration and restart rpki session\n")
 {
-       int ret = reset(false);
+       reset(false);
 
        vty->node = CONFIG_NODE;
-       return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
+       return CMD_SUCCESS;
 }
 
 DEFUN_NOSH (rpki_quit,
index f7eac095463ebb11ab819478d1cf96fafa8378e9..60c2cbd4a483c3e646595ebc4434b2f16badd6ff 100644 (file)
@@ -128,9 +128,9 @@ static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node)
 /*
  * bgp_unlock_node
  */
-static inline struct bgp_node *bgp_unlock_node(struct bgp_node *node)
+static inline void bgp_unlock_node(struct bgp_node *node)
 {
-       return (struct bgp_node *)route_unlock_node(bgp_node_to_rnode(node));
+       route_unlock_node(bgp_node_to_rnode(node));
 }
 
 /*
index fda458cb84f41cebf93aeaa712befd4cb28c1c51..1460a26215bbbd66b6ac2e1598e043dee0165a53 100644 (file)
@@ -2019,7 +2019,7 @@ DEFUN (no_bgp_fast_external_failover,
 }
 
 /* "bgp enforce-first-as" configuration. */
-#if CONFDATE > 20180517
+#if CONFDATE > 20190517
 CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands")
 #endif
 
@@ -10995,7 +10995,7 @@ DEFUN (show_ip_bgp_attr_info,
 }
 
 static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
-                                  afi_t afi, safi_t safi)
+                                  afi_t afi, safi_t safi, uint8_t use_json)
 {
        struct bgp *bgp;
        struct listnode *node;
@@ -11004,64 +11004,148 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
        char *ecom_str;
        vpn_policy_direction_t dir;
 
-       if (name) {
-               bgp = bgp_lookup_by_name(name);
+       if (use_json) {
+               json_object *json = NULL;
+               json_object *json_import_vrfs = NULL;
+               json_object *json_export_vrfs = NULL;
+
+               json = json_object_new_object();
+
+               /* Provide context for the block */
+               json_object_string_add(json, "vrf", name ? name : "default");
+               json_object_string_add(json, "afiSafi",
+                                       afi_safi_print(afi, safi));
+
+               bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
+
                if (!bgp) {
-                       vty_out(vty, "%% No such BGP instance exist\n");
+                       json_object_boolean_true_add(json,
+                                                    "bgpNoSuchInstance");
+                       vty_out(vty, "%s\n",
+                               json_object_to_json_string_ext(
+                                       json,
+                                       JSON_C_TO_STRING_PRETTY));
+                       json_object_free(json);
+
                        return CMD_WARNING;
                }
+
+               if (!CHECK_FLAG(bgp->af_flags[afi][safi],
+                               BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
+                       json_object_string_add(json, "importFromVrfs", "none");
+                       json_object_string_add(json, "importRts", "none");
+               } else {
+                       json_import_vrfs = json_object_new_array();
+
+                       for (ALL_LIST_ELEMENTS_RO(
+                                               bgp->vpn_policy[afi].import_vrf,
+                                               node, vname))
+                               json_object_array_add(json_import_vrfs,
+                                               json_object_new_string(vname));
+
+                       dir = BGP_VPN_POLICY_DIR_FROMVPN;
+                       ecom_str = ecommunity_ecom2str(
+                                       bgp->vpn_policy[afi].rtlist[dir],
+                                       ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+                       json_object_object_add(json, "importFromVrfs",
+                                              json_import_vrfs);
+                       json_object_string_add(json, "importRts", ecom_str);
+
+                       XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
+               }
+
+               if (!CHECK_FLAG(bgp->af_flags[afi][safi],
+                               BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
+                       json_object_string_add(json, "exportToVrfs", "none");
+                       json_object_string_add(json, "routeDistinguisher",
+                                              "none");
+                       json_object_string_add(json, "exportRts", "none");
+               } else {
+                       json_export_vrfs = json_object_new_array();
+
+                       for (ALL_LIST_ELEMENTS_RO(
+                                               bgp->vpn_policy[afi].export_vrf,
+                                               node, vname))
+                               json_object_array_add(json_export_vrfs,
+                                               json_object_new_string(vname));
+                       json_object_object_add(json, "exportToVrfs",
+                                              json_export_vrfs);
+                       json_object_string_add(json, "routeDistinguisher",
+                                  prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
+                                                buf1, RD_ADDRSTRLEN));
+
+                       dir = BGP_VPN_POLICY_DIR_TOVPN;
+                       ecom_str = ecommunity_ecom2str(
+                                              bgp->vpn_policy[afi].rtlist[dir],
+                                              ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+                       json_object_string_add(json, "exportRts", ecom_str);
+
+                       XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
+               }
+
+               vty_out(vty, "%s\n",
+                       json_object_to_json_string_ext(json,
+                                                     JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+
        } else {
-               bgp = bgp_get_default();
+               bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
+
                if (!bgp) {
-                       vty_out(vty,
-                               "%% Default BGP instance does not exist\n");
+                       vty_out(vty, "%% No such BGP instance exist\n");
                        return CMD_WARNING;
                }
-       }
 
-       if (!CHECK_FLAG(bgp->af_flags[afi][safi],
-                       BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
-               vty_out(vty,
-                       "This VRF is not importing %s routes from any other VRF\n",
-                       afi_safi_print(afi, safi));
-       } else {
-               vty_out(vty,
-                       "This VRF is importing %s routes from the following VRFs:\n",
-                       afi_safi_print(afi, safi));
-               for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].import_vrf, node,
-                                         vname)) {
-                       vty_out(vty, "  %s\n", vname);
+               if (!CHECK_FLAG(bgp->af_flags[afi][safi],
+                               BGP_CONFIG_VRF_TO_VRF_IMPORT))
+                       vty_out(vty,
+                    "This VRF is not importing %s routes from any other VRF\n",
+                     afi_safi_print(afi, safi));
+               else {
+                       vty_out(vty,
+                  "This VRF is importing %s routes from the following VRFs:\n",
+                   afi_safi_print(afi, safi));
+
+                       for (ALL_LIST_ELEMENTS_RO(
+                                               bgp->vpn_policy[afi].import_vrf,
+                                               node, vname))
+                               vty_out(vty, "  %s\n", vname);
+
+                       dir = BGP_VPN_POLICY_DIR_FROMVPN;
+                       ecom_str = ecommunity_ecom2str(
+                                              bgp->vpn_policy[afi].rtlist[dir],
+                                              ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+                       vty_out(vty, "Import RT(s): %s\n", ecom_str);
+
+                       XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
                }
-               dir = BGP_VPN_POLICY_DIR_FROMVPN;
-               ecom_str = ecommunity_ecom2str(
-                               bgp->vpn_policy[afi].rtlist[dir],
-                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
-               vty_out(vty, "Import RT(s): %s\n", ecom_str);
-               XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
-       }
 
-       if (!CHECK_FLAG(bgp->af_flags[afi][safi],
-                       BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
-               vty_out(vty,
-                       "This VRF is not exporting %s routes to any other VRF\n",
+               if (!CHECK_FLAG(bgp->af_flags[afi][safi],
+                               BGP_CONFIG_VRF_TO_VRF_EXPORT))
+                       vty_out(vty,
+                      "This VRF is not exporting %s routes to any other VRF\n",
                        afi_safi_print(afi, safi));
-       } else {
-               vty_out(vty,
-                       "This VRF is exporting %s routes to the following VRFs:\n",
+               else {
+                       vty_out(vty,
+                      "This VRF is exporting %s routes to the following VRFs:\n",
                        afi_safi_print(afi, safi));
-               for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].export_vrf, node,
-                                         vname)) {
-                       vty_out(vty, "  %s\n", vname);
+
+                       for (ALL_LIST_ELEMENTS_RO(
+                                               bgp->vpn_policy[afi].export_vrf,
+                                               node, vname))
+                               vty_out(vty, "  %s\n", vname);
+
+                       vty_out(vty, "RD: %s\n",
+                               prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
+                                             buf1, RD_ADDRSTRLEN));
+
+                       dir = BGP_VPN_POLICY_DIR_TOVPN;
+                       ecom_str = ecommunity_ecom2str(
+                                       bgp->vpn_policy[afi].rtlist[dir],
+                                       ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+                       vty_out(vty, "Export RT: %s\n", ecom_str);
+                       XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
                }
-               vty_out(vty, "RD: %s\n",
-                       prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
-                                     buf1, RD_ADDRSTRLEN));
-               dir = BGP_VPN_POLICY_DIR_TOVPN;
-               ecom_str = ecommunity_ecom2str(
-                               bgp->vpn_policy[afi].rtlist[dir],
-                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
-               vty_out(vty, "Emport RT: %s\n", ecom_str);
-               XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
        }
 
        return CMD_SUCCESS;
@@ -11069,20 +11153,22 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
 
 /* "show [ip] bgp route-leak" command.  */
 DEFUN (show_ip_bgp_route_leak,
-       show_ip_bgp_route_leak_cmd,
-       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak",
-       SHOW_STR
-       IP_STR
-       BGP_STR
-       BGP_INSTANCE_HELP_STR
-       BGP_AFI_HELP_STR
-       BGP_SAFI_HELP_STR
-       "Route leaking information\n")
+       show_ip_bgp_route_leak_cmd,
+       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak  [json]",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       BGP_INSTANCE_HELP_STR
+       BGP_AFI_HELP_STR
+       BGP_SAFI_HELP_STR
+       "Route leaking information\n"
+       JSON_STR)
 {
        char *vrf = NULL;
        afi_t afi = AFI_MAX;
        safi_t safi = SAFI_MAX;
 
+       uint8_t uj = use_json(argc, argv);
        int idx = 0;
 
        /* show [ip] bgp */
@@ -11110,7 +11196,7 @@ DEFUN (show_ip_bgp_route_leak,
                return CMD_WARNING;
        }
 
-       return bgp_show_route_leak_vty(vty, vrf, afi, safi);
+       return bgp_show_route_leak_vty(vty, vrf, afi, safi, uj);
 }
 
 static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
@@ -11462,7 +11548,7 @@ DEFUN (bgp_redistribute_ipv4,
        }
 
        bgp_redist_add(bgp, AFI_IP, type, 0);
-       return bgp_redistribute_set(bgp, AFI_IP, type, 0);
+       return bgp_redistribute_set(bgp, AFI_IP, type, 0, false);
 }
 
 ALIAS_HIDDEN(
@@ -11483,6 +11569,7 @@ DEFUN (bgp_redistribute_ipv4_rmap,
        int idx_word = 3;
        int type;
        struct bgp_redist *red;
+       bool changed;
 
        type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
        if (type < 0) {
@@ -11491,8 +11578,8 @@ DEFUN (bgp_redistribute_ipv4_rmap,
        }
 
        red = bgp_redist_add(bgp, AFI_IP, type, 0);
-       bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
-       return bgp_redistribute_set(bgp, AFI_IP, type, 0);
+       changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
+       return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
 }
 
 ALIAS_HIDDEN(
@@ -11516,6 +11603,7 @@ DEFUN (bgp_redistribute_ipv4_metric,
        int type;
        uint32_t metric;
        struct bgp_redist *red;
+       bool changed;
 
        type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
        if (type < 0) {
@@ -11525,8 +11613,8 @@ DEFUN (bgp_redistribute_ipv4_metric,
        metric = strtoul(argv[idx_number]->arg, NULL, 10);
 
        red = bgp_redist_add(bgp, AFI_IP, type, 0);
-       bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
-       return bgp_redistribute_set(bgp, AFI_IP, type, 0);
+       changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
+       return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
 }
 
 ALIAS_HIDDEN(
@@ -11553,6 +11641,7 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric,
        int type;
        uint32_t metric;
        struct bgp_redist *red;
+       bool changed;
 
        type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
        if (type < 0) {
@@ -11562,9 +11651,9 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric,
        metric = strtoul(argv[idx_number]->arg, NULL, 10);
 
        red = bgp_redist_add(bgp, AFI_IP, type, 0);
-       bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
-       bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
-       return bgp_redistribute_set(bgp, AFI_IP, type, 0);
+       changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
+       changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
+       return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
 }
 
 ALIAS_HIDDEN(
@@ -11595,6 +11684,7 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap,
        int type;
        uint32_t metric;
        struct bgp_redist *red;
+       bool changed;
 
        type = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
        if (type < 0) {
@@ -11604,9 +11694,9 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap,
        metric = strtoul(argv[idx_number]->arg, NULL, 10);
 
        red = bgp_redist_add(bgp, AFI_IP, type, 0);
-       bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
-       bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
-       return bgp_redistribute_set(bgp, AFI_IP, type, 0);
+       changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric);
+       changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
+       return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed);
 }
 
 ALIAS_HIDDEN(
@@ -11642,7 +11732,7 @@ DEFUN (bgp_redistribute_ipv4_ospf,
                protocol = ZEBRA_ROUTE_TABLE;
 
        bgp_redist_add(bgp, AFI_IP, protocol, instance);
-       return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
+       return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, false);
 }
 
 ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf, bgp_redistribute_ipv4_ospf_hidden_cmd,
@@ -11669,6 +11759,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap,
        struct bgp_redist *red;
        unsigned short instance;
        int protocol;
+       bool changed;
 
        if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
                protocol = ZEBRA_ROUTE_OSPF;
@@ -11677,8 +11768,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap,
 
        instance = strtoul(argv[idx_number]->arg, NULL, 10);
        red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
-       bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
-       return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
+       changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
+       return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
 }
 
 ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_rmap,
@@ -11709,6 +11800,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
        struct bgp_redist *red;
        unsigned short instance;
        int protocol;
+       bool changed;
 
        if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
                protocol = ZEBRA_ROUTE_OSPF;
@@ -11719,8 +11811,9 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric,
        metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
 
        red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
-       bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
-       return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
+       changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
+                                               metric);
+       return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
 }
 
 ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_metric,
@@ -11754,6 +11847,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
        struct bgp_redist *red;
        unsigned short instance;
        int protocol;
+       bool changed;
 
        if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
                protocol = ZEBRA_ROUTE_OSPF;
@@ -11764,9 +11858,10 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric,
        metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
 
        red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
-       bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
-       bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
-       return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
+       changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
+       changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
+                                               metric);
+       return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
 }
 
 ALIAS_HIDDEN(
@@ -11803,6 +11898,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
        struct bgp_redist *red;
        unsigned short instance;
        int protocol;
+       bool changed;
 
        if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0)
                protocol = ZEBRA_ROUTE_OSPF;
@@ -11813,9 +11909,10 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap,
        metric = strtoul(argv[idx_number_2]->arg, NULL, 10);
 
        red = bgp_redist_add(bgp, AFI_IP, protocol, instance);
-       bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric);
-       bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
-       return bgp_redistribute_set(bgp, AFI_IP, protocol, instance);
+       changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol,
+                                               metric);
+       changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
+       return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed);
 }
 
 ALIAS_HIDDEN(
@@ -11923,7 +12020,7 @@ DEFUN (bgp_redistribute_ipv6,
        }
 
        bgp_redist_add(bgp, AFI_IP6, type, 0);
-       return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
+       return bgp_redistribute_set(bgp, AFI_IP6, type, 0, false);
 }
 
 DEFUN (bgp_redistribute_ipv6_rmap,
@@ -11939,6 +12036,7 @@ DEFUN (bgp_redistribute_ipv6_rmap,
        int idx_word = 3;
        int type;
        struct bgp_redist *red;
+       bool changed;
 
        type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
        if (type < 0) {
@@ -11947,8 +12045,8 @@ DEFUN (bgp_redistribute_ipv6_rmap,
        }
 
        red = bgp_redist_add(bgp, AFI_IP6, type, 0);
-       bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
-       return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
+       changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
+       return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
 }
 
 DEFUN (bgp_redistribute_ipv6_metric,
@@ -11965,6 +12063,7 @@ DEFUN (bgp_redistribute_ipv6_metric,
        int type;
        uint32_t metric;
        struct bgp_redist *red;
+       bool changed;
 
        type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
        if (type < 0) {
@@ -11974,8 +12073,8 @@ DEFUN (bgp_redistribute_ipv6_metric,
        metric = strtoul(argv[idx_number]->arg, NULL, 10);
 
        red = bgp_redist_add(bgp, AFI_IP6, type, 0);
-       bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
-       return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
+       changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
+       return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
 }
 
 DEFUN (bgp_redistribute_ipv6_rmap_metric,
@@ -11995,6 +12094,7 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
        int type;
        uint32_t metric;
        struct bgp_redist *red;
+       bool changed;
 
        type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
        if (type < 0) {
@@ -12004,9 +12104,10 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
        metric = strtoul(argv[idx_number]->arg, NULL, 10);
 
        red = bgp_redist_add(bgp, AFI_IP6, type, 0);
-       bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
-       bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric);
-       return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
+       changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
+       changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP6, type,
+                                               metric);
+       return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
 }
 
 DEFUN (bgp_redistribute_ipv6_metric_rmap,
@@ -12026,6 +12127,7 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
        int type;
        uint32_t metric;
        struct bgp_redist *red;
+       bool changed;
 
        type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text);
        if (type < 0) {
@@ -12035,9 +12137,10 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
        metric = strtoul(argv[idx_number]->arg, NULL, 10);
 
        red = bgp_redist_add(bgp, AFI_IP6, type, 0);
-       bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST, metric);
-       bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
-       return bgp_redistribute_set(bgp, AFI_IP6, type, 0);
+       changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST,
+                                               metric);
+       changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg);
+       return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
 }
 
 DEFUN (no_bgp_redistribute_ipv6,
index c7049ef213363f2e5eba06919956c6533e7cfb5c..43afc317e9b30e9a1ed4b19d2d9deda01842ce64 100644 (file)
@@ -1576,8 +1576,14 @@ static void bgp_redist_del(struct bgp *bgp, afi_t afi, uint8_t type,
 
 /* Other routes redistribution into BGP. */
 int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
-                        unsigned short instance)
+                        unsigned short instance, bool changed)
 {
+       /* If redistribute options are changed call
+        * bgp_redistribute_unreg() to reset the option and withdraw
+        * the routes
+        */
+       if (changed)
+               bgp_redistribute_unreg(bgp, afi, type, instance);
 
        /* Return if already redistribute flag is set. */
        if (instance) {
index e3c88b9db664712e4eab521a4faef8da42214cef..546d72402af819ef288f9a4a0914cfae50e56cb7 100644 (file)
@@ -51,7 +51,8 @@ extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, uint8_t,
                                            unsigned short);
 extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t,
                                         unsigned short);
-extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short);
+extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short,
+                               bool changed);
 extern int bgp_redistribute_resend(struct bgp *, afi_t, int, unsigned short);
 extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *);
 extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t,
index c8b4e3acf53e3035f1b925040c48775067c7ca1f..7ff5053ce37a8907e65c299acdb1aea15847b981 100644 (file)
@@ -3187,15 +3187,16 @@ int bgp_delete(struct bgp *bgp)
                                .import_redirect_rtlist);
                bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
        }
-       /* Remove visibility via the master list - there may however still be
-        * routes to be processed still referencing the struct bgp.
-        */
-       listnode_delete(bm->bgp, bgp);
 
        /* Deregister from Zebra, if needed */
        if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
                bgp_zebra_instance_deregister(bgp);
 
+       /* Remove visibility via the master list - there may however still be
+        * routes to be processed still referencing the struct bgp.
+        */
+       listnode_delete(bm->bgp, bgp);
+
        /* Free interfaces in this instance. */
        bgp_if_finish(bgp);
 
@@ -6631,17 +6632,6 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, uint8_t use_json,
        time_t uptime1, epoch_tbuf;
        struct tm *tm;
 
-       /* Check buffer length. */
-       if (len < BGP_UPTIME_LEN) {
-               if (!use_json) {
-                       zlog_warn("peer_uptime (): buffer shortage %lu",
-                                 (unsigned long)len);
-                       /* XXX: should return status instead of buf... */
-                       snprintf(buf, len, "<error> ");
-               }
-               return buf;
-       }
-
        /* If there is no connection has been done before print `never'. */
        if (uptime2 == 0) {
                if (use_json) {
@@ -7356,7 +7346,7 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
 }
 
 /* clang-format off */
-#if CONFDATE > 20180517
+#if CONFDATE > 20190517
 CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write")
 #endif
 /* clang-format on */
index 96e201cc4210dc146663e3174d8e9c195356665b..be1c2763a1ef5b30d88b975b040dfeba2543043e 100755 (executable)
@@ -382,7 +382,7 @@ AC_ARG_ENABLE(bgp-vnc,
 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)]))
+  AS_HELP_STRING([--enable-snmp], [enable SNMP support for agentx]))
 AC_ARG_ENABLE(zeromq,
   AS_HELP_STRING([--enable-zeromq], [enable ZeroMQ handler (libfrrzmq)]))
 AC_ARG_WITH(libpam,
@@ -418,8 +418,6 @@ AC_ARG_ENABLE(rusage,
   AS_HELP_STRING([--disable-rusage], [disable using getrusage]))
 AC_ARG_ENABLE(gcc_ultra_verbose,
   AS_HELP_STRING([--enable-gcc-ultra-verbose], [enable ultra verbose GCC warnings]))
-AC_ARG_ENABLE(linux24_tcp_md5,
-  AS_HELP_STRING([--enable-linux24-tcp-md5], [enable support for old, Linux-2.4 RFC2385 patch]))
 AC_ARG_ENABLE(backtrace,
   AS_HELP_STRING([--disable-backtrace,], [disable crash backtraces (default autodetect)]))
 AC_ARG_ENABLE(time-check,
@@ -644,10 +642,6 @@ AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$have_protobuf" = "xyes"])
 # End of logic for protobuf support.
 #
 
-if test "${enable_linux24_tcp_md5}" = "yes"; then
-  AC_DEFINE(HAVE_TCP_MD5_LINUX24,,Old Linux 2.4 TCP MD5 Signature Patch)
-fi
-
 AC_MSG_CHECKING(if zebra should be configurable to send Route Advertisements)
 if test "${enable_rtadv}" != "no"; then
   AC_MSG_RESULT(yes)
@@ -1496,14 +1490,13 @@ int main(void);
      yes)
       SNMP_METHOD=agentx
       ;;
-     smux|agentx)
+     agentx)
       SNMP_METHOD="${enable_snmp}"
       ;;
      *)
-      AC_MSG_ERROR([--enable-snmp given with an unknown method (${enable_snmp}). Use smux or agentx])
+      AC_MSG_ERROR([--enable-snmp given with an unknown method (${enable_snmp}). Use yes or agentx])
       ;;
    esac
-   AH_TEMPLATE([SNMP_SMUX], [Use SNMP SMUX to interface with snmpd])
    AH_TEMPLATE([SNMP_AGENTX], [Use SNMP AgentX to interface with snmpd])
    AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd)
 fi
index 3a6c80297eb5a929e895a38f36e701755dbbb9e0..7495db89cb7bb7b711a962d26f6c15685733dac6 100755 (executable)
@@ -10,7 +10,6 @@
 WANT_LDP ?= 1
 WANT_PIM ?= 1
 WANT_OSPFAPI ?= 1
-WANT_TCP_ZEBRA ?= 0
 WANT_BGP_VNC ?= 1
 WANT_CUMULUS_MODE ?= 0
 WANT_MULTIPATH ?= 1
@@ -65,12 +64,6 @@ else
   USE_OSPFAPI=--enable-ospfapi=no
 endif
 
-ifeq ($(WANT_TCP_ZEBRA),1)
-  USE_TCP_ZEBRA=--enable-tcp-zebra
-else
-  USE_TCP_ZEBRA=--disable-tcp-zebra
-endif
-
 ifeq ($(WANT_BGP_VNC), 1)
   USE_BGP_VNC=--enable-bgp-vnc=yes
 else
@@ -123,7 +116,6 @@ override_dh_auto_configure:
                $(USE_OSPFAPI) \
                $(USE_MULTIPATH) \
                $(USE_LDP) \
-               $(USE_TCP_ZEBRA) \
                --enable-fpm \
                $(USE_FRR_USER) $(USE_FRR_GROUP) \
                $(USE_FRR_VTY_GROUP) \
@@ -162,12 +154,8 @@ override_dh_auto_install:
        mkdir -p debian/tmp/etc/frr/
        perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
 
-       # installing the Frr specific SNMP MIB
-ifeq ($(WANT_SNMP), 1)
-       install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB
-else
+       # leftover from previously shipping SMUX client OID MIB
        mkdir -p debian/tmp/usr/share/snmp/mibs
-endif
 
        # cleaning .la files
        sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
index f7468d6f791fc16218dcc9e1d86e78af2a957f30..c955d0c9454a7066f1ed06dc1e3d7c6368e8b253 100755 (executable)
@@ -10,7 +10,6 @@
 WANT_LDP ?= 1
 WANT_PIM ?= 1
 WANT_OSPFAPI ?= 1
-WANT_TCP_ZEBRA ?= 0
 WANT_BGP_VNC ?= 1
 WANT_CUMULUS_MODE ?= 0
 WANT_MULTIPATH ?= 1
@@ -75,12 +74,6 @@ else
   USE_OSPFAPI=--enable-ospfapi=no
 endif
 
-ifeq ($(WANT_TCP_ZEBRA),1)
-  USE_TCP_ZEBRA=--enable-tcp-zebra
-else
-  USE_TCP_ZEBRA=--disable-tcp-zebra
-endif
-
 ifeq ($(WANT_BGP_VNC), 1)
   USE_BGP_VNC=--enable-bgp-vnc=yes
 else
@@ -152,7 +145,6 @@ override_dh_auto_configure:
                $(USE_OSPFAPI) \
                $(USE_MULTIPATH) \
                $(USE_LDP) \
-               $(USE_TCP_ZEBRA) \
                --enable-fpm \
                $(USE_FRR_USER) $(USE_FRR_GROUP) \
                $(USE_FRR_VTY_GROUP) \
@@ -196,12 +188,8 @@ override_dh_auto_install:
        mkdir -p debian/tmp/etc/frr/
        perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
 
-       # installing the Frr specific SNMP MIB
-ifeq ($(WANT_SNMP), 1)
-       install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB
-else
+       # leftover from previously shipping SMUX client OID MIB
        mkdir -p debian/tmp/usr/share/snmp/mibs/
-endif
 
        # cleaning .la files
        sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
index c1cb865490f3a2bad277cb66e1226e3019c57a1b..811d45bc0b065432c616c8b9577fca6997d1e563 100755 (executable)
@@ -10,7 +10,6 @@
 WANT_LDP ?= 1
 WANT_PIM ?= 1
 WANT_OSPFAPI ?= 1
-WANT_TCP_ZEBRA ?= 0
 WANT_BGP_VNC ?= 1
 WANT_CUMULUS_MODE ?= 0
 WANT_MULTIPATH ?= 1
@@ -75,12 +74,6 @@ else
   USE_OSPFAPI=--enable-ospfapi=no
 endif
 
-ifeq ($(WANT_TCP_ZEBRA),1)
-  USE_TCP_ZEBRA=--enable-tcp-zebra
-else
-  USE_TCP_ZEBRA=--disable-tcp-zebra
-endif
-
 ifeq ($(WANT_BGP_VNC), 1)
   USE_BGP_VNC=--enable-bgp-vnc=yes
 else
@@ -152,7 +145,6 @@ override_dh_auto_configure:
                $(USE_OSPFAPI) \
                $(USE_MULTIPATH) \
                $(USE_LDP) \
-               $(USE_TCP_ZEBRA) \
                --enable-fpm \
                $(USE_FRR_USER) $(USE_FRR_GROUP) \
                $(USE_FRR_VTY_GROUP) \
@@ -194,12 +186,8 @@ override_dh_auto_install:
        mkdir -p debian/tmp/etc/frr/
        perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample*
 
-       # installing the Frr specific SNMP MIB
-ifeq ($(WANT_SNMP), 1)
-       install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB
-else
+       # leftover from previously shipping SMUX client OID MIB
        mkdir -p debian/tmp/usr/share/snmp/mibs/
-endif
 
        # cleaning .la files
        sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la
index 6f72585485470fddf026dc497912baaf4fd84bd6..f4218650545f93429e57dad8dc38bc02e0869d65 100644 (file)
@@ -193,6 +193,7 @@ EXTRA_DIST = frr-sphinx.mk \
        developer/index.rst \
        developer/ldpd-basic-test-setup.md \
        developer/library.rst \
+       developer/logging.rst \
        developer/Makefile.in \
        developer/maintainer-release-build.rst \
        developer/memtypes.rst \
index f6efa33051d81ed47b5c2a25f7730e4733a3e763..77b2f229b785a02e7fb2c871dbec5773df312b9d 100644 (file)
@@ -7,6 +7,7 @@ Library Facilities (libfrr)
 .. toctree::
    :maxdepth: 2
 
+   logging
    memtypes
    hooks
    cli
diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst
new file mode 100644 (file)
index 0000000..4338d90
--- /dev/null
@@ -0,0 +1,131 @@
+Developer's Guide to Logging
+============================
+
+One of the most frequent decisions to make while writing code for FRR is what
+to log, what level to log it at, and when to log it.  Here is a list of
+recommendations for these decisions.
+
+
+Errors and warnings
+-------------------
+
+If it is something that the user will want to look at and maybe do
+something, it is either an **error** or a **warning**.
+
+We're expecting that warnings and errors are in some way visible to the
+user (in the worst case by looking at the log after the network broke, but
+maybe by a syslog collector from all routers.)  Therefore, anything that
+needs to get the user in the loop—and only these things—are warnings or
+errors.
+
+Note that this doesn't neccessarily mean the user needs to fix something in
+the FRR instance.  It also includes when we detect something else needs
+fixing, for example another router, the system we're running on, or the
+configuration.  The common point is that the user should probably do
+*something*.
+
+Deciding between a warning and an error is slightly less obvious; the rule
+of thumb here is that an error will cause considerable fallout beyond its
+direct effect.  Closing a BGP session due to a malformed update is an error
+since all routes from the peer are dropped; discarding one route because
+its attributes don't make sense is a warning.
+
+This also loosely corresponds to the kind of reaction we're expecting from
+the user.  An error is likely to need immediate response while a warning
+might be snoozed for a bit and addressed as part of general maintenance.
+If a problem will self-repair (e.g. by retransmits), it should be a
+warning—unless the impact until that self-repair is very harsh.
+
+Examples for warnings:
+
+* a BGP update, LSA or LSP could not be processed, but operation is
+  proceeding and the broken pieces are likely to self-fix later
+* some kind of controller cannot be reached, but we can work without it
+* another router is using some unknown or unsupported capability
+
+Examples for errors:
+
+* dropping a BGP session due to malformed data
+* a socket for routing protocol operation cannot be opened
+* desynchronization from network state because something went wrong
+* *everything that we as developers would really like to be notified about,
+  i.e. some assumption in the code isn't holding up*
+
+
+Informational messages
+----------------------
+
+Anything that provides introspection to the user during normal operation
+is an **info** message.
+
+This includes all kinds of operational state transitions and events,
+especially if they might be interesting to the user during the course of
+figuring out a warning or an error.
+
+By itself, these messages should mostly be statements of fact.  They might
+indicate the order and relationship in which things happened.  Also covered
+are conditions that might be "operational issues" like a link failure due
+to an unplugged cable.  If it's pretty much the point of running a routing
+daemon for, it's not a warning or an error, just business as usual.
+
+The user should be able to see the state of these bits from operational
+state output, i.e. `show interface` or `show foobar neighbors`.  The log
+message indicating the change may have been printed weeks ago, but the
+state can always be viewed.  (If some state change has an info message but
+no "show" command, maybe that command needs to be added.)
+
+Examples:
+
+* all kinds of up/down state changes
+
+  * interface coming up or going down
+  * addresses being added or deleted
+  * peers and neighbors coming up or going down
+
+* rejection of some routes due to user-configured route maps
+* backwards compatibility handling because another system on the network
+  has a different or smaller feature set
+
+.. note::
+   The previously used **notify** priority is replaced with *info* in all
+   cases.  We don't currently have a well-defined use case for it.
+
+
+Debug messages and asserts
+--------------------------
+
+Everything that is only interesting on-demand, or only while developing,
+is a **debug** message.  It might be interesting to the user for a
+particularly evasive issue, but in general these are details that an
+average user might not even be able to make sense of.
+
+Most (or all?) debug messages should be behind a `debug foobar` category
+switch that controls which subset of these messages is currently
+interesting and thus printed.  If a debug message doesn't have such a
+guard, there should be a good explanation as to why.
+
+Conversely, debug messages are the only thing that should be guarded by
+these switches.  Neither info nor warning or error messages should be
+hidden in this way.
+
+**Asserts** should only be used as pretty crashes.  We are expecting that
+asserts remain enabled in production builds, but please try to not use
+asserts in a way that would cause a security problem if the assert wasn't
+there (i.e. don't use them for length checks.)
+
+The purpose of asserts is mainly to help development and bug hunting.  If
+the daemon crashes, then having some more information is nice, and the
+assert can provide crucial hints that cut down on the time needed to track
+an issue.  That said, if the issue can be reasonably handled and/or isn't
+going to crash the daemon, it shouldn't be an assert.
+
+For anything else where internal constraints are violated but we're not
+breaking due to it, it's an error instead (not a debug.)  These require
+"user action" of notifying the developers.
+
+Examples:
+
+* mismatched :code:`prev`/:code:`next` pointers in lists
+* some field that is absolutely needed is :code:`NULL`
+* any other kind of data structure corruption that will cause the daemon
+  to crash sooner or later, one way or another
index 3d64b671155067cf3abe8d9750fc77c0fd968c70..1bf31e96244f5c4c893f398875b98b021813c770 100644 (file)
@@ -102,14 +102,6 @@ Zebra Protocol Commands
 +-----------------------------------+-------+
 | ZEBRA_INTERFACE_DOWN              | 6     |
 +-----------------------------------+-------+
-| ZEBRA_IPV4_ROUTE_ADD              | 7     |
-+-----------------------------------+-------+
-| ZEBRA_IPV4_ROUTE_DELETE           | 8     |
-+-----------------------------------+-------+
-| ZEBRA_IPV6_ROUTE_ADD              | 9     |
-+-----------------------------------+-------+
-| ZEBRA_IPV6_ROUTE_DELETE           | 10    |
-+-----------------------------------+-------+
 | ZEBRA_REDISTRIBUTE_ADD            | 11    |
 +-----------------------------------+-------+
 | ZEBRA_REDISTRIBUTE_DELETE         | 12    |
index 1e99010505b405d4e142fb22a45b2ce6e316c6b0..5fff6fca6651cd6014b6ca42da0b745ce1357269 100644 (file)
@@ -126,7 +126,7 @@ These following options control the daemon's VTY (interactive command line) inte
       staticd         2616
       bfdd            2617
 
-   Port 2607 is used for ospfd's Opaque LSA API, while port 2600 is used for the (insecure) TCP-ZEBRA interface.
+   Port 2607 is used for ospfd's Opaque LSA API.
 
 .. option:: --vty_socket vty-path
 
index e95dd26e84bbacddf0f91514dcc3bc891396baa7..c62835c7701f3588a63902459e0d92b0f775e5ce 100644 (file)
@@ -6,6 +6,7 @@
 .. toctree::
    :maxdepth: 2
 
+   bfdd
    bgpd
    eigrpd
    isisd
index 0d871c961a898405fd9d11f1a6cdd8d713869cce..3143f8bb65300ca05d0657e3d1bdfadfe7dc039a 100644 (file)
@@ -6,3 +6,50 @@ div.body {
 pre {
     background-color: #e2e2e2;
 }
+
+/* styling for the protocols vs. OS table in overview.rst */
+/* first, general bits */
+div.body td.mark {
+    text-align: center;
+    border-left: 1px solid #ccc;
+}
+table.mark th {
+    text-align: center;
+}
+table.mark td {
+    vertical-align: middle;
+}
+table.mark td[colspan="7"] {
+    text-align: center;
+    padding-top: 8pt;
+    padding-bottom: 2pt;
+}
+table.mark cite {
+    font-weight: bold;
+}
+
+/* individual Y/N/... cells */
+td.mark {
+    width: 4.5em;
+}
+td.mark span {
+    display: block;
+    padding: 3px 1px;
+    border: 1px dotted #666;
+    width: 36pt;
+    margin:auto;
+}
+span.mark-y   { background-color: #77ffaa; }
+span.mark-geq { background-color: #aaff77; }
+span.mark-cp  { background-color: #ffbb55; }
+span.mark-n   { background-color: #ff8877; }
+span.mark-dag { background-color: #ffee99; font-size: 8pt; padding:0px 1px; border-top:0px; }
+
+/* for the legend below */
+li span.mark {
+    display: inline-block;
+    padding: 3px 1px;
+    border: 1px dotted #666;
+    width: 36pt;
+    text-align: center;
+}
diff --git a/doc/user/_static/overrides.js b/doc/user/_static/overrides.js
new file mode 100644 (file)
index 0000000..73bf612
--- /dev/null
@@ -0,0 +1,13 @@
+/* special styling for the protocols vs. OS table in overview.rst
+ *
+ * unfortunately this can't be done in straight CSS because we're changing
+ * the styling on the parent.
+ */
+$(document).ready(function() {
+    $("span.mark:contains('Y')" ).addClass("mark-y"  ).parent("td").addClass("mark");
+    $("span.mark:contains('≥')" ).addClass("mark-geq").parent("td").addClass("mark");
+    $("span.mark:contains('N')" ).addClass("mark-n"  ).parent("td").addClass("mark");
+    $("span.mark:contains('CP')").addClass("mark-cp" ).parent("td").addClass("mark");
+    $("span.mark:contains('†')" ).addClass("mark-dag").parent("td").addClass("mark");
+    $('td.mark').parents('table').addClass("mark").children('colgroup').remove();
+});
index 8eb9efe789e9b357fbc8e6cf375aef75bc687a32..986d1494a5476a782c2cb507bea660f61749082b 100644 (file)
@@ -179,7 +179,7 @@ The following commands are available inside the BGP configuration node.
 .. _bfd-ospf-peer-config:
 
 OSPF BFD Configuration
----------------------
+----------------------
 
 The following commands are available inside the interface configuration node.
 
@@ -364,7 +364,7 @@ You can inspect the current BFD peer status with the following commands:
                            Echo transmission interval: 50ms
 
    frr# show bfd peer 192.168.0.1 json
-{"multihop":false,"peer":"192.168.0.1","id":1,"remote-id":1,"status":"up","uptime":161,"diagnostic":"ok","remote-diagnostic":"ok","receive-interval":300,"transmit-interval":300,"echo-interval":50,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-interval":50}
+   {"multihop":false,"peer":"192.168.0.1","id":1,"remote-id":1,"status":"up","uptime":161,"diagnostic":"ok","remote-diagnostic":"ok","receive-interval":300,"transmit-interval":300,"echo-interval":50,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-interval":50}
 
 
 You can also inspect peer session counters with the following commands:
@@ -402,4 +402,4 @@ You can also inspect peer session counters with the following commands:
                 Zebra notifications: 4
 
    frr# show bfd peer 192.168.0.1 counters json
-{"multihop":false,"peer":"192.168.0.1","control-packet-input":348,"control-packet-output":685,"echo-packet-input":6815,"echo-packet-output":6816,"session-up":1,"session-down":0,"zebra-notifications":4}
+   {"multihop":false,"peer":"192.168.0.1","control-packet-input":348,"control-packet-output":685,"echo-packet-input":6815,"echo-packet-output":6816,"session-up":1,"session-down":0,"zebra-notifications":4}
index f1209c21728c04fb0ea827164a5892231c8ac174..2cea24a8bd4b197a9ca6059c9759d05934269ff9 100644 (file)
@@ -1011,6 +1011,75 @@ is 4 octet long. The following format is used to define the community value.
 ``internet``
    ``internet`` represents well-known communities value 0.
 
+``graceful-shutdown``
+   ``graceful-shutdown`` represents well-known communities value
+   ``GRACEFUL_SHUTDOWN`` ``0xFFFF0000`` ``65535:0``. :rfc:`8326` implements
+   the purpose Graceful BGP Session Shutdown to reduce the amount of
+   lost traffic when taking BGP sessions down for maintainance. The use
+   of the community needs to be supported from your peers side to
+   actually have any effect.
+
+``accept-own``
+   ``accept-own`` represents well-known communities value ``ACCEPT_OWN``
+   ``0xFFFF0001`` ``65535:1``. :rfc:`7611` implements a way to signal
+   to a router to accept routes with a local nexthop address. This
+   can be the case when doing policing and having traffic having a
+   nexthop located in another VRF but still local interface to the
+   router. It is recommended to read the RFC for full details.
+
+``route-filter-translated-v4``
+   ``route-filter-translated-v4`` represents well-known communities value
+   ``ROUTE_FILTER_TRANSLATED_v4`` ``0xFFFF0002`` ``65535:2``.
+
+``route-filter-v4``
+   ``route-filter-v4`` represents well-known communities value
+   ``ROUTE_FILTER_v4`` ``0xFFFF0003`` ``65535:3``.
+
+``route-filter-translated-v6``
+   ``route-filter-translated-v6`` represents well-known communities value
+   ``ROUTE_FILTER_TRANSLATED_v6`` ``0xFFFF0004`` ``65535:4``.
+
+``route-filter-v6``
+   ``route-filter-v6`` represents well-known communities value
+   ``ROUTE_FILTER_v6`` ``0xFFFF0005`` ``65535:5``.
+
+``llgr-stale``
+   ``llgr-stale`` represents well-known communities value ``LLGR_STALE``
+   ``0xFFFF0006`` ``65535:6``.
+   Assigned and intented only for use with routers supporting the
+   Long-lived Graceful Restart Capability  as described in
+   :rfc:`draft-uttaro-idr-bgp-persistence`.
+   Routers recieving routes with this community may (depending on
+   implementation) choose allow to reject or modify routes on the
+   presence or absence of this community.
+
+``no-llgr``
+   ``no-llgr`` represents well-known communities value ``NO_LLGR``
+   ``0xFFFF0007`` ``65535:7``.
+   Assigned and intented only for use with routers supporting the
+   Long-lived Graceful Restart Capability  as described in
+   :rfc:`draft-uttaro-idr-bgp-persistence`.
+   Routers recieving routes with this community may (depending on
+   implementation) choose allow to reject or modify routes on the
+   presence or absence of this community.
+
+``accept-own-nexthop``
+   ``accept-own-nexthop`` represents well-known communities value
+   ``accept-own-nexthop`` ``0xFFFF0008`` ``65535:8``.
+   :rfc:`draft-agrewal-idr-accept-own-nexthop` describes
+   how to tag and label VPN routes to be able to send traffic between VRFs
+   via an internal layer 2 domain on the same PE device. Refer to
+   :rfc:`draft-agrewal-idr-accept-own-nexthop` for full details.
+
+``blackhole``
+   ``blackhole`` represents well-known communities value ``BLACKHOLE``
+   ``0xFFFF029A`` ``65535:666``. :rfc:`7999` documents sending prefixes to
+   EBGP peers and upstream for the purpose of blackholing traffic.
+   Prefixes tagged with the this community should normally not be
+   re-advertised from neighbors of the originating network. It is
+   recommended upon receiving prefixes tagged with this community to
+   add ``NO_EXPORT`` and ``NO_ADVERTISE``.
+
 ``no-export``
    ``no-export`` represents well-known communities value ``NO_EXPORT``
    ``0xFFFFFF01``. All routes carry this value must not be advertised to
@@ -1030,6 +1099,11 @@ is 4 octet long. The following format is used to define the community value.
    it is considered as external BGP peer, so the route will not be announced to
    the peer.
 
+``no-peer``
+   ``no-peer`` represents well-known communities value ``NOPEER``
+   ``0xFFFFFF04``  ``65535:65284``. :rfc:`3765` is used to communicate to
+   another network how the originating network want the prefix propagated.
+
 When the communities attribute is received duplicate community values in the
 attribute are ignored and value is sorted in numerical order.
 
index 28081bca7d52378eb7ced343f046fae731d3312a..2231989fe51713dc5960c3c93d11124e54dbe16c 100644 (file)
@@ -358,6 +358,7 @@ def setup(app):
     app.add_object_type('clicmd', 'clicmd')
     # css overrides for HTML theme
     app.add_stylesheet('overrides.css')
+    app.add_javascript('overrides.js')
     # load Pygments lexer for FRR config syntax
     #
     # NB: in Pygments 2.2+ this can be done with `load_lexer_from_file`, but we
index 369f17dcba1f8d18a0a46bc673badc13c6b3a960..51bd6228e3eb227deee6d4bb3dd3bf538035ac46 100644 (file)
@@ -5,12 +5,12 @@ Overview
 ********
 
 `FRR`_ is a routing software package that provides TCP/IP based routing
-services with routing protocols support such as RIPv1, RIPv2, RIPng, OSPFv2,
-OSPFv3, IS-IS, BGP-4, and BGP-4+ (:ref:`supported-rfcs`). FRR also supports
+services with routing protocols support such as BGP, RIP, OSPF, IS-IS and more
+(see :ref:`supported-protocols`). FRR also supports
 special BGP Route Reflector and Route Server behavior.  In addition to
 traditional IPv4 routing protocols, FRR also supports IPv6 routing protocols.
-With SNMP daemon which supports SMUX and AgentX protocol, FRR provides routing
-protocol MIBs (:ref:`snmp-support`).
+With an SNMP daemon that supports the AgentX protocol, FRR provides routing
+protocol MIB read-only access (:ref:`snmp-support`).
 
 FRR uses an advanced software architecture to provide you with a high quality,
 multi server routing engine. FRR has an interactive user interface for each
@@ -150,27 +150,93 @@ Recent versions of the following compilers are well tested:
 
 .. _supported-protocols:
 
-Supported Protocols & RFCs
-==========================
-
-The following well-known protocols are supported:
-
-- BGP
-- Babel
-- EIGRP
-- IS-IS
-- LDP
-- NHRP
-- OSPFv2
-- OSPFv3
-- PIM
-- RIP
-- RIPNG
-
-The following technologies are supported as well:
-
-- PBR (Policy Based Routing)
-- VNC (Virtual Network Control)
+Supported Protocols vs. Platform
+================================
+
+The following table lists all protocols cross-refrenced to all operating
+systems that have at least CI build tests.  Note that for features, only
+features with system dependencies are included here.
+
+.. role:: mark
+
+.. comment - the :mark:`X` pieces mesh with a little bit of JavaScript and
+   CSS in _static/overrides.{js,css} respectively.  The JS code looks at the
+   presence of the 'Y' 'N' '≥' '†' or 'CP' strings.  This seemed to be the
+   best / least intrusive way of getting a nice table in HTML.  The table
+   will look somewhat shoddy on other sphinx targets like PDF or info (but
+   should still be readable.)
+
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| Daemon / Feature                  | Linux          | OpenBSD      | FreeBSD    | NetBSD     | Solaris    |
++==+================================+================+==============+============+============+============+
+| FRR Core                                                                                                 |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `zebra`                           | :mark:`Y`      | :mark:`Y`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | VRF                            | :mark:`≥4.8`   | :mark:`N`    | :mark:`N`  | :mark:`N`  | :mark:`N`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | MPLS                           | :mark:`≥4.5`   | :mark:`Y`    | :mark:`N`  | :mark:`N`  | :mark:`N`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `pbrd` (Policy Routing)           | :mark:`Y`      | :mark:`N`    | :mark:`N`  | :mark:`N`  | :mark:`N`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| WAN / Carrier protocols                                                                                  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `bgpd` (BGP)                      | :mark:`Y`      | :mark:`Y`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | VRF / L3VPN                    | :mark:`≥4.8`   | :mark:`CP`   | :mark:`CP` | :mark:`CP` | :mark:`CP` |
+|  |                                | :mark:`†4.3`   |              |            |            |            |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | EVPN                           | :mark:`≥4.18`  | :mark:`CP`   | :mark:`CP` | :mark:`CP` | :mark:`CP` |
+|  |                                | :mark:`†4.9`   |              |            |            |            |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | VNC (Virtual Network Control)  | :mark:`CP`     | :mark:`CP`   | :mark:`CP` | :mark:`CP` | :mark:`CP` |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | Flowspec                       | :mark:`CP`     | :mark:`CP`   | :mark:`CP` | :mark:`CP` | :mark:`CP` |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `ldpd` (LDP)                      | :mark:`≥4.5`   | :mark:`Y`    | :mark:`N`  | :mark:`N`  | :mark:`N`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | VPWS / PW                      | :mark:`N`      | :mark:`≥5.8` | :mark:`N`  | :mark:`N`  | :mark:`N`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | VPLS                           | :mark:`N`      | :mark:`≥5.8` | :mark:`N`  | :mark:`N`  | :mark:`N`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `nhrpd` (NHRP)                    | :mark:`Y`      | :mark:`N`    | :mark:`N`  | :mark:`N`  | :mark:`N`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| Link-State Routing                                                                                       |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `ospfd` (OSPFv2)                  | :mark:`Y`      | :mark:`Y`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | Segment Routing                | :mark:`≥4.12`  | :mark:`N`    | :mark:`N`  | :mark:`N`  | :mark:`N`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `ospf6d` (OSPFv3)                 | :mark:`Y`      | :mark:`Y`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `isisd` (IS-IS)                   | :mark:`Y`      | :mark:`Y`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| Distance-Vector Routing                                                                                  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `ripd` (RIPv2)                    | :mark:`Y`      | :mark:`Y`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `ripngd` (RIPng)                  | :mark:`Y`      | :mark:`Y`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `babeld` (BABEL)                  | :mark:`Y`      | :mark:`Y`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `eigrpd` (EIGRP)                  | :mark:`Y`      | :mark:`Y`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| Multicast Routing                                                                                        |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+| `pimd` (PIM)                      | :mark:`≥4.18`  | :mark:`N`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | SSM (Source Specific)          | :mark:`Y`      | :mark:`N`    | :mark:`Y`  | :mark:`Y`  | :mark:`Y`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+|  | ASM (Any Source)               | :mark:`Y`      | :mark:`N`    | :mark:`N`  | :mark:`N`  | :mark:`N`  |
++--+--------------------------------+----------------+--------------+------------+------------+------------+
+
+The indicators have the following semantics:
+
+* :mark:`Y` - daemon/feature fully functional
+* :mark:`≥X.X` - fully functional with kernel version X.X or newer
+* :mark:`†X.X` - restricted functionality or impaired performance with kernel version X.X or newer
+* :mark:`CP` - control plane only (i.e. BGP route server / route reflector)
+* :mark:`N` - daemon/feature not supported by operating system
 
 .. _supported-rfcs:
 
index 38918ff250f34e967777574940016087e36141cd..5579969c0e00f035d3c8e6d07844ae299c8a57a8 100644 (file)
@@ -7,8 +7,8 @@ SNMP Support
 :abbr:`SNMP (Simple Network Managing Protocol)` is a widely implemented feature
 for collecting network information from router and/or host. FRR itself does
 not support SNMP agent (server daemon) functionality but is able to connect to
-a SNMP agent using the SMUX protocol (:rfc:`1227`) or the AgentX protocol
-(:rfc:`2741`) and make the routing protocol MIBs available through it.
+a SNMP agent using the the AgentX protocol (:rfc:`2741`) and make the
+routing protocol MIBs available through it.
 
 Note that SNMP Support needs to be enabled at compile-time and loaded as module
 on daemon startup. Refer to :ref:`loadable-module-support` on the latter.
@@ -18,16 +18,10 @@ on daemon startup. Refer to :ref:`loadable-module-support` on the latter.
 Getting and installing an SNMP agent
 ====================================
 
-There are several SNMP agent which support SMUX or AgentX. We recommend to use
+The supported SNMP agent is AgentX. We recommend to use
 the latest version of `net-snmp` which was formerly known as `ucd-snmp`. It is
 free and open software and available at `http://www.net-snmp.org/ <http://www.net-snmp.org/>`_
-and as binary package for most Linux distributions. `net-snmp` has to be
-compiled with `--with-mib-modules=agentx` to be able to accept connections from
-FRR using AgentX protocol or with `--with-mib-modules=smux` to use SMUX
-protocol.
-
-Nowadays, SMUX is a legacy protocol. The AgentX protocol should be preferred
-for any new deployment. Both protocols have the same coverage.
+and as binary package for most Linux distributions.
 
 .. _agentx-configuration:
 
@@ -42,7 +36,7 @@ master SNMP agent (snmpd) and each of the FRR daemons must be configured. In
 :file:`/etc/snmp/snmpd.conf`, the ``master agentx`` directive should be added.
 In each of the FRR daemons, ``agentx`` command will enable AgentX support.
 
-:file:`/etc/snmp/snmpd.conf`:
+:file:`/etc/snmp/zebra.conf`:
 
 ::
 
@@ -97,105 +91,6 @@ need to configure FRR to use another transport, you can configure it through
    agentXSocket tcp:192.168.15.12:705
 
 
-.. _smux-configuration:
-
-SMUX configuration
-==================
-
-To enable SMUX protocol support, FRR must have been build with the
-:option:`--enable-snmp` option.
-
-A separate connection has then to be established between the SNMP agent (snmpd)
-and each of the FRR daemons. This connections each use different OID numbers
-and passwords. Be aware that this OID number is not the one that is used in
-queries by clients, it is solely used for the intercommunication of the
-daemons.
-
-In the following example the ospfd daemon will be connected to the snmpd daemon
-using the password "frr_ospfd". For testing it is recommending to take exactly
-the below snmpd.conf as wrong access restrictions can be hard to debug.
-
-:file:`/etc/snmp/snmpd.conf`:
-
-::
-
-   #
-   # example access restrictions setup
-   #
-   com2sec readonly default public
-   group MyROGroup v1 readonly
-   view all included .1 80
-   access MyROGroup "" any noauth exact all none none
-   #
-   # the following line is relevant for FRR
-   #
-   smuxpeer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd
-
-:file:`/etc/frr/ospf`:
-
-::
-
-   ! ... the rest of ospfd.conf has been omitted for clarity ...
-   !
-   smux peer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd
-   !
-
-
-After restarting snmpd and frr, a successful connection can be verified in the
-syslog and by querying the SNMP daemon:
-
-::
-
-   snmpd[12300]: [smux_accept] accepted fd 12 from 127.0.0.1:36255
-   snmpd[12300]: accepted smux peer: \\
-      oid GNOME-PRODUCT-ZEBRA-MIB::ospfd, frr-0.96.5
-
-   # snmpwalk -c public -v1 localhost .1.3.6.1.2.1.14.1.1
-   OSPF-MIB::ospfRouterId.0 = IpAddress: 192.168.42.109
-
-
-Be warned that the current version (5.1.1) of the Net-SNMP daemon writes a line
-for every SNMP connect to the syslog which can lead to enormous log file sizes.
-If that is a problem you should consider to patch snmpd and comment out the
-troublesome `snmp_log()` line in the function `netsnmp_agent_check_packet()` in
-`agent/snmp_agent.c`.
-
-MIB and command reference
-=========================
-
-The following OID numbers are used for the interprocess communication of snmpd and
-the FRR daemons with SMUX only.::
-
-  .    (OIDs below .iso.org.dod.internet.private.enterprises)
-  zebra        .1.3.6.1.4.1.3317.1.2.1 .gnome.gnomeProducts.zebra.zserv
-  bgpd .1.3.6.1.4.1.3317.1.2.2 .gnome.gnomeProducts.zebra.bgpd
-  ripd .1.3.6.1.4.1.3317.1.2.3 .gnome.gnomeProducts.zebra.ripd
-  ospfd        .1.3.6.1.4.1.3317.1.2.5 .gnome.gnomeProducts.zebra.ospfd
-  ospf6d       .1.3.6.1.4.1.3317.1.2.6 .gnome.gnomeProducts.zebra.ospf6d
-
-
-Sadly, SNMP has not been implemented in all daemons yet. The following
-OID numbers are used for querying the SNMP daemon by a client:::
-
-  zebra        .1.3.6.1.2.1.4.24   .iso.org.dot.internet.mgmt.mib-2.ip.ipForward
-  ospfd        .1.3.6.1.2.1.14     .iso.org.dot.internet.mgmt.mib-2.ospf
-  bgpd .1.3.6.1.2.1.15     .iso.org.dot.internet.mgmt.mib-2.bgp
-  ripd .1.3.6.1.2.1.23     .iso.org.dot.internet.mgmt.mib-2.rip2
-  ospf6d       .1.3.6.1.3.102      .iso.org.dod.internet.experimental.ospfv3
-
-
-The following syntax is understood by the FRR daemons for configuring SNMP
-using SMUX:
-
-.. index:: smux peer OID
-.. clicmd:: smux peer OID
-.. index:: no smux peer OID
-.. clicmd:: no smux peer OID
-.. index:: smux peer OID PASSWORD
-.. clicmd:: smux peer OID PASSWORD
-.. index:: no smux peer OID PASSWORD
-.. clicmd:: no smux peer OID PASSWORD
-
 Here is the syntax for using AgentX:
 
 .. index:: agentx
index d05dba33ee0bce8f641b0e8ec908063a05087035..7e8a4a4edaba81502d7ba6ec840a3c2baa431882 100644 (file)
@@ -43,6 +43,7 @@
 #include "isisd/isis_constants.h"
 #include "isisd/isis_circuit.h"
 #include "isisd/isis_network.h"
+#include "isisd/isis_pdu.h"
 
 #include "privs.h"
 
index 7cf83f20fad262baa83baf33a175034716fcaca1..cd4b76139f7455f6603abbbb1cb6ce910beb9209 100644 (file)
@@ -536,7 +536,7 @@ void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream)
                *stream = stream_new(stream_size);
        } else {
                if (STREAM_SIZE(*stream) != stream_size)
-                       stream_resize(*stream, stream_size);
+                       stream_resize_inplace(stream, stream_size);
                stream_reset(*stream);
        }
 }
index 0292c85dac0b5920cd1cfd8d0096dfa771c23776..1799c6b94f3c79bde7f161d54ec22c53c26be377 100644 (file)
@@ -274,19 +274,12 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width,
        if (!b->head)
                return BUFFER_EMPTY;
 
-       if (height < 1) {
-               zlog_warn(
-                       "%s called with non-positive window height %d, forcing to 1",
-                       __func__, height);
+       if (height < 1)
                height = 1;
-       else if (height >= 2)
+       else if (height >= 2)
                height--;
-       if (width < 1) {
-               zlog_warn(
-                       "%s called with non-positive window width %d, forcing to 1",
-                       __func__, width);
+       if (width < 1)
                width = 1;
-       }
 
        /* For erase and more data add two to b's buffer_data count.*/
        if (b->head->next == NULL) {
@@ -334,11 +327,6 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width,
                {
                        iov_alloc *= 2;
                        if (iov != small_iov) {
-                               zlog_warn(
-                                       "%s: growing iov array to %d; "
-                                       "width %d, height %d, size %lu",
-                                       __func__, iov_alloc, width, height,
-                                       (unsigned long)b->size);
                                iov = XREALLOC(MTYPE_TMP, iov,
                                               iov_alloc * sizeof(*iov));
                        } else {
index b19c33f65e6b3de860ae46f58e791429c67b4c65..24b8fafd108a29a40e96688fcf7198ecc865be33 100644 (file)
@@ -24,6 +24,9 @@
 #if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
 #  define _RET_NONNULL    , returns_nonnull
 #endif
+#if __has_attribute(fallthrough)
+#  define _FALLTHROUGH __attribute__((fallthrough));
+#endif
 # define _CONSTRUCTOR(x)  constructor(x)
 #elif defined(__GNUC__)
 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
@@ -34,6 +37,9 @@
 #  define _DESTRUCTOR(x)  destructor(x)
 #  define _ALLOC_SIZE(x)  alloc_size(x)
 #endif
+#if __GNUC__ >= 7
+#  define _FALLTHROUGH __attribute__((fallthrough));
+#endif
 #endif
 
 #ifdef __sun
@@ -55,6 +61,9 @@
 #ifndef _ALLOC_SIZE
 # define _ALLOC_SIZE(x)
 #endif
+#ifndef _FALLTHROUGH
+#define _FALLTHROUGH
+#endif
 
 /*
  * for warnings on macros, put in the macro content like this:
index 2fa5db6f34fb1ec20add64f60c5f39985c6b8acd..17ec51c4bfa9138b7c3b1646fe91b45075caafec 100644 (file)
@@ -107,7 +107,7 @@ struct log_ref *log_ref_get(uint32_t code)
 void log_ref_display(struct vty *vty, uint32_t code, bool json)
 {
        struct log_ref *ref;
-       struct json_object *top, *obj;
+       struct json_object *top = NULL, *obj = NULL;
        struct list *errlist;
        struct listnode *ln;
 
@@ -146,7 +146,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json)
                        char ubuf[256];
 
                        snprintf(pbuf, sizeof(pbuf), "\nError %"PRIu32" - %s",
-                                code, ref->title);
+                                ref->code, ref->title);
                        memset(ubuf, '=', strlen(pbuf));
                        ubuf[sizeof(ubuf) - 1] = '\0';
 
index 6023624dc1bdf1d3401c5c90c63857353cf3d98b..2bf0c6e6b5ae4a93f65bbaacda9a9864eff9eaa0 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -393,7 +393,8 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, int vty)
         * this should not be considered as an update
         * then create the new interface
         */
-       if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns(vrf_id))
+       if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns(
+                                       vrf_lookup_by_id(vrf_id)))
                return if_create(name, vrf_id);
        /* If it came from the kernel
         * or by way of zclient, believe it and update
@@ -471,6 +472,14 @@ int if_is_vrf(struct interface *ifp)
        return CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
 }
 
+bool if_is_loopback_or_vrf(struct interface *ifp)
+{
+       if (if_is_loopback(ifp) || if_is_vrf(ifp))
+               return true;
+
+       return false;
+}
+
 /* Does this interface support broadcast ? */
 int if_is_broadcast(struct interface *ifp)
 {
@@ -1140,7 +1149,7 @@ const char *if_link_type_str(enum zebra_link_type llt)
                llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4");
                llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
        default:
-               zlog_warn("Unknown value %d", llt);
+               flog_err(LIB_ERR_DEVELOPMENT, "Unknown value %d", llt);
                return "Unknown type!";
 #undef llts
        }
index 3a9c4af8486d2eccb8bde1818e9f481ba5153b53..a861cf2d855907d4714a9576e7a22abb64bad5ba 100644 (file)
--- a/lib/if.h
+++ b/lib/if.h
@@ -497,6 +497,7 @@ extern int if_is_operative(struct interface *);
 extern int if_is_no_ptm_operative(struct interface *);
 extern int if_is_loopback(struct interface *);
 extern int if_is_vrf(struct interface *ifp);
+extern bool if_is_loopback_or_vrf(struct interface *ifp);
 extern int if_is_broadcast(struct interface *);
 extern int if_is_pointopoint(struct interface *);
 extern int if_is_multicast(struct interface *);
index e011a78f1c3a38e4b267aab9e0a1e1f9e65ef20e..b067018e08de3bdef4b33f9b2b635a3fc0b3833f 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -868,11 +868,16 @@ int zlog_rotate(void)
                save_errno = errno;
                umask(oldumask);
                if (zl->fp == NULL) {
+
+                       pthread_mutex_unlock(&loglock);
+
                        flog_err_sys(
                                LIB_ERR_SYSTEM_CALL,
                                "Log rotate failed: cannot open file %s for append: %s",
                                zl->filename, safe_strerror(save_errno));
                        ret = -1;
+
+                       pthread_mutex_lock(&loglock);
                } else {
                        logfile_fd = fileno(zl->fp);
                        zl->maxlvl[ZLOG_DEST_FILE] = level;
@@ -903,10 +908,6 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_ROUTE_ADD),
        DESC_ENTRY(ZEBRA_ROUTE_DELETE),
        DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_OWNER),
-       DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD),
-       DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE),
-       DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD),
-       DESC_ENTRY(ZEBRA_IPV6_ROUTE_DELETE),
        DESC_ENTRY(ZEBRA_REDISTRIBUTE_ADD),
        DESC_ENTRY(ZEBRA_REDISTRIBUTE_DELETE),
        DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_ADD),
index 980f3ddf4b189ad460385efbe3eba6788ed31a33..7d05b846411ea3d38cfefeb0d1f49cd35af92bfe 100644 (file)
--- a/lib/log.h
+++ b/lib/log.h
@@ -87,7 +87,7 @@ extern void zlog_debug(const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
 
 /* For logs which have error codes associated with them */
 #define flog_err(ferr_id, format, ...)                                        \
-       zlog_err("[EC %d] " format, ferr_id, ##__VA_ARGS__)
+       zlog_err("[EC %"PRIu32"] " format, ferr_id, ##__VA_ARGS__)
 #define flog_err_sys(ferr_id, format, ...)                                     \
        flog_err(ferr_id, format, ##__VA_ARGS__)
 
diff --git a/lib/smux.c b/lib/smux.c
deleted file mode 100644 (file)
index 51abfcc..0000000
+++ /dev/null
@@ -1,1416 +0,0 @@
-/* SNMP support
- * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra 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>
-
-#ifdef SNMP_SMUX
-#include <net-snmp/net-snmp-config.h>
-#include <net-snmp/net-snmp-includes.h>
-
-#include "log.h"
-#include "thread.h"
-#include "linklist.h"
-#include "command.h"
-#include <lib/version.h>
-#include "memory.h"
-#include "sockunion.h"
-#include "smux.h"
-
-#define SMUX_PORT_DEFAULT 199
-
-#define SMUXMAXPKTSIZE    1500
-#define SMUXMAXSTRLEN      256
-
-#define SMUX_OPEN       (ASN_APPLICATION | ASN_CONSTRUCTOR | 0)
-#define SMUX_CLOSE      (ASN_APPLICATION | ASN_PRIMITIVE | 1)
-#define SMUX_RREQ       (ASN_APPLICATION | ASN_CONSTRUCTOR | 2)
-#define SMUX_RRSP       (ASN_APPLICATION | ASN_PRIMITIVE | 3)
-#define SMUX_SOUT       (ASN_APPLICATION | ASN_PRIMITIVE | 4)
-
-#define SMUX_GET        (ASN_CONTEXT | ASN_CONSTRUCTOR | 0)
-#define SMUX_GETNEXT    (ASN_CONTEXT | ASN_CONSTRUCTOR | 1)
-#define SMUX_GETRSP     (ASN_CONTEXT | ASN_CONSTRUCTOR | 2)
-#define SMUX_SET       (ASN_CONTEXT | ASN_CONSTRUCTOR | 3)
-#define SMUX_TRAP      (ASN_CONTEXT | ASN_CONSTRUCTOR | 4)
-
-#define SMUX_MAX_FAILURE 3
-
-/* SNMP tree. */
-struct subtree {
-       /* Tree's oid. */
-       oid name[MAX_OID_LEN];
-       uint8_t name_len;
-
-       /* List of the variables. */
-       struct variable *variables;
-
-       /* Length of the variables list. */
-       int variables_num;
-
-       /* Width of the variables list. */
-       int variables_width;
-
-       /* Registered flag. */
-       int registered;
-};
-
-#define min(A,B) ((A) < (B) ? (A) : (B))
-
-enum smux_event { SMUX_SCHEDULE, SMUX_CONNECT, SMUX_READ };
-
-void smux_event(enum smux_event, int);
-
-
-/* SMUX socket. */
-int smux_sock = -1;
-
-/* SMUX subtree list. */
-struct list *treelist;
-
-/* SMUX oid. */
-oid *smux_oid = NULL;
-size_t smux_oid_len;
-
-/* SMUX password. */
-char *smux_passwd = NULL;
-
-/* SMUX read threads. */
-struct thread *smux_read_thread;
-
-/* SMUX connect thrads. */
-struct thread *smux_connect_thread;
-
-/* SMUX debug flag. */
-int debug_smux = 0;
-
-/* SMUX failure count. */
-int fail = 0;
-
-/* SMUX node. */
-static struct cmd_node smux_node = {
-       SMUX_NODE, "" /* SMUX has no interface. */
-};
-
-/* thread master */
-static struct thread_master *smux_master;
-
-static int oid_compare_part(oid *o1, int o1_len, oid *o2, int o2_len)
-{
-       int i;
-
-       for (i = 0; i < min(o1_len, o2_len); i++) {
-               if (o1[i] < o2[i])
-                       return -1;
-               else if (o1[i] > o2[i])
-                       return 1;
-       }
-       if (o1_len < o2_len)
-               return -1;
-
-       return 0;
-}
-
-static void smux_oid_dump(const char *prefix, const oid *oid, size_t oid_len)
-{
-       unsigned int i;
-       int first = 1;
-       char buf[MAX_OID_LEN * 3];
-
-       buf[0] = '\0';
-
-       for (i = 0; i < oid_len; i++) {
-               sprintf(buf + strlen(buf), "%s%d", first ? "" : ".",
-                       (int)oid[i]);
-               first = 0;
-       }
-       zlog_debug("%s: %s", prefix, buf);
-}
-
-static int smux_socket(void)
-{
-       int ret;
-       struct addrinfo hints, *res0, *res;
-       int gai;
-       int sock = 0;
-
-       memset(&hints, 0, sizeof(hints));
-       hints.ai_family = PF_UNSPEC;
-       hints.ai_socktype = SOCK_STREAM;
-       gai = getaddrinfo(NULL, "smux", &hints, &res0);
-       if (gai == EAI_SERVICE) {
-               char servbuf[NI_MAXSERV];
-               sprintf(servbuf, "%d", SMUX_PORT_DEFAULT);
-               servbuf[sizeof(servbuf) - 1] = '\0';
-               gai = getaddrinfo(NULL, servbuf, &hints, &res0);
-       }
-       if (gai) {
-               zlog_warn("Cannot locate loopback service smux");
-               return -1;
-       }
-       for (res = res0; res; res = res->ai_next) {
-               if (res->ai_family != AF_INET && res->ai_family != AF_INET6)
-                       continue;
-
-               sock = socket(res->ai_family, res->ai_socktype,
-                             res->ai_protocol);
-               if (sock < 0)
-                       continue;
-               sockopt_reuseaddr(sock);
-               sockopt_reuseport(sock);
-               ret = connect(sock, res->ai_addr, res->ai_addrlen);
-               if (ret < 0) {
-                       close(sock);
-                       sock = -1;
-                       continue;
-               }
-               break;
-       }
-       freeaddrinfo(res0);
-       if (sock < 0)
-               zlog_warn("Can't connect to SNMP agent with SMUX");
-       return sock;
-}
-
-static void smux_getresp_send(oid objid[], size_t objid_len, long reqid,
-                             long errstat, long errindex, uint8_t val_type,
-                             void *arg, size_t arg_len)
-{
-       uint8_t buf[BUFSIZ];
-       uint8_t *ptr, *h1, *h1e, *h2, *h2e;
-       size_t len, length;
-
-       ptr = buf;
-       len = BUFSIZ;
-       length = len;
-
-       if (debug_smux) {
-               zlog_debug("SMUX GETRSP send");
-               zlog_debug("SMUX GETRSP reqid: %ld", reqid);
-       }
-
-       h1 = ptr;
-       /* Place holder h1 for complete sequence */
-       ptr = asn_build_sequence(ptr, &len, (uint8_t)SMUX_GETRSP, 0);
-       h1e = ptr;
-
-       ptr = asn_build_int(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &reqid,
-               sizeof(reqid));
-
-       if (debug_smux)
-               zlog_debug("SMUX GETRSP errstat: %ld", errstat);
-
-       ptr = asn_build_int(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-               &errstat, sizeof(errstat));
-       if (debug_smux)
-               zlog_debug("SMUX GETRSP errindex: %ld", errindex);
-
-       ptr = asn_build_int(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-               &errindex, sizeof(errindex));
-
-       h2 = ptr;
-       /* Place holder h2 for one variable */
-       ptr = asn_build_sequence(ptr, &len,
-                                (uint8_t)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
-       h2e = ptr;
-
-       ptr = snmp_build_var_op(ptr, objid, &objid_len, val_type, arg_len, arg,
-                               &len);
-
-       /* Now variable size is known, fill in size */
-       asn_build_sequence(h2, &length,
-                          (uint8_t)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
-                          ptr - h2e);
-
-       /* Fill in size of whole sequence */
-       asn_build_sequence(h1, &length, (uint8_t)SMUX_GETRSP, ptr - h1e);
-
-       if (debug_smux)
-               zlog_debug("SMUX getresp send: %td", (ptr - buf));
-
-       send(smux_sock, buf, (ptr - buf), 0);
-}
-
-static uint8_t *smux_var(uint8_t *ptr, size_t len, oid objid[],
-                        size_t *objid_len, size_t *var_val_len,
-                        uint8_t *var_val_type, void **var_value)
-{
-       uint8_t type;
-       uint8_t val_type;
-       size_t val_len;
-       uint8_t *val;
-
-       if (debug_smux)
-               zlog_debug("SMUX var parse: len %zd", len);
-
-       /* Parse header. */
-       ptr = asn_parse_header(ptr, &len, &type);
-
-       if (debug_smux) {
-               zlog_debug("SMUX var parse: type %d len %zd", type, len);
-               zlog_debug("SMUX var parse: type must be %d",
-                          (ASN_SEQUENCE | ASN_CONSTRUCTOR));
-       }
-
-       /* Parse var option. */
-       *objid_len = MAX_OID_LEN;
-       ptr = snmp_parse_var_op(ptr, objid, objid_len, &val_type, &val_len,
-                               &val, &len);
-
-       if (var_val_len)
-               *var_val_len = val_len;
-
-       if (var_value)
-               *var_value = (void *)val;
-
-       if (var_val_type)
-               *var_val_type = val_type;
-
-       /* Requested object id length is objid_len. */
-       if (debug_smux)
-               smux_oid_dump("Request OID", objid, *objid_len);
-
-       if (debug_smux)
-               zlog_debug("SMUX val_type: %d", val_type);
-
-       /* Check request value type. */
-       if (debug_smux)
-               switch (val_type) {
-               case ASN_NULL:
-                       /* In case of SMUX_GET or SMUX_GET_NEXT val_type is set
-                          to
-                          ASN_NULL. */
-                       zlog_debug("ASN_NULL");
-                       break;
-
-               case ASN_INTEGER:
-                       zlog_debug("ASN_INTEGER");
-                       break;
-               case ASN_COUNTER:
-               case ASN_GAUGE:
-               case ASN_TIMETICKS:
-               case ASN_UINTEGER:
-                       zlog_debug("ASN_COUNTER");
-                       break;
-               case ASN_COUNTER64:
-                       zlog_debug("ASN_COUNTER64");
-                       break;
-               case ASN_IPADDRESS:
-                       zlog_debug("ASN_IPADDRESS");
-                       break;
-               case ASN_OCTET_STR:
-                       zlog_debug("ASN_OCTET_STR");
-                       break;
-               case ASN_OPAQUE:
-               case ASN_NSAP:
-               case ASN_OBJECT_ID:
-                       zlog_debug("ASN_OPAQUE");
-                       break;
-               case SNMP_NOSUCHOBJECT:
-                       zlog_debug("SNMP_NOSUCHOBJECT");
-                       break;
-               case SNMP_NOSUCHINSTANCE:
-                       zlog_debug("SNMP_NOSUCHINSTANCE");
-                       break;
-               case SNMP_ENDOFMIBVIEW:
-                       zlog_debug("SNMP_ENDOFMIBVIEW");
-                       break;
-               case ASN_BIT_STR:
-                       zlog_debug("ASN_BIT_STR");
-                       break;
-               default:
-                       zlog_debug("Unknown type");
-                       break;
-               }
-       return ptr;
-}
-
-/* NOTE: all 3 functions (smux_set, smux_get & smux_getnext) are based on
-   ucd-snmp smux and as such suppose, that the peer receives in the message
-   only one variable. Fortunately, IBM seems to do the same in AIX. */
-
-static int smux_set(oid *reqid, size_t *reqid_len, uint8_t val_type, void *val,
-                   size_t val_len, int action)
-{
-       int j;
-       struct subtree *subtree;
-       struct variable *v;
-       int subresult;
-       oid *suffix;
-       size_t suffix_len;
-       int result;
-       uint8_t *statP = NULL;
-       WriteMethod *write_method = NULL;
-       struct listnode *node, *nnode;
-
-       /* Check */
-       for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) {
-               subresult = oid_compare_part(reqid, *reqid_len, subtree->name,
-                                            subtree->name_len);
-
-               /* Subtree matched. */
-               if (subresult == 0) {
-                       /* Prepare suffix. */
-                       suffix = reqid + subtree->name_len;
-                       suffix_len = *reqid_len - subtree->name_len;
-                       result = subresult;
-
-                       /* Check variables. */
-                       for (j = 0; j < subtree->variables_num; j++) {
-                               v = &subtree->variables[j];
-
-                               /* Always check suffix */
-                               result = oid_compare_part(suffix, suffix_len,
-                                                         v->name, v->namelen);
-
-                               /* This is exact match so result must be zero.
-                                */
-                               if (result == 0) {
-                                       if (debug_smux)
-                                               zlog_debug(
-                                                       "SMUX function call index is %d",
-                                                       v->magic);
-
-                                       statP = (*v->findVar)(
-                                               v, suffix, &suffix_len, 1,
-                                               &val_len, &write_method);
-
-                                       if (write_method) {
-                                               return (*write_method)(
-                                                       action, val, val_type,
-                                                       val_len, statP, suffix,
-                                                       suffix_len);
-                                       } else {
-                                               return SNMP_ERR_READONLY;
-                                       }
-                               }
-
-                               /* If above execution is failed or oid is small
-                                  (so
-                                  there is no further match). */
-                               if (result < 0)
-                                       return SNMP_ERR_NOSUCHNAME;
-                       }
-               }
-       }
-       return SNMP_ERR_NOSUCHNAME;
-}
-
-static int smux_get(oid *reqid, size_t *reqid_len, int exact, uint8_t *val_type,
-                   void **val, size_t *val_len)
-{
-       int j;
-       struct subtree *subtree;
-       struct variable *v;
-       int subresult;
-       oid *suffix;
-       size_t suffix_len;
-       int result;
-       WriteMethod *write_method = NULL;
-       struct listnode *node, *nnode;
-
-       /* Check */
-       for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) {
-               subresult = oid_compare_part(reqid, *reqid_len, subtree->name,
-                                            subtree->name_len);
-
-               /* Subtree matched. */
-               if (subresult == 0) {
-                       /* Prepare suffix. */
-                       suffix = reqid + subtree->name_len;
-                       suffix_len = *reqid_len - subtree->name_len;
-                       result = subresult;
-
-                       /* Check variables. */
-                       for (j = 0; j < subtree->variables_num; j++) {
-                               v = &subtree->variables[j];
-
-                               /* Always check suffix */
-                               result = oid_compare_part(suffix, suffix_len,
-                                                         v->name, v->namelen);
-
-                               /* This is exact match so result must be zero.
-                                */
-                               if (result == 0) {
-                                       if (debug_smux)
-                                               zlog_debug(
-                                                       "SMUX function call index is %d",
-                                                       v->magic);
-
-                                       *val = (*v->findVar)(
-                                               v, suffix, &suffix_len, exact,
-                                               val_len, &write_method);
-
-                                       /* There is no instance. */
-                                       if (*val == NULL)
-                                               return SNMP_NOSUCHINSTANCE;
-
-                                       /* Call is suceed. */
-                                       *val_type = v->type;
-
-                                       return 0;
-                               }
-
-                               /* If above execution is failed or oid is small
-                                  (so
-                                  there is no further match). */
-                               if (result < 0)
-                                       return SNMP_ERR_NOSUCHNAME;
-                       }
-               }
-       }
-       return SNMP_ERR_NOSUCHNAME;
-}
-
-static int smux_getnext(oid *reqid, size_t *reqid_len, int exact,
-                       uint8_t *val_type, void **val, size_t *val_len)
-{
-       int j;
-       oid save[MAX_OID_LEN];
-       int savelen = 0;
-       struct subtree *subtree;
-       struct variable *v;
-       int subresult;
-       oid *suffix;
-       size_t suffix_len;
-       int result;
-       WriteMethod *write_method = NULL;
-       struct listnode *node, *nnode;
-
-
-       /* Save incoming request. */
-       oid_copy(save, reqid, *reqid_len);
-       savelen = *reqid_len;
-
-       /* Check */
-       for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) {
-               subresult = oid_compare_part(reqid, *reqid_len, subtree->name,
-                                            subtree->name_len);
-
-               /* If request is in the tree. The agent has to make sure we
-                  only receive requests we have registered for. */
-               /* Unfortunately, that's not true. In fact, a SMUX subagent has
-                  to
-                  behave as if it manages the whole SNMP MIB tree itself. It's
-                  the
-                  duty of the master agent to collect the best answer and
-                  return it
-                  to the manager. See RFC 1227 chapter 3.1.6 for the glory
-                  details
-                  :-). ucd-snmp really behaves bad here as it actually might
-                  ask
-                  multiple times for the same GETNEXT request as it throws away
-                  the
-                  answer when it expects it in a different subtree and might
-                  come
-                  back later with the very same request. --jochen */
-
-               if (subresult <= 0) {
-                       /* Prepare suffix. */
-                       suffix = reqid + subtree->name_len;
-                       suffix_len = *reqid_len - subtree->name_len;
-                       if (subresult < 0) {
-                               oid_copy(reqid, subtree->name,
-                                        subtree->name_len);
-                               *reqid_len = subtree->name_len;
-                       }
-                       for (j = 0; j < subtree->variables_num; j++) {
-                               result = subresult;
-                               v = &subtree->variables[j];
-
-                               /* Next then check result >= 0. */
-                               if (result == 0)
-                                       result = oid_compare_part(
-                                               suffix, suffix_len, v->name,
-                                               v->namelen);
-
-                               if (result <= 0) {
-                                       if (debug_smux)
-                                               zlog_debug(
-                                                       "SMUX function call index is %d",
-                                                       v->magic);
-                                       if (result < 0) {
-                                               oid_copy(suffix, v->name,
-                                                        v->namelen);
-                                               suffix_len = v->namelen;
-                                       }
-                                       *val = (*v->findVar)(
-                                               v, suffix, &suffix_len, exact,
-                                               val_len, &write_method);
-                                       *reqid_len =
-                                               suffix_len + subtree->name_len;
-                                       if (*val) {
-                                               *val_type = v->type;
-                                               return 0;
-                                       }
-                               }
-                       }
-               }
-       }
-       memcpy(reqid, save, savelen * sizeof(oid));
-       *reqid_len = savelen;
-
-       return SNMP_ERR_NOSUCHNAME;
-}
-
-/* GET message header. */
-static uint8_t *smux_parse_get_header(uint8_t *ptr, size_t *len, long *reqid)
-{
-       uint8_t type;
-       long errstat;
-       long errindex;
-
-       /* Request ID. */
-       ptr = asn_parse_int(ptr, len, &type, reqid, sizeof(*reqid));
-
-       if (debug_smux)
-               zlog_debug("SMUX GET reqid: %d len: %d", (int)*reqid,
-                          (int)*len);
-
-       /* Error status. */
-       ptr = asn_parse_int(ptr, len, &type, &errstat, sizeof(errstat));
-
-       if (debug_smux)
-               zlog_debug("SMUX GET errstat %ld len: %zd", errstat, *len);
-
-       /* Error index. */
-       ptr = asn_parse_int(ptr, len, &type, &errindex, sizeof(errindex));
-
-       if (debug_smux)
-               zlog_debug("SMUX GET errindex %ld len: %zd", errindex, *len);
-
-       return ptr;
-}
-
-static void smux_parse_set(uint8_t *ptr, size_t len, int action)
-{
-       long reqid;
-       oid oid[MAX_OID_LEN];
-       size_t oid_len;
-       uint8_t val_type;
-       void *val;
-       size_t val_len;
-       int ret;
-
-       if (debug_smux)
-               zlog_debug("SMUX SET(%s) message parse: len %zd",
-                          (RESERVE1 == action)
-                                  ? "RESERVE1"
-                                  : ((FREE == action) ? "FREE" : "COMMIT"),
-                          len);
-
-       /* Parse SET message header. */
-       ptr = smux_parse_get_header(ptr, &len, &reqid);
-
-       /* Parse SET message object ID. */
-       ptr = smux_var(ptr, len, oid, &oid_len, &val_len, &val_type, &val);
-
-       ret = smux_set(oid, &oid_len, val_type, val, val_len, action);
-       if (debug_smux)
-               zlog_debug("SMUX SET ret %d", ret);
-
-       /* Return result. */
-       if (RESERVE1 == action)
-               smux_getresp_send(oid, oid_len, reqid, ret, 3, ASN_NULL, NULL,
-                                 0);
-}
-
-static void smux_parse_get(uint8_t *ptr, size_t len, int exact)
-{
-       long reqid;
-       oid oid[MAX_OID_LEN];
-       size_t oid_len;
-       uint8_t val_type;
-       void *val;
-       size_t val_len;
-       int ret;
-
-       if (debug_smux)
-               zlog_debug("SMUX GET message parse: len %zd", len);
-
-       /* Parse GET message header. */
-       ptr = smux_parse_get_header(ptr, &len, &reqid);
-
-       /* Parse GET message object ID. We needn't the value come */
-       ptr = smux_var(ptr, len, oid, &oid_len, NULL, NULL, NULL);
-
-       /* Traditional getstatptr. */
-       if (exact)
-               ret = smux_get(oid, &oid_len, exact, &val_type, &val, &val_len);
-       else
-               ret = smux_getnext(oid, &oid_len, exact, &val_type, &val,
-                                  &val_len);
-
-       /* Return result. */
-       if (ret == 0)
-               smux_getresp_send(oid, oid_len, reqid, 0, 0, val_type, val,
-                                 val_len);
-       else
-               smux_getresp_send(oid, oid_len, reqid, ret, 3, ASN_NULL, NULL,
-                                 0);
-}
-
-/* Parse SMUX_CLOSE message. */
-static void smux_parse_close(uint8_t *ptr, int len)
-{
-       long reason = 0;
-
-       while (len--) {
-               reason = (reason << 8) | (long)*ptr;
-               ptr++;
-       }
-       zlog_info("SMUX_CLOSE with reason: %ld", reason);
-}
-
-/* SMUX_RRSP message. */
-static void smux_parse_rrsp(uint8_t *ptr, size_t len)
-{
-       uint8_t val;
-       long errstat;
-
-       ptr = asn_parse_int(ptr, &len, &val, &errstat, sizeof(errstat));
-
-       if (debug_smux)
-               zlog_debug("SMUX_RRSP value: %d errstat: %ld", val, errstat);
-}
-
-/* Parse SMUX message. */
-static int smux_parse(uint8_t *ptr, size_t len)
-{
-       /* This buffer we'll use for SOUT message. We could allocate it with
-          malloc and save only static pointer/lenght, but IMHO static
-          buffer is a faster solusion. */
-       static uint8_t sout_save_buff[SMUXMAXPKTSIZE];
-       static int sout_save_len = 0;
-
-       int len_income = len; /* see note below: YYY */
-       uint8_t type;
-       uint8_t rollback;
-
-       rollback = ptr[2]; /* important only for SMUX_SOUT */
-
-process_rest: /* see note below: YYY */
-
-       /* Parse SMUX message type and subsequent length. */
-       ptr = asn_parse_header(ptr, &len, &type);
-
-       if (debug_smux)
-               zlog_debug("SMUX message received type: %d rest len: %zd", type,
-                          len);
-
-       switch (type) {
-       case SMUX_OPEN:
-               /* Open must be not send from SNMP agent. */
-               zlog_warn("SMUX_OPEN received: resetting connection.");
-               return -1;
-               break;
-       case SMUX_RREQ:
-               /* SMUX_RREQ message is invalid for us. */
-               zlog_warn("SMUX_RREQ received: resetting connection.");
-               return -1;
-               break;
-       case SMUX_SOUT:
-               /* SMUX_SOUT message is now valied for us. */
-               if (debug_smux)
-                       zlog_debug("SMUX_SOUT(%s)",
-                                  rollback ? "rollback" : "commit");
-
-               if (sout_save_len > 0) {
-                       smux_parse_set(sout_save_buff, sout_save_len,
-                                      rollback ? FREE : COMMIT);
-                       sout_save_len = 0;
-               } else
-                       zlog_warn("SMUX_SOUT sout_save_len=%d - invalid",
-                                 (int)sout_save_len);
-
-               if (len_income > 3) {
-                       /* YYY: this strange code has to solve the "slow peer"
-                          problem: When agent sends SMUX_SOUT message it
-                          doesn't
-                          wait any responce and may send some next message to
-                          subagent. Then the peer in 'smux_read()' will recieve
-                          from socket the 'concatenated' buffer, contaning both
-                          SMUX_SOUT message and the next one
-                          (SMUX_GET/SMUX_GETNEXT/SMUX_GET). So we should check:
-                          if
-                          the buffer is longer than 3 ( length of SMUX_SOUT ),
-                          we
-                          must process the rest of it.  This effect may be
-                          observed
-                          if 'debug_smux' is set to '1' */
-                       ptr++;
-                       len = len_income - 3;
-                       goto process_rest;
-               }
-               break;
-       case SMUX_GETRSP:
-               /* SMUX_GETRSP message is invalid for us. */
-               zlog_warn("SMUX_GETRSP received: resetting connection.");
-               return -1;
-               break;
-       case SMUX_CLOSE:
-               /* Close SMUX connection. */
-               if (debug_smux)
-                       zlog_debug("SMUX_CLOSE");
-               smux_parse_close(ptr, len);
-               return -1;
-               break;
-       case SMUX_RRSP:
-               /* This is response for register message. */
-               if (debug_smux)
-                       zlog_debug("SMUX_RRSP");
-               smux_parse_rrsp(ptr, len);
-               break;
-       case SMUX_GET:
-               /* Exact request for object id. */
-               if (debug_smux)
-                       zlog_debug("SMUX_GET");
-               smux_parse_get(ptr, len, 1);
-               break;
-       case SMUX_GETNEXT:
-               /* Next request for object id. */
-               if (debug_smux)
-                       zlog_debug("SMUX_GETNEXT");
-               smux_parse_get(ptr, len, 0);
-               break;
-       case SMUX_SET:
-               /* SMUX_SET is supported with some limitations. */
-               if (debug_smux)
-                       zlog_debug("SMUX_SET");
-
-               /* save the data for future SMUX_SOUT */
-               memcpy(sout_save_buff, ptr, len);
-               sout_save_len = len;
-               smux_parse_set(ptr, len, RESERVE1);
-               break;
-       default:
-               zlog_info("Unknown type: %d", type);
-               break;
-       }
-       return 0;
-}
-
-/* SMUX message read function. */
-static int smux_read(struct thread *t)
-{
-       int sock;
-       int len;
-       uint8_t buf[SMUXMAXPKTSIZE];
-       int ret;
-
-       /* Clear thread. */
-       sock = THREAD_FD(t);
-       smux_read_thread = NULL;
-
-       if (debug_smux)
-               zlog_debug("SMUX read start");
-
-       /* Read message from SMUX socket. */
-       len = recv(sock, buf, SMUXMAXPKTSIZE, 0);
-
-       if (len < 0) {
-               zlog_warn("Can't read all SMUX packet: %s",
-                         safe_strerror(errno));
-               close(sock);
-               smux_sock = -1;
-               smux_event(SMUX_CONNECT, 0);
-               return -1;
-       }
-
-       if (len == 0) {
-               zlog_warn("SMUX connection closed: %d", sock);
-               close(sock);
-               smux_sock = -1;
-               smux_event(SMUX_CONNECT, 0);
-               return -1;
-       }
-
-       if (debug_smux)
-               zlog_debug("SMUX read len: %d", len);
-
-       /* Parse the message. */
-       ret = smux_parse(buf, len);
-
-       if (ret < 0) {
-               close(sock);
-               smux_sock = -1;
-               smux_event(SMUX_CONNECT, 0);
-               return -1;
-       }
-
-       /* Regiser read thread. */
-       smux_event(SMUX_READ, sock);
-
-       return 0;
-}
-
-static int smux_open(int sock)
-{
-       uint8_t buf[BUFSIZ];
-       uint8_t *ptr;
-       size_t len;
-       long version;
-       const char progname[] = FRR_SMUX_NAME "-" FRR_VERSION;
-
-       if (debug_smux) {
-               smux_oid_dump("SMUX open oid", smux_oid, smux_oid_len);
-               zlog_debug("SMUX open progname: %s", progname);
-               zlog_debug("SMUX open password: %s", smux_passwd);
-       }
-
-       ptr = buf;
-       len = BUFSIZ;
-
-       /* SMUX Header.  As placeholder. */
-       ptr = asn_build_header(ptr, &len, (uint8_t)SMUX_OPEN, 0);
-
-       /* SMUX Open. */
-       version = 0;
-       ptr = asn_build_int(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-               &version, sizeof(version));
-
-       /* SMUX connection oid. */
-       ptr = asn_build_objid(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),
-               smux_oid, smux_oid_len);
-
-       /* SMUX connection description. */
-       ptr = asn_build_string(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
-               (const uint8_t *)progname, strlen(progname));
-
-       /* SMUX connection password. */
-       ptr = asn_build_string(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
-               (uint8_t *)smux_passwd, strlen(smux_passwd));
-
-       /* Fill in real SMUX header.  We exclude ASN header size (2). */
-       len = BUFSIZ;
-       asn_build_header(buf, &len, (uint8_t)SMUX_OPEN, (ptr - buf) - 2);
-
-       return send(sock, buf, (ptr - buf), 0);
-}
-
-/* `ename` is ignored. Instead of using the provided enterprise OID,
-   the SMUX peer is used. This keep compatibility with the previous
-   versions of Quagga.
-
-   All other fields are used as they are intended. */
-int smux_trap(struct variable *vp, size_t vp_len, const oid *ename,
-             size_t enamelen, const oid *name, size_t namelen,
-             const oid *iname, size_t inamelen,
-             const struct trap_object *trapobj, size_t trapobjlen,
-             uint8_t sptrap)
-{
-       unsigned int i;
-       uint8_t buf[BUFSIZ];
-       uint8_t *ptr;
-       size_t len, length;
-       struct in_addr addr;
-       unsigned long val;
-       uint8_t *h1, *h1e;
-
-       ptr = buf;
-       len = BUFSIZ;
-       length = len;
-
-       /* When SMUX connection is not established. */
-       if (smux_sock < 0)
-               return 0;
-
-       /* SMUX header. */
-       ptr = asn_build_header(ptr, &len, (uint8_t)SMUX_TRAP, 0);
-
-       /* Sub agent enterprise oid. */
-       ptr = asn_build_objid(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),
-               smux_oid, smux_oid_len);
-
-       /* IP address. */
-       addr.s_addr = 0;
-       ptr = asn_build_string(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_IPADDRESS),
-               (uint8_t *)&addr, sizeof(addr));
-
-       /* Generic trap integer. */
-       val = SNMP_TRAP_ENTERPRISESPECIFIC;
-       ptr = asn_build_int(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-               (long *)&val, sizeof(val));
-
-       /* Specific trap integer. */
-       val = sptrap;
-       ptr = asn_build_int(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-               (long *)&val, sizeof(val));
-
-       /* Timeticks timestamp. */
-       val = 0;
-       ptr = asn_build_unsigned_int(
-               ptr, &len,
-               (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_TIMETICKS), &val,
-               sizeof(val));
-
-       /* Variables. */
-       h1 = ptr;
-       ptr = asn_build_sequence(ptr, &len,
-                                (uint8_t)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
-
-
-       /* Iteration for each objects. */
-       h1e = ptr;
-       for (i = 0; i < trapobjlen; i++) {
-               int ret;
-               oid oid[MAX_OID_LEN];
-               size_t oid_len;
-               void *val;
-               size_t val_len;
-               uint8_t val_type;
-
-               /* Make OID. */
-               if (trapobj[i].namelen > 0) {
-                       oid_copy(oid, name, namelen);
-                       oid_copy(oid + namelen, trapobj[i].name,
-                                trapobj[i].namelen);
-                       oid_copy(oid + namelen + trapobj[i].namelen, iname,
-                                inamelen);
-                       oid_len = namelen + trapobj[i].namelen + inamelen;
-               } else {
-                       oid_copy(oid, name, namelen);
-                       oid_copy(oid + namelen, trapobj[i].name,
-                                trapobj[i].namelen * (-1));
-                       oid_len = namelen + trapobj[i].namelen * (-1);
-               }
-
-               if (debug_smux) {
-                       smux_oid_dump("Trap", name, namelen);
-                       if (trapobj[i].namelen < 0)
-                               smux_oid_dump("Trap", trapobj[i].name,
-                                             (-1) * (trapobj[i].namelen));
-                       else {
-                               smux_oid_dump("Trap", trapobj[i].name,
-                                             (trapobj[i].namelen));
-                               smux_oid_dump("Trap", iname, inamelen);
-                       }
-                       smux_oid_dump("Trap", oid, oid_len);
-                       zlog_info("BUFSIZ: %d // oid_len: %lu", BUFSIZ,
-                                 (unsigned long)oid_len);
-               }
-
-               ret = smux_get(oid, &oid_len, 1, &val_type, &val, &val_len);
-
-               if (debug_smux)
-                       zlog_debug("smux_get result %d", ret);
-
-               if (ret == 0)
-                       ptr = snmp_build_var_op(ptr, oid, &oid_len, val_type,
-                                               val_len, val, &len);
-       }
-
-       /* Now variable size is known, fill in size */
-       asn_build_sequence(h1, &length,
-                          (uint8_t)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
-                          ptr - h1e);
-
-       /* Fill in size of whole sequence */
-       len = BUFSIZ;
-       asn_build_header(buf, &len, (uint8_t)SMUX_TRAP, (ptr - buf) - 2);
-
-       return send(smux_sock, buf, (ptr - buf), 0);
-}
-
-static int smux_register(int sock)
-{
-       uint8_t buf[BUFSIZ];
-       uint8_t *ptr;
-       int ret;
-       size_t len;
-       long priority;
-       long operation;
-       struct subtree *subtree;
-       struct listnode *node, *nnode;
-
-       ret = 0;
-
-       for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) {
-               ptr = buf;
-               len = BUFSIZ;
-
-               /* SMUX RReq Header. */
-               ptr = asn_build_header(ptr, &len, (uint8_t)SMUX_RREQ, 0);
-
-               /* Register MIB tree. */
-               ptr = asn_build_objid(ptr, &len,
-                                     (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE
-                                               | ASN_OBJECT_ID),
-                                     subtree->name, subtree->name_len);
-
-               /* Priority. */
-               priority = -1;
-               ptr = asn_build_int(
-                       ptr, &len,
-                       (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-                       &priority, sizeof(priority));
-
-               /* Operation. */
-               operation = 2; /* Register R/W */
-               ptr = asn_build_int(
-                       ptr, &len,
-                       (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-                       &operation, sizeof(operation));
-
-               if (debug_smux) {
-                       smux_oid_dump("SMUX register oid", subtree->name,
-                                     subtree->name_len);
-                       zlog_debug("SMUX register priority: %ld", priority);
-                       zlog_debug("SMUX register operation: %ld", operation);
-               }
-
-               len = BUFSIZ;
-               asn_build_header(buf, &len, (uint8_t)SMUX_RREQ,
-                                (ptr - buf) - 2);
-               ret = send(sock, buf, (ptr - buf), 0);
-               if (ret < 0)
-                       return ret;
-       }
-       return ret;
-}
-
-/* Try to connect to SNMP agent. */
-static int smux_connect(struct thread *t)
-{
-       int ret;
-
-       if (debug_smux)
-               zlog_debug("SMUX connect try %d", fail + 1);
-
-       /* Clear thread poner of myself. */
-       smux_connect_thread = NULL;
-
-       /* Make socket.  Try to connect. */
-       smux_sock = smux_socket();
-       if (smux_sock < 0) {
-               if (++fail < SMUX_MAX_FAILURE)
-                       smux_event(SMUX_CONNECT, 0);
-               return 0;
-       }
-
-       /* Send OPEN PDU. */
-       ret = smux_open(smux_sock);
-       if (ret < 0) {
-               zlog_warn("SMUX open message send failed: %s",
-                         safe_strerror(errno));
-               close(smux_sock);
-               smux_sock = -1;
-               if (++fail < SMUX_MAX_FAILURE)
-                       smux_event(SMUX_CONNECT, 0);
-               return -1;
-       }
-
-       /* Send any outstanding register PDUs. */
-       ret = smux_register(smux_sock);
-       if (ret < 0) {
-               zlog_warn("SMUX register message send failed: %s",
-                         safe_strerror(errno));
-               close(smux_sock);
-               smux_sock = -1;
-               if (++fail < SMUX_MAX_FAILURE)
-                       smux_event(SMUX_CONNECT, 0);
-               return -1;
-       }
-
-       /* Everything goes fine. */
-       smux_event(SMUX_READ, smux_sock);
-
-       return 0;
-}
-
-/* Clear all SMUX related resources. */
-static void smux_stop(void)
-{
-       if (smux_read_thread) {
-               thread_cancel(smux_read_thread);
-               smux_read_thread = NULL;
-       }
-
-       if (smux_connect_thread) {
-               thread_cancel(smux_connect_thread);
-               smux_connect_thread = NULL;
-       }
-
-       if (smux_sock >= 0) {
-               close(smux_sock);
-               smux_sock = -1;
-       }
-}
-
-
-void smux_event(enum smux_event event, int sock)
-{
-       switch (event) {
-       case SMUX_SCHEDULE:
-               smux_connect_thread = NULL;
-               thread_add_event(smux_master, smux_connect, NULL, 0,
-                                &smux_connect_thread);
-               break;
-       case SMUX_CONNECT:
-               smux_connect_thread = NULL;
-               thread_add_timer(smux_master, smux_connect, NULL, 10,
-                                &smux_connect_thread);
-               break;
-       case SMUX_READ:
-               smux_read_thread = NULL;
-               thread_add_read(smux_master, smux_read, NULL, sock,
-                               &smux_read_thread);
-               break;
-       default:
-               break;
-       }
-}
-
-static int smux_str2oid(const char *str, oid *oid, size_t *oid_len)
-{
-       int len;
-       int val;
-
-       len = 0;
-       val = 0;
-       *oid_len = 0;
-
-       if (*str == '.')
-               str++;
-       if (*str == '\0')
-               return 0;
-
-       while (1) {
-               if (!isdigit(*str))
-                       return -1;
-
-               while (isdigit(*str)) {
-                       val *= 10;
-                       val += (*str - '0');
-                       str++;
-               }
-
-               if (*str == '\0')
-                       break;
-               if (*str != '.')
-                       return -1;
-
-               oid[len++] = val;
-               val = 0;
-               str++;
-       }
-
-       oid[len++] = val;
-       *oid_len = len;
-
-       return 0;
-}
-
-static oid *smux_oid_dup(oid *objid, size_t objid_len)
-{
-       oid *new;
-
-       new = XMALLOC(MTYPE_TMP, sizeof(oid) * objid_len);
-       oid_copy(new, objid, objid_len);
-
-       return new;
-}
-
-static int smux_peer_oid(struct vty *vty, const char *oid_str,
-                        const char *passwd_str)
-{
-       int ret;
-       oid oid[MAX_OID_LEN];
-       size_t oid_len;
-
-       ret = smux_str2oid(oid_str, oid, &oid_len);
-       if (ret != 0) {
-               vty_out(vty, "object ID malformed\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       if (smux_oid) {
-               free(smux_oid);
-               smux_oid = NULL;
-       }
-
-       /* careful, smux_passwd might point to string constant */
-       if (smux_passwd) {
-               free(smux_passwd);
-               smux_passwd = NULL;
-       }
-
-       smux_oid = smux_oid_dup(oid, oid_len);
-       smux_oid_len = oid_len;
-
-       if (passwd_str)
-               smux_passwd = strdup(passwd_str);
-       else
-               smux_passwd = strdup("");
-
-       return 0;
-}
-
-static int smux_peer_default(void)
-{
-       if (smux_oid) {
-               free(smux_oid);
-               smux_oid = NULL;
-       }
-
-       /* careful, smux_passwd might be pointing at string constant */
-       if (smux_passwd) {
-               free(smux_passwd);
-               smux_passwd = NULL;
-       }
-
-       return CMD_SUCCESS;
-}
-
-DEFUN (smux_peer,
-       smux_peer_cmd,
-       "smux peer OID",
-       "SNMP MUX protocol settings\n"
-       "SNMP MUX peer settings\n"
-       "Object ID used in SMUX peering\n")
-{
-       int idx_oid = 2;
-       if (smux_peer_oid(vty, argv[idx_oid]->arg, NULL) == 0) {
-               smux_start();
-               return CMD_SUCCESS;
-       } else
-               return CMD_WARNING_CONFIG_FAILED;
-}
-
-DEFUN (smux_peer_password,
-       smux_peer_password_cmd,
-       "smux peer OID PASSWORD",
-       "SNMP MUX protocol settings\n"
-       "SNMP MUX peer settings\n"
-       "SMUX peering object ID\n"
-       "SMUX peering password\n")
-{
-       int idx_oid = 2;
-       if (smux_peer_oid(vty, argv[idx_oid]->arg, argv[3]->rg) == 0) {
-               smux_start();
-               return CMD_SUCCESS;
-       } else
-               return CMD_WARNING_CONFIG_FAILED;
-}
-
-DEFUN (no_smux_peer,
-       no_smux_peer_cmd,
-       "no smux peer [OID [PASSWORD]]",
-       NO_STR
-       "SNMP MUX protocol settings\n"
-       "SNMP MUX peer settings\n"
-       "SMUX peering object ID\n"
-       "SMUX peering password\n")
-{
-       smux_stop();
-       return smux_peer_default();
-}
-
-static int config_write_smux(struct vty *vty)
-{
-       int first = 1;
-       unsigned int i;
-
-       if (smux_oid) {
-               vty_out(vty, "smux peer ");
-               for (i = 0; i < smux_oid_len; i++) {
-                       vty_out(vty, "%s%d", first ? "" : ".",
-                               (int)smux_oid[i]);
-                       first = 0;
-               }
-               vty_out(vty, " %s\n", smux_passwd);
-       }
-       return 0;
-}
-
-/* Register subtree to smux master tree. */
-void smux_register_mib(const char *descr, struct variable *var, size_t width,
-                      int num, oid name[], size_t namelen)
-{
-       struct subtree *tree;
-
-       tree = (struct subtree *)malloc(sizeof(struct subtree));
-       oid_copy(tree->name, name, namelen);
-       tree->name_len = namelen;
-       tree->variables = var;
-       tree->variables_num = num;
-       tree->variables_width = width;
-       tree->registered = 0;
-       listnode_add_sort(treelist, tree);
-}
-
-/* Compare function to keep treelist sorted */
-static int smux_tree_cmp(struct subtree *tree1, struct subtree *tree2)
-{
-       return oid_compare(tree1->name, tree1->name_len, tree2->name,
-                          tree2->name_len);
-}
-
-/* Initialize some values then schedule first SMUX connection. */
-void smux_init(struct thread_master *tm)
-{
-       assert(tm);
-       /* copy callers thread master */
-       smux_master = tm;
-
-       /* Make MIB tree. */
-       treelist = list_new();
-       treelist->cmp = (int (*)(void *, void *))smux_tree_cmp;
-
-       /* Install commands. */
-       install_node(&smux_node, config_write_smux);
-
-       install_element(CONFIG_NODE, &smux_peer_cmd);
-       install_element(CONFIG_NODE, &smux_peer_password_cmd);
-       install_element(CONFIG_NODE, &no_smux_peer_cmd);
-       install_element(CONFIG_NODE, &no_smux_peer_oid_cmd);
-       install_element(CONFIG_NODE, &no_smux_peer_oid_password_cmd);
-}
-
-void smux_start(void)
-{
-       /* Close any existing connections. */
-       smux_stop();
-
-       /* Schedule first connection. */
-       smux_event(SMUX_SCHEDULE, 0);
-}
-#endif /* SNMP_SMUX */
index 878b5ae09dd856450ecbce322a9340113ee56c71..3febcb714d5a57e406cce9921034fe5139b2141d 100644 (file)
@@ -580,31 +580,7 @@ int sockopt_tcp_rtt(int sock)
 
 int sockopt_tcp_signature(int sock, union sockunion *su, const char *password)
 {
-#if defined(HAVE_TCP_MD5_LINUX24) && defined(GNU_LINUX)
-/* Support for the old Linux 2.4 TCP-MD5 patch, taken from Hasso Tepper's
- * version of the Quagga patch (based on work by Rick Payne, and Bruce
- * Simpson)
- */
-#define TCP_MD5_AUTH 13
-#define TCP_MD5_AUTH_ADD 1
-#define TCP_MD5_AUTH_DEL 2
-       struct tcp_rfc2385_cmd {
-               uint8_t command;  /* Command - Add/Delete */
-               uint32_t address; /* IPV4 address associated */
-               uint8_t keylen;   /* MD5 Key len (do NOT assume 0 terminated
-                                     ascii) */
-               void *key;       /* MD5 Key */
-       } cmd;
-       struct in_addr *addr = &su->sin.sin_addr;
-
-       cmd.command = (password != NULL ? TCP_MD5_AUTH_ADD : TCP_MD5_AUTH_DEL);
-       cmd.address = addr->s_addr;
-       cmd.keylen = (password != NULL ? strlen(password) : 0);
-       cmd.key = password;
-
-       return setsockopt(sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd);
-
-#elif HAVE_DECL_TCP_MD5SIG
+#if HAVE_DECL_TCP_MD5SIG
        int ret;
 #ifndef GNU_LINUX
        /*
index c420c25f04d0cc8c3f399731f9fd690a714de091..41d4e2bb578f2756d94568b075e57e5465b2c4fa 100644 (file)
@@ -143,7 +143,7 @@ static int spf_backoff_holddown_elapsed(struct thread *thread)
 
 long spf_backoff_schedule(struct spf_backoff *backoff)
 {
-       long rv;
+       long rv = 0;
        struct timeval now;
 
        gettimeofday(&now, NULL);
@@ -176,9 +176,6 @@ long spf_backoff_schedule(struct spf_backoff *backoff)
                else
                        rv = backoff->long_delay;
                break;
-       default:
-               zlog_warn("SPF Back-off(%s) in unknown state", backoff->name);
-               rv = backoff->init_delay;
        }
 
        backoff_debug(
index cf9af4d3bb98fd768e8b3a9fe64acb20a33df60b..55e7f6435826118df2c8735f12a3832ea7912191 100644 (file)
@@ -28,9 +28,9 @@
 #include "network.h"
 #include "prefix.h"
 #include "log.h"
+#include "lib_errors.h"
 
 DEFINE_MTYPE_STATIC(LIB, STREAM, "Stream")
-DEFINE_MTYPE_STATIC(LIB, STREAM_DATA, "Stream data")
 DEFINE_MTYPE_STATIC(LIB, STREAM_FIFO, "Stream FIFO")
 
 /* Tests whether a position is valid */
@@ -100,9 +100,7 @@ struct stream *stream_new(size_t size)
 
        assert(size > 0);
 
-       s = XMALLOC(MTYPE_STREAM, sizeof(struct stream));
-
-       s->data = XMALLOC(MTYPE_STREAM_DATA, size);
+       s = XMALLOC(MTYPE_STREAM, sizeof(struct stream) + size);
 
        s->getp = s->endp = 0;
        s->next = NULL;
@@ -116,7 +114,6 @@ void stream_free(struct stream *s)
        if (!s)
                return;
 
-       XFREE(MTYPE_STREAM_DATA, s->data);
        XFREE(MTYPE_STREAM, s);
 }
 
@@ -166,27 +163,33 @@ struct stream *stream_dupcat(struct stream *s1, struct stream *s2,
        return new;
 }
 
-size_t stream_resize(struct stream *s, size_t newsize)
+size_t stream_resize_inplace(struct stream **sptr, size_t newsize)
 {
-       uint8_t *newdata;
-       STREAM_VERIFY_SANE(s);
+       struct stream *orig = *sptr;
 
-       newdata = XREALLOC(MTYPE_STREAM_DATA, s->data, newsize);
+       STREAM_VERIFY_SANE(orig);
 
-       if (newdata == NULL)
-               return s->size;
+       orig = XREALLOC(MTYPE_STREAM, orig, sizeof(struct stream) + newsize);
 
-       s->data = newdata;
-       s->size = newsize;
+       orig->size = newsize;
 
-       if (s->endp > s->size)
-               s->endp = s->size;
-       if (s->getp > s->endp)
-               s->getp = s->endp;
+       if (orig->endp > orig->size)
+               orig->endp = orig->size;
+       if (orig->getp > orig->endp)
+               orig->getp = orig->endp;
 
-       STREAM_VERIFY_SANE(s);
+       STREAM_VERIFY_SANE(orig);
 
-       return s->size;
+       *sptr = orig;
+       return orig->size;
+}
+
+size_t __attribute__((deprecated))stream_resize_orig(struct stream *s,
+                                                    size_t newsize)
+{
+       assert("stream_resize: Switch code to use stream_resize_inplace" == NULL);
+
+       return stream_resize_inplace(&s, newsize);
 }
 
 size_t stream_get_getp(struct stream *s)
index e808f039c623c07468df2ade9792c85648931a06..ef9366e1ae0b1da43950dce715e8aefa995cca65 100644 (file)
 struct stream {
        struct stream *next;
 
-       /* Remainder is ***private*** to stream
+       /*
+        * Remainder is ***private*** to stream
         * direct access is frowned upon!
         * Use the appropriate functions/macros
         */
-       size_t getp;     /* next get position */
-       size_t endp;     /* last valid data position */
-       size_t size;     /* size of data segment */
-       unsigned char *data; /* data pointer */
+       size_t getp;           /* next get position */
+       size_t endp;           /* last valid data position */
+       size_t size;           /* size of data segment */
+       unsigned char data[0]; /* data pointer */
 };
 
 /* First in first out queue structure. */
@@ -154,7 +155,14 @@ extern struct stream *stream_new(size_t);
 extern void stream_free(struct stream *);
 extern struct stream *stream_copy(struct stream *, struct stream *src);
 extern struct stream *stream_dup(struct stream *);
-extern size_t stream_resize(struct stream *, size_t);
+
+#if CONFDATE > 20190821
+CPP_NOTICE("lib: time to remove stream_resize_orig")
+#endif
+extern size_t stream_resize_orig(struct stream *s, size_t newsize);
+#define stream_resize stream_resize_orig
+extern size_t stream_resize_inplace(struct stream **sptr, size_t newsize);
+
 extern size_t stream_get_getp(struct stream *);
 extern size_t stream_get_endp(struct stream *);
 extern size_t stream_get_size(struct stream *);
index b938dbcea34a4a50583b6c44bd17b5ed9ffb5465..50cfd70a571ff4e6071ea5a6d7f5cf51e90859a4 100644 (file)
@@ -150,7 +150,6 @@ pkginclude_HEADERS += \
        lib/sha256.h \
        lib/sigevent.h \
        lib/skiplist.h \
-       lib/smux.h \
        lib/sockopt.h \
        lib/sockunion.h \
        lib/spf_backoff.h \
@@ -199,7 +198,6 @@ lib_libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
 lib_libfrrsnmp_la_LIBADD = lib/libfrr.la $(SNMP_LIBS)
 lib_libfrrsnmp_la_SOURCES = \
        lib/agentx.c \
-       lib/smux.c \
        lib/snmp.c \
        # end
 
index ac7df3e6950b455a93c95354620e2e204baf2293..8304abe59b38ec5b3b349b1848a412ccf266a9a3 100644 (file)
@@ -235,17 +235,13 @@ static inline struct route_node *route_lock_node(struct route_node *node)
 }
 
 /* Unlock node. */
-static inline struct route_node *route_unlock_node(struct route_node *node)
+static inline void route_unlock_node(struct route_node *node)
 {
        assert(node->lock > 0);
        (*(unsigned *)&node->lock)--;
 
-       if (node->lock == 0) {
+       if (node->lock == 0)
                route_node_delete(node);
-               return NULL;
-       }
-
-       return node;
 }
 
 /*
index 898e9e9fced5b42285f6826e8f6da47b8a69f5ff..52bc79ffe6ba528ad81afb4df505baed8d394c04 100644 (file)
@@ -36,6 +36,7 @@
 
 DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread")
 DEFINE_MTYPE_STATIC(LIB, THREAD_MASTER, "Thread master")
+DEFINE_MTYPE_STATIC(LIB, THREAD_POLL, "Thread Poll Info")
 DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats")
 
 #if defined(__APPLE__)
@@ -423,19 +424,11 @@ struct thread_master *thread_master_create(const char *name)
        /* Initialize I/O task data structures */
        getrlimit(RLIMIT_NOFILE, &limit);
        rv->fd_limit = (int)limit.rlim_cur;
-       rv->read =
-               XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit);
-       if (rv->read == NULL) {
-               XFREE(MTYPE_THREAD_MASTER, rv);
-               return NULL;
-       }
-       rv->write =
-               XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit);
-       if (rv->write == NULL) {
-               XFREE(MTYPE_THREAD, rv->read);
-               XFREE(MTYPE_THREAD_MASTER, rv);
-               return NULL;
-       }
+       rv->read = XCALLOC(MTYPE_THREAD_POLL,
+                          sizeof(struct thread *) * rv->fd_limit);
+
+       rv->write = XCALLOC(MTYPE_THREAD_POLL,
+                           sizeof(struct thread *) * rv->fd_limit);
 
        rv->cpu_record = hash_create_size(
                8, (unsigned int (*)(void *))cpu_record_hash_key,
@@ -539,17 +532,23 @@ static struct thread *thread_trim_head(struct thread_list *list)
        return NULL;
 }
 
+#define THREAD_UNUSED_DEPTH 10
+
 /* Move thread to unuse list. */
 static void thread_add_unuse(struct thread_master *m, struct thread *thread)
 {
        assert(m != NULL && thread != NULL);
        assert(thread->next == NULL);
        assert(thread->prev == NULL);
-       thread->ref = NULL;
 
-       thread->type = THREAD_UNUSED;
        thread->hist->total_active--;
-       thread_list_add(&m->unuse, thread);
+       memset(thread, 0, sizeof(struct thread));
+       thread->type = THREAD_UNUSED;
+
+       if (m->unuse.count < THREAD_UNUSED_DEPTH)
+               thread_list_add(&m->unuse, thread);
+       else
+               XFREE(MTYPE_THREAD, thread);
 }
 
 /* Free all unused thread. */
@@ -580,7 +579,7 @@ static void thread_array_free(struct thread_master *m,
                        m->alloc--;
                }
        }
-       XFREE(MTYPE_THREAD, thread_array);
+       XFREE(MTYPE_THREAD_POLL, thread_array);
 }
 
 static void thread_queue_free(struct thread_master *m, struct pqueue *queue)
@@ -1182,17 +1181,19 @@ void thread_cancel_event(struct thread_master *master, void *arg)
  */
 void thread_cancel(struct thread *thread)
 {
-       assert(thread->master->owner == pthread_self());
+       struct thread_master *master = thread->master;
+
+       assert(master->owner == pthread_self());
 
-       pthread_mutex_lock(&thread->master->mtx);
+       pthread_mutex_lock(&master->mtx);
        {
                struct cancel_req *cr =
                        XCALLOC(MTYPE_TMP, sizeof(struct cancel_req));
                cr->thread = thread;
-               listnode_add(thread->master->cancel_req, cr);
-               do_thread_cancel(thread->master);
+               listnode_add(master->cancel_req, cr);
+               do_thread_cancel(master);
        }
-       pthread_mutex_unlock(&thread->master->mtx);
+       pthread_mutex_unlock(&master->mtx);
 }
 
 /**
index 36111dfeae4ceebe327565bb309f809fc2483fdb..ecd09a6b915460ed26c391d2171b4bbca5a19345 100644 (file)
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -342,91 +342,103 @@ void *vrf_info_lookup(vrf_id_t vrf_id)
 }
 
 /*
- * VRF bit-map
+ * VRF hash for storing set or not.
  */
+struct vrf_bit_set {
+       vrf_id_t vrf_id;
+       bool set;
+};
 
-#define VRF_BITMAP_NUM_OF_GROUPS            1024
-#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT32_MAX / VRF_BITMAP_NUM_OF_GROUPS)
-#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP                                       \
-       (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
+static unsigned int vrf_hash_bitmap_key(void *data)
+{
+       struct vrf_bit_set *bit = data;
 
-#define VRF_BITMAP_GROUP(_id) ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
-#define VRF_BITMAP_BIT_OFFSET(_id) ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
+       return bit->vrf_id;
+}
 
-#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) ((_bit_offset) / CHAR_BIT)
-#define VRF_BITMAP_FLAG(_bit_offset)                                           \
-       (((uint8_t)1) << ((_bit_offset) % CHAR_BIT))
+static int vrf_hash_bitmap_cmp(const void *a, const void *b)
+{
+       const struct vrf_bit_set *bit1 = a;
+       const struct vrf_bit_set *bit2 = b;
 
-struct vrf_bitmap {
-       uint8_t *groups[VRF_BITMAP_NUM_OF_GROUPS];
-};
+       return bit1->vrf_id == bit2->vrf_id;
+}
+
+static void *vrf_hash_bitmap_alloc(void *data)
+{
+       struct vrf_bit_set *copy = data;
+       struct vrf_bit_set *bit;
+
+       bit = XMALLOC(MTYPE_VRF_BITMAP, sizeof(*bit));
+       bit->vrf_id = copy->vrf_id;
+
+       return bit;
+}
+
+static void vrf_hash_bitmap_free(void *data)
+{
+       struct vrf_bit_set *bit = data;
+
+       XFREE(MTYPE_VRF_BITMAP, bit);
+}
 
 vrf_bitmap_t vrf_bitmap_init(void)
 {
-       return (vrf_bitmap_t)XCALLOC(MTYPE_VRF_BITMAP,
-                                    sizeof(struct vrf_bitmap));
+       return hash_create_size(32, vrf_hash_bitmap_key, vrf_hash_bitmap_cmp,
+                               "VRF BIT HASH");
 }
 
 void vrf_bitmap_free(vrf_bitmap_t bmap)
 {
-       struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
-       int i;
+       struct hash *vrf_hash = bmap;
 
-       if (bmap == VRF_BITMAP_NULL)
+       if (vrf_hash == NULL)
                return;
 
-       for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
-               if (bm->groups[i])
-                       XFREE(MTYPE_VRF_BITMAP, bm->groups[i]);
-
-       XFREE(MTYPE_VRF_BITMAP, bm);
+       hash_clean(vrf_hash, vrf_hash_bitmap_free);
+       hash_free(vrf_hash);
 }
 
 void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
 {
-       struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
-       uint8_t group = VRF_BITMAP_GROUP(vrf_id);
-       uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
+       struct vrf_bit_set lookup = { .vrf_id = vrf_id };
+       struct hash *vrf_hash = bmap;
+       struct vrf_bit_set *bit;
 
-       if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN)
+       if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
                return;
 
-       if (bm->groups[group] == NULL)
-               bm->groups[group] = XCALLOC(MTYPE_VRF_BITMAP,
-                                           VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
-
-       SET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
-                VRF_BITMAP_FLAG(offset));
+       bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
+       bit->set = true;
 }
 
 void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
 {
-       struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
-       uint8_t group = VRF_BITMAP_GROUP(vrf_id);
-       uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
+       struct vrf_bit_set lookup = { .vrf_id = vrf_id };
+       struct hash *vrf_hash = bmap;
+       struct vrf_bit_set *bit;
 
-       if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
-           || bm->groups[group] == NULL)
+       if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
                return;
 
-       UNSET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
-                  VRF_BITMAP_FLAG(offset));
+       bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
+       bit->set = false;
 }
 
 int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
 {
-       struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
-       uint8_t group = VRF_BITMAP_GROUP(vrf_id);
-       uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
+       struct vrf_bit_set lookup = { .vrf_id = vrf_id };
+       struct hash *vrf_hash = bmap;
+       struct vrf_bit_set *bit;
 
-       if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
-           || bm->groups[group] == NULL)
+       if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
                return 0;
 
-       return CHECK_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
-                         VRF_BITMAP_FLAG(offset))
-                      ? 1
-                      : 0;
+       bit = hash_lookup(vrf_hash, &lookup);
+       if (bit)
+               return bit->set;
+
+       return 0;
 }
 
 static void vrf_autocomplete(vector comps, struct cmd_token *token)
@@ -682,10 +694,8 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
        return CMD_SUCCESS;
 }
 
-int vrf_is_mapped_on_netns(vrf_id_t vrf_id)
+int vrf_is_mapped_on_netns(struct vrf *vrf)
 {
-       struct vrf *vrf = vrf_lookup_by_id(vrf_id);
-
        if (!vrf || vrf->data.l.netns_name[0] == '\0')
                return 0;
        if (vrf->vrf_id == VRF_DEFAULT)
@@ -887,7 +897,7 @@ int vrf_bind(vrf_id_t vrf_id, int fd, char *name)
 
        if (fd < 0 || name == NULL)
                return fd;
-       if (vrf_is_mapped_on_netns(vrf_id))
+       if (vrf_is_mapped_on_netns(vrf_lookup_by_id(vrf_id)))
                return fd;
 #ifdef SO_BINDTODEVICE
        ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);
index 0f4f36be507a4172e6d58d7123370f4990b6e1da..56ba101ff0cf97bd038feb931933e500acea0b15 100644 (file)
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -237,7 +237,7 @@ extern vrf_id_t vrf_get_default_id(void);
 #define VRF_DEFAULT vrf_get_default_id()
 
 /* VRF is mapped on netns or not ? */
-int vrf_is_mapped_on_netns(vrf_id_t vrf_id);
+int vrf_is_mapped_on_netns(struct vrf *vrf);
 
 /* VRF switch from NETNS */
 extern int vrf_switch_to_netns(vrf_id_t vrf_id);
index cc91705ee227c8fd1565328cf050b230e635895a..b2bafcb7d8f831e2c5f8a69037b331cde2ae2a51 100644 (file)
@@ -676,11 +676,11 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
  * "xdr_encode"-like interface that allows daemon (client) to send
  * a message to zebra server for a route that needs to be
  * added/deleted to the kernel. Info about the route is specified
- * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes
+ * by the caller in a struct zapi_route. zapi_route_encode() then writes
  * the info down the zclient socket using the stream_* functions.
  *
  * The corresponding read ("xdr_decode") function on the server
- * side is zread_ipv4_add()/zread_ipv4_delete().
+ * side is zapi_route_decode().
  *
  *  0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -707,21 +707,16 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
  * 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
- * ifindex") nexthop data unit. A special encoding can be used to feed
- * onlink (64-bit "gate AND ifindex") nexthops into zapi_ipv4_route()
- * using the same zapi_ipv4 structure. This is done by setting zapi_ipv4
- * fields as follows:
+ * The original struct zapi_route_*() infrastructure was built around
+ * the traditional (32-bit "gate OR ifindex") nexthop data unit.
+ * A special encoding can be used to feed onlink (64-bit "gate AND ifindex")
+ * nexthops into zapi_route_encode() using the same zapi_route structure.
+ * This is done by setting zapi_route fields as follows:
  *  - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK
  *  - .nexthop_num == .ifindex_num
  *  - .nexthop and .ifindex are filled with gate and ifindex parts of
  *    each compound nexthop, both in the same order
  *
- * zapi_ipv4_route() will produce two nexthop data units for each such
- * interleaved 64-bit nexthop. On the zserv side of the socket it will be
- * mapped to a singlle NEXTHOP_TYPE_IPV4_IFINDEX_OL RIB nexthop structure.
- *
  * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1
  * byte value.
  *
@@ -734,226 +729,6 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p,
  *
  * XXX: No attention paid to alignment.
  */
-int zapi_ipv4_route(uint8_t cmd, struct zclient *zclient, struct prefix_ipv4 *p,
-                   struct zapi_ipv4 *api)
-{
-       int i;
-       int psize;
-       struct stream *s;
-
-       /* Reset stream. */
-       s = zclient->obuf;
-       stream_reset(s);
-
-       /* Some checks for labeled-unicast. The current expectation is that each
-        * nexthop is accompanied by a label in the case of labeled-unicast.
-        */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
-           && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               /* We expect prefixes installed with labels and the number to
-                * match
-                * the number of nexthops.
-                */
-               assert(api->label_num == api->nexthop_num);
-       }
-
-       zclient_create_header(s, cmd, api->vrf_id);
-
-       /* Put type and nexthop. */
-       stream_putc(s, api->type);
-       stream_putw(s, api->instance);
-       stream_putl(s, api->flags);
-       stream_putc(s, api->message);
-       stream_putw(s, api->safi);
-
-       /* Put prefix information. */
-       psize = PSIZE(p->prefixlen);
-       stream_putc(s, p->prefixlen);
-       stream_write(s, (uint8_t *)&p->prefix, psize);
-
-       /* Nexthop, ifindex, distance and metric information. */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               stream_putc(s, api->nexthop_num + api->ifindex_num);
-
-               for (i = 0; i < api->nexthop_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IPV4);
-                       stream_put_in_addr(s, api->nexthop[i]);
-                       /* For labeled-unicast, each nexthop is followed by
-                        * label. */
-                       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
-                               stream_putl(s, api->label[i]);
-               }
-               for (i = 0; i < api->ifindex_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IFINDEX);
-                       stream_putl(s, api->ifindex[i]);
-               }
-       }
-
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
-               stream_putc(s, api->distance);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
-               stream_putl(s, api->metric);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
-               stream_putl(s, api->tag);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
-               stream_putl(s, api->mtu);
-
-       /* Put length at the first point of the stream. */
-       stream_putw_at(s, 0, stream_get_endp(s));
-
-       return zclient_send_message(zclient);
-}
-
-int zapi_ipv4_route_ipv6_nexthop(uint8_t cmd, struct zclient *zclient,
-                                struct prefix_ipv4 *p, struct zapi_ipv6 *api)
-{
-       int i;
-       int psize;
-       struct stream *s;
-
-       /* Reset stream. */
-       s = zclient->obuf;
-       stream_reset(s);
-
-       /* Some checks for labeled-unicast. The current expectation is that each
-        * nexthop is accompanied by a label in the case of labeled-unicast.
-        */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
-           && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               /* We expect prefixes installed with labels and the number to
-                * match
-                * the number of nexthops.
-                */
-               assert(api->label_num == api->nexthop_num);
-       }
-
-       zclient_create_header(s, cmd, api->vrf_id);
-
-       /* Put type and nexthop. */
-       stream_putc(s, api->type);
-       stream_putw(s, api->instance);
-       stream_putl(s, api->flags);
-       stream_putc(s, api->message);
-       stream_putw(s, api->safi);
-
-       /* Put prefix information. */
-       psize = PSIZE(p->prefixlen);
-       stream_putc(s, p->prefixlen);
-       stream_write(s, (uint8_t *)&p->prefix, psize);
-
-       /* Nexthop, ifindex, distance and metric information. */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               stream_putc(s, api->nexthop_num + api->ifindex_num);
-
-               for (i = 0; i < api->nexthop_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IPV6);
-                       stream_write(s, (uint8_t *)api->nexthop[i], 16);
-                       /* For labeled-unicast, each nexthop is followed by
-                        * label. */
-                       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
-                               stream_putl(s, api->label[i]);
-               }
-               for (i = 0; i < api->ifindex_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IFINDEX);
-                       stream_putl(s, api->ifindex[i]);
-               }
-       }
-
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
-               stream_putc(s, api->distance);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
-               stream_putl(s, api->metric);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
-               stream_putl(s, api->tag);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
-               stream_putl(s, api->mtu);
-
-       /* Put length at the first point of the stream. */
-       stream_putw_at(s, 0, stream_get_endp(s));
-
-       return zclient_send_message(zclient);
-}
-
-int zapi_ipv6_route(uint8_t cmd, struct zclient *zclient, struct prefix_ipv6 *p,
-                   struct prefix_ipv6 *src_p, struct zapi_ipv6 *api)
-{
-       int i;
-       int psize;
-       struct stream *s;
-
-       /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL
-        */
-       assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p);
-
-       /* Reset stream. */
-       s = zclient->obuf;
-       stream_reset(s);
-
-       /* Some checks for labeled-unicast. The current expectation is that each
-        * nexthop is accompanied by a label in the case of labeled-unicast.
-        */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)
-           && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               /* We expect prefixes installed with labels and the number to
-                * match
-                * the number of nexthops.
-                */
-               assert(api->label_num == api->nexthop_num);
-       }
-
-       zclient_create_header(s, cmd, api->vrf_id);
-
-       /* Put type and nexthop. */
-       stream_putc(s, api->type);
-       stream_putw(s, api->instance);
-       stream_putl(s, api->flags);
-       stream_putc(s, api->message);
-       stream_putw(s, api->safi);
-
-       /* Put prefix information. */
-       psize = PSIZE(p->prefixlen);
-       stream_putc(s, p->prefixlen);
-       stream_write(s, (uint8_t *)&p->prefix, psize);
-
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) {
-               psize = PSIZE(src_p->prefixlen);
-               stream_putc(s, src_p->prefixlen);
-               stream_write(s, (uint8_t *)&src_p->prefix, psize);
-       }
-
-       /* Nexthop, ifindex, distance and metric information. */
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) {
-               stream_putc(s, api->nexthop_num + api->ifindex_num);
-
-               for (i = 0; i < api->nexthop_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IPV6);
-                       stream_write(s, (uint8_t *)api->nexthop[i], 16);
-                       /* For labeled-unicast, each nexthop is followed by
-                        * label. */
-                       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL))
-                               stream_putl(s, api->label[i]);
-               }
-               for (i = 0; i < api->ifindex_num; i++) {
-                       stream_putc(s, NEXTHOP_TYPE_IFINDEX);
-                       stream_putl(s, api->ifindex[i]);
-               }
-       }
-
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE))
-               stream_putc(s, api->distance);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
-               stream_putl(s, api->metric);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
-               stream_putl(s, api->tag);
-       if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
-               stream_putl(s, api->mtu);
-
-       /* Put length at the first point of the stream. */
-       stream_putw_at(s, 0, stream_get_endp(s));
-
-       return zclient_send_message(zclient);
-}
-
 int zclient_route_send(uint8_t cmd, struct zclient *zclient,
                       struct zapi_route *api)
 {
index 962b1707c948c9ebc6ff79533c4239dffca73d3d..b8ff85e80ff584f954f990abcc695d0d15d45c70 100644 (file)
@@ -73,10 +73,6 @@ typedef enum {
        ZEBRA_ROUTE_ADD,
        ZEBRA_ROUTE_DELETE,
        ZEBRA_ROUTE_NOTIFY_OWNER,
-       ZEBRA_IPV4_ROUTE_ADD,
-       ZEBRA_IPV4_ROUTE_DELETE,
-       ZEBRA_IPV6_ROUTE_ADD,
-       ZEBRA_IPV6_ROUTE_DELETE,
        ZEBRA_REDISTRIBUTE_ADD,
        ZEBRA_REDISTRIBUTE_DELETE,
        ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
@@ -286,7 +282,7 @@ struct zclient {
  */
 #define ZAPI_MESSAGE_TABLEID  0x80
 
-#define ZSERV_VERSION 5
+#define ZSERV_VERSION 6
 /* Zserv protocol message header */
 struct zmsghdr {
        uint16_t length;
@@ -353,37 +349,6 @@ struct zapi_route {
        uint32_t tableid;
 };
 
-/* Zebra IPv4 route message API. */
-struct zapi_ipv4 {
-       uint8_t type;
-       unsigned short instance;
-
-       uint32_t flags;
-
-       uint8_t message;
-
-       safi_t safi;
-
-       uint8_t nexthop_num;
-       struct in_addr **nexthop;
-
-       uint8_t ifindex_num;
-       ifindex_t *ifindex;
-
-       uint8_t label_num;
-       unsigned int *label;
-
-       uint8_t distance;
-
-       uint32_t metric;
-
-       route_tag_t tag;
-
-       uint32_t mtu;
-
-       vrf_id_t vrf_id;
-};
-
 struct zapi_pw {
        char ifname[IF_NAMESIZE];
        ifindex_t ifindex;
@@ -600,15 +565,6 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
 extern void zebra_interface_if_set_value(struct stream *, struct interface *);
 extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
 
-/* clang-format off */
-#if CONFDATE > 20180823
-CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now");
-#endif
-/* clang-format on */
-
-extern int zapi_ipv4_route(uint8_t, struct zclient *, struct prefix_ipv4 *,
-                          struct zapi_ipv4 *) __attribute__((deprecated));
-
 extern struct interface *zebra_interface_link_params_read(struct stream *);
 extern size_t zebra_interface_link_params_write(struct stream *,
                                                struct interface *);
@@ -635,45 +591,6 @@ extern void zebra_read_pw_status_update(int command, struct zclient *zclient,
                                        zebra_size_t length, vrf_id_t vrf_id,
                                        struct zapi_pw_status *pw);
 
-/* IPv6 prefix add and delete function prototype. */
-
-struct zapi_ipv6 {
-       uint8_t type;
-       unsigned short instance;
-
-       uint32_t flags;
-
-       uint8_t message;
-
-       safi_t safi;
-
-       uint8_t nexthop_num;
-       struct in6_addr **nexthop;
-
-       uint8_t ifindex_num;
-       ifindex_t *ifindex;
-
-       uint8_t label_num;
-       unsigned int *label;
-
-       uint8_t distance;
-
-       uint32_t metric;
-
-       route_tag_t tag;
-
-       uint32_t mtu;
-
-       vrf_id_t vrf_id;
-};
-
-extern int zapi_ipv6_route(uint8_t cmd, struct zclient *zclient,
-                          struct prefix_ipv6 *p, struct prefix_ipv6 *src_p,
-                          struct zapi_ipv6 *api) __attribute__((deprecated));
-extern int zapi_ipv4_route_ipv6_nexthop(uint8_t, struct zclient *,
-                                       struct prefix_ipv4 *,
-                                       struct zapi_ipv6 *)
-       __attribute__((deprecated));
 extern int zclient_route_send(uint8_t, struct zclient *, struct zapi_route *);
 extern int zclient_send_rnh(struct zclient *zclient, int command,
                            struct prefix *p, bool exact_match,
index db624ae0741aaefaae71579a15e8198e6a8fb20f..50485cc7e25c334de1a40787e945d3809c8b13c0 100644 (file)
@@ -46,6 +46,7 @@
 #include "ospfd/ospf_lsdb.h"
 #include "ospfd/ospf_neighbor.h"
 #include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_route.h"
 #include "ospfd/ospf_zebra.h"
 #include "ospfd/ospf_api.h"
 
index c0ce971f0cbd6fd5d7520a2096e934fbb6f9ffb1..57e0ae5ec95f83c95b3323c119483d103dd782b7 100644 (file)
@@ -1425,19 +1425,7 @@ struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area,
        newlsa->length = htons(length);
 
        /* Create OSPF LSA. */
-       if ((new = ospf_lsa_new()) == NULL) {
-               zlog_warn("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?");
-               stream_free(s);
-               return NULL;
-       }
-
-       if ((new->data = ospf_lsa_data_new(length)) == NULL) {
-               zlog_warn(
-                       "ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?");
-               ospf_lsa_unlock(&new);
-               stream_free(s);
-               return NULL;
-       }
+       new = ospf_lsa_new_and_data(length);
 
        new->area = area;
        new->oi = oi;
index 18c1077da09427e2698968a89e5573b471002a04..8e8f65530529e5f4319973337c602385045582a5 100644 (file)
@@ -73,26 +73,6 @@ void ospf_external_route_remove(struct ospf *ospf, struct prefix_ipv4 *p)
                  p->prefixlen);
 }
 
-/* Lookup external route. */
-struct ospf_route *ospf_external_route_lookup(struct ospf *ospf,
-                                             struct prefix_ipv4 *p)
-{
-       struct route_node *rn;
-
-       rn = route_node_lookup(ospf->old_external_route, (struct prefix *)p);
-       if (rn) {
-               route_unlock_node(rn);
-               if (rn->info)
-                       return rn->info;
-       }
-
-       zlog_warn("Route[%s/%d]: lookup, no such prefix", inet_ntoa(p->prefix),
-                 p->prefixlen);
-
-       return NULL;
-}
-
-
 /* Add an External info for AS-external-LSA. */
 struct external_info *ospf_external_info_new(uint8_t type,
                                             unsigned short instance)
index 370c6787b4153c8cdb49e53d33d5904f43a76a67..ac7bd68b5f3d7cb9cd20ce341b21efdf1338dcf5 100644 (file)
@@ -68,8 +68,6 @@ extern void ospf_external_info_delete(struct ospf *, uint8_t, unsigned short,
 extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t,
                                                       unsigned short,
                                                       struct prefix_ipv4 *);
-extern struct ospf_route *ospf_external_route_lookup(struct ospf *,
-                                                    struct prefix_ipv4 *);
 extern void ospf_asbr_status_update(struct ospf *, uint8_t);
 
 extern void ospf_redistribute_withdraw(struct ospf *, uint8_t, unsigned short);
index d84fd26ac4af74b90d1e3f2640d9ed907cae964e..0221d1e1b272afa7d13bb59ec02cc26412ce2674 100644 (file)
@@ -288,6 +288,7 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
        struct prefix_ipv4 asbr, p;
        struct route_node *rn;
        struct ospf_route *new, * or ;
+       char buf1[INET_ADDRSTRLEN];
        int ret;
 
        assert(lsa);
@@ -304,10 +305,14 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
                return 0;
        }
 
-       if (IS_DEBUG_OSPF(lsa, LSA))
+       if (IS_DEBUG_OSPF(lsa, LSA)) {
+               snprintf(buf1, INET_ADDRSTRLEN, "%s",
+                        inet_ntoa(al->header.adv_router));
                zlog_debug(
-                       "Route[External]: Calculate AS-external-LSA to %s/%d",
-                       inet_ntoa(al->header.id), ip_masklen(al->mask));
+                       "Route[External]: Calculate AS-external-LSA to %s/%d adv_router %s",
+                       inet_ntoa(al->header.id), ip_masklen(al->mask), buf1);
+       }
+
        /* (1) If the cost specified by the LSA is LSInfinity, or if the
               LSA's LS age is equal to MaxAge, then examine the next LSA. */
        if ((metric = GET_METRIC(al->e[0].metric)) >= OSPF_LS_INFINITY) {
@@ -459,8 +464,9 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
 
        if (!rn || (or = rn->info) == NULL) {
                if (IS_DEBUG_OSPF(lsa, LSA))
-                       zlog_debug("Route[External]: Adding a new route %s/%d",
-                                  inet_ntoa(p.prefix), p.prefixlen);
+                       zlog_debug("Route[External]: Adding a new route %s/%d with paths %u",
+                                  inet_ntoa(p.prefix), p.prefixlen,
+                                  listcount(asbr_route->paths));
 
                ospf_route_add(ospf->new_external_route, &p, new, asbr_route);
 
index b8d14c351ee38b1a82aa494fac7dead90144ccbc..f6ed9b81b964d04915f6f9b9f01e64e7998be741 100644 (file)
@@ -977,20 +977,7 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area,
        lsah->length = htons(length);
 
        /* Now, create an OSPF LSA instance. */
-       new = ospf_lsa_new();
-       if (new == NULL) {
-               zlog_warn("EXT (%s): ospf_lsa_new() error", __func__);
-               stream_free(s);
-               return NULL;
-       }
-       new->data = ospf_lsa_data_new(length);
-       if (new->data == NULL) {
-               zlog_warn("EXT (%s): ospf_lsa_data_new() error", __func__);
-               ospf_lsa_unlock(&new);
-               new = NULL;
-               stream_free(s);
-               return NULL;
-       }
+       new = ospf_lsa_new_and_data(length);
 
        /* Segment Routing belongs only to default VRF */
        new->vrf_id = VRF_DEFAULT;
@@ -1056,20 +1043,7 @@ static struct ospf_lsa *ospf_ext_link_lsa_new(struct ospf_area *area,
        lsah->length = htons(length);
 
        /* Now, create an OSPF LSA instance. */
-       new = ospf_lsa_new();
-       if (new == NULL) {
-               zlog_warn("EXT (%s): ospf_lsa_new() error", __func__);
-               stream_free(s);
-               return NULL;
-       }
-       new->data = ospf_lsa_data_new(length);
-       if (new->data == NULL) {
-               zlog_warn("EXT (%s): ospf_lsa_data_new() error", __func__);
-               ospf_lsa_unlock(&new);
-               new = NULL;
-               stream_free(s);
-               return NULL;
-       }
+       new = ospf_lsa_new_and_data(length);
 
        /* Segment Routing belongs only to default VRF */
        new->vrf_id = VRF_DEFAULT;
index 002c6bba8d7023a52743955ed84b09466c538be5..b4e9dda58a106f51347399df61be7d0cad0caf03 100644 (file)
@@ -810,8 +810,7 @@ struct ospf_lsa *ospf_ls_request_new(struct lsa_header *lsah)
 {
        struct ospf_lsa *new;
 
-       new = ospf_lsa_new();
-       new->data = ospf_lsa_data_new(OSPF_LSA_HEADER_SIZE);
+       new = ospf_lsa_new_and_data(OSPF_LSA_HEADER_SIZE);
        memcpy(new->data, lsah, OSPF_LSA_HEADER_SIZE);
 
        return new;
index 2651cf717b82355c9d83190db21752394ec795be..7c8a68994fbba2dc6020af6934d0bef870458547 100644 (file)
@@ -167,6 +167,16 @@ struct ospf_lsa *ospf_lsa_new()
        return new;
 }
 
+struct ospf_lsa *ospf_lsa_new_and_data(size_t size)
+{
+       struct ospf_lsa *new;
+
+       new = ospf_lsa_new();
+       new->data = ospf_lsa_data_new(size);
+
+       return new;
+}
+
 /* Duplicate OSPF LSA. */
 struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *lsa)
 {
@@ -406,7 +416,7 @@ static uint16_t ospf_link_cost(struct ospf_interface *oi)
 }
 
 /* Set a link information. */
-static char link_info_set(struct stream *s, struct in_addr id,
+static char link_info_set(struct stream **s, struct in_addr id,
                          struct in_addr data, uint8_t type, uint8_t tos,
                          uint16_t cost)
 {
@@ -415,11 +425,11 @@ static char link_info_set(struct stream *s, struct in_addr id,
         * more.
         * we try accomodate those here.
         */
-       if (STREAM_WRITEABLE(s) < OSPF_ROUTER_LSA_LINK_SIZE) {
+       if (STREAM_WRITEABLE(*s) < OSPF_ROUTER_LSA_LINK_SIZE) {
                size_t ret = OSPF_MAX_LSA_SIZE;
 
                /* Can we enlarge the stream still? */
-               if (STREAM_SIZE(s) == OSPF_MAX_LSA_SIZE) {
+               if (STREAM_SIZE(*s) == OSPF_MAX_LSA_SIZE) {
                        /* we futz the size here for simplicity, really we need
                         * to account
                         * for just:
@@ -431,30 +441,31 @@ static char link_info_set(struct stream *s, struct in_addr id,
                         *
                         * Simpler just to subtract OSPF_MAX_LSA_SIZE though.
                         */
-                       ret = stream_resize(
+                       ret = stream_resize_inplace(
                                s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE);
                }
 
                if (ret == OSPF_MAX_LSA_SIZE) {
                        zlog_warn(
                                "%s: Out of space in LSA stream, left %zd, size %zd",
-                               __func__, STREAM_WRITEABLE(s), STREAM_SIZE(s));
+                               __func__, STREAM_WRITEABLE(*s),
+                               STREAM_SIZE(*s));
                        return 0;
                }
        }
 
        /* TOS based routing is not supported. */
-       stream_put_ipv4(s, id.s_addr);   /* Link ID. */
-       stream_put_ipv4(s, data.s_addr); /* Link Data. */
-       stream_putc(s, type);            /* Link Type. */
-       stream_putc(s, tos);             /* TOS = 0. */
-       stream_putw(s, cost);            /* Link Cost. */
+       stream_put_ipv4(*s, id.s_addr);   /* Link ID. */
+       stream_put_ipv4(*s, data.s_addr); /* Link Data. */
+       stream_putc(*s, type);            /* Link Type. */
+       stream_putc(*s, tos);             /* TOS = 0. */
+       stream_putw(*s, cost);            /* Link Cost. */
 
        return 1;
 }
 
 /* Describe Point-to-Point link (Section 12.4.1.1). */
-static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi)
+static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
 {
        int links = 0;
        struct ospf_neighbor *nbr;
@@ -500,7 +511,7 @@ static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi)
 }
 
 /* Describe Broadcast Link. */
-static int lsa_link_broadcast_set(struct stream *s, struct ospf_interface *oi)
+static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi)
 {
        struct ospf_neighbor *dr;
        struct in_addr id, mask;
@@ -546,7 +557,7 @@ static int lsa_link_broadcast_set(struct stream *s, struct ospf_interface *oi)
        }
 }
 
-static int lsa_link_loopback_set(struct stream *s, struct ospf_interface *oi)
+static int lsa_link_loopback_set(struct stream **s, struct ospf_interface *oi)
 {
        struct in_addr id, mask;
 
@@ -560,7 +571,8 @@ static int lsa_link_loopback_set(struct stream *s, struct ospf_interface *oi)
 }
 
 /* Describe Virtual Link. */
-static int lsa_link_virtuallink_set(struct stream *s, struct ospf_interface *oi)
+static int lsa_link_virtuallink_set(struct stream **s,
+                                   struct ospf_interface *oi)
 {
        struct ospf_neighbor *nbr;
        uint16_t cost = ospf_link_cost(oi);
@@ -583,7 +595,7 @@ static int lsa_link_virtuallink_set(struct stream *s, struct ospf_interface *oi)
 12.4.1.4.*/
 /* from "edward rrr" <edward_rrr@hotmail.com>
    http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */
-static int lsa_link_ptomp_set(struct stream *s, struct ospf_interface *oi)
+static int lsa_link_ptomp_set(struct stream **s, struct ospf_interface *oi)
 {
        int links = 0;
        struct route_node *rn;
@@ -624,7 +636,7 @@ static int lsa_link_ptomp_set(struct stream *s, struct ospf_interface *oi)
 }
 
 /* Set router-LSA link information. */
-static int router_lsa_link_set(struct stream *s, struct ospf_area *area)
+static int router_lsa_link_set(struct stream **s, struct ospf_area *area)
 {
        struct listnode *node;
        struct ospf_interface *oi;
@@ -667,28 +679,28 @@ static int router_lsa_link_set(struct stream *s, struct ospf_area *area)
 }
 
 /* Set router-LSA body. */
-static void ospf_router_lsa_body_set(struct stream *s, struct ospf_area *area)
+static void ospf_router_lsa_body_set(struct stream **s, struct ospf_area *area)
 {
        unsigned long putp;
        uint16_t cnt;
 
        /* Set flags. */
-       stream_putc(s, router_lsa_flags(area));
+       stream_putc(*s, router_lsa_flags(area));
 
        /* Set Zero fields. */
-       stream_putc(s, 0);
+       stream_putc(*s, 0);
 
        /* Keep pointer to # links. */
-       putp = stream_get_endp(s);
+       putp = stream_get_endp(*s);
 
        /* Forward word */
-       stream_putw(s, 0);
+       stream_putw(*s, 0);
 
        /* Set all link information. */
        cnt = router_lsa_link_set(s, area);
 
        /* Set # of links here. */
-       stream_putw_at(s, putp, cnt);
+       stream_putw_at(*s, putp, cnt);
 }
 
 static int ospf_stub_router_timer(struct thread *t)
@@ -773,7 +785,7 @@ static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area)
                       OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
 
        /* Set router-LSA body fields. */
-       ospf_router_lsa_body_set(s, area);
+       ospf_router_lsa_body_set(&s, area);
 
        /* Set length. */
        length = stream_get_endp(s);
@@ -781,17 +793,13 @@ static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area)
        lsah->length = htons(length);
 
        /* Now, create OSPF LSA instance. */
-       if ((new = ospf_lsa_new()) == NULL) {
-               zlog_err("%s: Unable to create new lsa", __func__);
-               return NULL;
-       }
+       new = ospf_lsa_new_and_data(length);
 
        new->area = area;
        SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
        new->vrf_id = area->ospf->vrf_id;
 
        /* Copy LSA data to store, discard stream. */
-       new->data = ospf_lsa_data_new(length);
        memcpy(new->data, lsah, length);
        stream_free(s);
 
@@ -997,17 +1005,13 @@ static struct ospf_lsa *ospf_network_lsa_new(struct ospf_interface *oi)
        lsah->length = htons(length);
 
        /* Create OSPF LSA instance. */
-       if ((new = ospf_lsa_new()) == NULL) {
-               zlog_err("%s: ospf_lsa_new returned NULL", __func__);
-               return NULL;
-       }
+       new = ospf_lsa_new_and_data(length);
 
        new->area = oi->area;
        SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
        new->vrf_id = oi->ospf->vrf_id;
 
        /* Copy LSA to store. */
-       new->data = ospf_lsa_data_new(length);
        memcpy(new->data, lsah, length);
        stream_free(s);
 
@@ -1181,13 +1185,12 @@ static struct ospf_lsa *ospf_summary_lsa_new(struct ospf_area *area,
        lsah->length = htons(length);
 
        /* Create OSPF LSA instance. */
-       new = ospf_lsa_new();
+       new = ospf_lsa_new_and_data(length);
        new->area = area;
        SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
        new->vrf_id = area->ospf->vrf_id;
 
        /* Copy LSA to store. */
-       new->data = ospf_lsa_data_new(length);
        memcpy(new->data, lsah, length);
        stream_free(s);
 
@@ -1323,13 +1326,12 @@ static struct ospf_lsa *ospf_summary_asbr_lsa_new(struct ospf_area *area,
        lsah->length = htons(length);
 
        /* Create OSPF LSA instance. */
-       new = ospf_lsa_new();
+       new = ospf_lsa_new_and_data(length);
        new->area = area;
        SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
        new->vrf_id = area->ospf->vrf_id;
 
        /* Copy LSA to store. */
-       new->data = ospf_lsa_data_new(length);
        memcpy(new->data, lsah, length);
        stream_free(s);
 
@@ -1629,14 +1631,13 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf,
        lsah->length = htons(length);
 
        /* Now, create OSPF LSA instance. */
-       new = ospf_lsa_new();
+       new = ospf_lsa_new_and_data(length);
        new->area = NULL;
        SET_FLAG(new->flags,
                 OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED);
        new->vrf_id = ospf->vrf_id;
 
        /* Copy LSA data to store, discard stream. */
-       new->data = ospf_lsa_data_new(length);
        memcpy(new->data, lsah, length);
        stream_free(s);
 
index f8f7b28d4ed1a17c7d8bd4c903aae5c7e86cea14..ba4c4c1cacf7e2489e42ffc5046017f039039151 100644 (file)
@@ -235,6 +235,7 @@ extern int ospf_check_nbr_status(struct ospf *);
 
 /* Prototype for LSA primitive. */
 extern struct ospf_lsa *ospf_lsa_new(void);
+extern struct ospf_lsa *ospf_lsa_new_and_data(size_t size);
 extern struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *);
 extern void ospf_lsa_free(struct ospf_lsa *);
 extern struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *);
index 6dadc05bbab42bcaa95d84d3ae5479ba3f3a2df8..8853802d07e58b3ab1d1f57d08e91eb166589091 100644 (file)
@@ -49,6 +49,7 @@
 #include "ospfd/ospf_lsdb.h"
 #include "ospfd/ospf_neighbor.h"
 #include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_route.h"
 #include "ospfd/ospf_zebra.h"
 #include "ospfd/ospf_vty.h"
 #include "ospfd/ospf_bfd.h"
index f1d4a39dba82d06e1262e26ebbd522bd907918dd..56b83d22d5b7ca9f84d41f1de34959999b4737cb 100644 (file)
@@ -1742,7 +1742,7 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr,
                }
 
                /* Create OSPF LSA instance. */
-               lsa = ospf_lsa_new();
+               lsa = ospf_lsa_new_and_data(length);
 
                lsa->vrf_id = oi->ospf->vrf_id;
                /* We may wish to put some error checking if type NSSA comes in
@@ -1761,7 +1761,6 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr,
                        break;
                }
 
-               lsa->data = ospf_lsa_data_new(length);
                memcpy(lsa->data, lsah, length);
 
                if (IS_DEBUG_OSPF_EVENT)
index fa7dd04d19f800f6a48a408a7eb8fbb7330dff1a..c9d0a53c8dc1cf42c7504866d4fb8b2ab808508c 100644 (file)
@@ -775,18 +775,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new()
        lsah->length = htons(length);
 
        /* Now, create an OSPF LSA instance. */
-       if ((new = ospf_lsa_new()) == NULL) {
-               zlog_warn("ospf_router_info_lsa_new: ospf_lsa_new() ?");
-               stream_free(s);
-               return NULL;
-       }
-       if ((new->data = ospf_lsa_data_new(length)) == NULL) {
-               zlog_warn("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
-               ospf_lsa_unlock(&new);
-               new = NULL;
-               stream_free(s);
-               return new;
-       }
+       new = ospf_lsa_new_and_data(length);
 
        new->area = OspfRI.area; /* Area must be null if the Opaque type is AS
                                    scope, fulfill otherwise */
index c90db031dcf2f2137687d2cf81da53bc8e122980..19d2e6a95251f4fb1de862a5c56bda0105842370 100644 (file)
@@ -47,6 +47,7 @@
 #include "ospfd/ospf_flood.h"
 #include "ospfd/ospf_ism.h"
 #include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_route.h"
 #include "ospfd/ospf_zebra.h"
 
 /* OSPF2-MIB. */
index cc2d9282fe14c024427fef124a237345364ba7b4..a9dc1c18e392e110701acbbdc991215a6bf25fd7 100644 (file)
@@ -1201,18 +1201,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf *ospf,
        lsah->length = htons(length);
 
        /* Now, create an OSPF LSA instance. */
-       if ((new = ospf_lsa_new()) == NULL) {
-               zlog_warn("%s: ospf_lsa_new() ?", __func__);
-               stream_free(s);
-               return NULL;
-       }
-       if ((new->data = ospf_lsa_data_new(length)) == NULL) {
-               zlog_warn("%s: ospf_lsa_data_new() ?", __func__);
-               ospf_lsa_unlock(&new);
-               new = NULL;
-               stream_free(s);
-               return new;
-       }
+       new = ospf_lsa_new_and_data(length);
 
        new->vrf_id = ospf->vrf_id;
        if (area && area->ospf)
index 0a7776cced054c5dac2eb563530f0e3c80c46b7f..8c94a8ef9949bde227fa446aa0b05d7014a7e82e 100644 (file)
@@ -111,10 +111,11 @@ static int ospf_interface_add(int command, struct zclient *zclient,
 
        if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
                zlog_debug(
-                       "Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d",
+                       "Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d speed %u",
                        ifp->name, ospf_vrf_id_to_name(ifp->vrf_id),
                        ifp->vrf_id, ifp->ifindex,
-                       (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
+                       (unsigned long long)ifp->flags, ifp->metric, ifp->mtu,
+                       ifp->speed);
 
        assert(ifp->info);
 
@@ -128,6 +129,8 @@ static int ospf_interface_add(int command, struct zclient *zclient,
        if (!ospf)
                return 0;
 
+       ospf_if_recalculate_output_cost(ifp);
+
        ospf_if_update(ospf, ifp);
 
        hook_call(ospf_if_update, ifp);
@@ -448,14 +451,17 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
                count++;
 
                if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
-                       char buf[2][PREFIX2STR_BUFFER];
+                       char buf[2][INET_ADDRSTRLEN];
+                       struct interface *ifp;
+
+                       ifp = if_lookup_by_index(path->ifindex, ospf->vrf_id);
 
                        zlog_debug(
-                               "Zebra: Route add %s nexthop %s, ifindex=%d",
+                               "Zebra: Route add %s nexthop %s, ifindex=%d %s",
                                prefix2str(p, buf[0], sizeof(buf[0])),
                                inet_ntop(AF_INET, &path->nexthop,
                                          buf[1], sizeof(buf[1])),
-                               path->ifindex);
+                               path->ifindex, ifp ? ifp->name : " ");
                }
        }
        api.nexthop_num = count;
index ac8f0d92c322b988aa9a331676603185e2878269..bfaedf2fe70236495ac6906007a923df275017f2 100644 (file)
 #include "ospfd/ospf_spf.h"
 #include "ospfd/ospf_packet.h"
 #include "ospfd/ospf_dump.h"
+#include "ospfd/ospf_route.h"
 #include "ospfd/ospf_zebra.h"
 #include "ospfd/ospf_abr.h"
 #include "ospfd/ospf_flood.h"
-#include "ospfd/ospf_route.h"
 #include "ospfd/ospf_ase.h"
 
 
index 7c45ce261a48ae779711236bd374d4c9d2f67c1b..611d8d36811af5b631300f324e955add2458234a 100644 (file)
@@ -323,8 +323,8 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty,
        char addr_str[INET_ADDRSTRLEN];
        struct pim_assert_metric *am;
        struct in_addr ifaddr;
-       char pref_str[5];
-       char metr_str[7];
+       char pref_str[16];
+       char metr_str[16];
 
        ifaddr = pim_ifp->primary_address;
 
index e79e91d7dfb943fecffadfd848befb3e694c5719..72ccf3ab1ea4de84e5c6ccbebdecc597949826f9 100644 (file)
@@ -1495,14 +1495,6 @@ int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
        return 0;
 }
 
-bool pim_if_is_loopback(struct interface *ifp)
-{
-       if (if_is_loopback(ifp) || if_is_vrf(ifp))
-               return true;
-
-       return false;
-}
-
 bool pim_if_is_vrf_device(struct interface *ifp)
 {
        if (if_is_vrf(ifp))
index cf025cbd4a27be279c825f24d6d39f77c13de767..02926a6973be2cb4f8fec545013c13dc4f7e91cf 100644 (file)
@@ -207,8 +207,6 @@ void pim_if_create_pimreg(struct pim_instance *pim);
 int pim_if_connected_to_source(struct interface *ifp, struct in_addr src);
 int pim_update_source_set(struct interface *ifp, struct in_addr source);
 
-bool pim_if_is_loopback(struct interface *ifp);
-
 bool pim_if_is_vrf_device(struct interface *ifp);
 
 int pim_if_ifchannel_count(struct pim_interface *pim_ifp);
index 92a78c4bb4b43a3509157e65bc2f8b48a9b98399..3137345037061ec78adebaf04f067956443d1269 100644 (file)
@@ -174,7 +174,16 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
           ifchannel list is empty before deleting upstream_del
           ref count will take care of it.
        */
-       pim_upstream_del(pim_ifp->pim, ch->upstream, __PRETTY_FUNCTION__);
+       if (ch->upstream->ref_count > 0)
+               pim_upstream_del(pim_ifp->pim, ch->upstream,
+                       __PRETTY_FUNCTION__);
+
+       else
+               zlog_warn("%s: Avoiding deletion of upstream with ref_count %d "
+                       "from ifchannel(%s): %s", __PRETTY_FUNCTION__,
+                       ch->upstream->ref_count, ch->interface->name,
+                       ch->sg_str);
+
        ch->upstream = NULL;
 
        THREAD_OFF(ch->t_ifjoin_expiry_timer);
index f0f336fb7308ccbfb02330fa8f31235d313b93ef..a0debc0c78f86a0994f9c751fe96c872005714f3 100644 (file)
 
 char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
 {
+       char *out;
        struct prefix_sg sg;
        int i;
 
        sg.src = c_oil->oil.mfcc_origin;
        sg.grp = c_oil->oil.mfcc_mcastgrp;
-       sprintf(buf, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
-               c_oil->oil.mfcc_parent);
+       snprintf(buf, size, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
+                c_oil->oil.mfcc_parent);
 
+       out = buf + strlen(buf);
        for (i = 0; i < MAXVIFS; i++) {
                if (c_oil->oil.mfcc_ttls[i] != 0) {
-                       char buf1[10];
-                       sprintf(buf1, "%d ", i);
-                       strcat(buf, buf1);
+                       snprintf(out, buf + size - out, "%d ", i);
+                       out += strlen(out);
                }
        }
 
index b103da2e1b53410b22df76a31479deb0be39e345..7113d5405ec31dc9b8c559dea855708e7361a484 100644 (file)
@@ -655,7 +655,7 @@ static int pim_hello_send(struct interface *ifp, uint16_t holdtime)
 {
        struct pim_interface *pim_ifp = ifp->info;
 
-       if (pim_if_is_loopback(ifp))
+       if (if_is_loopback_or_vrf(ifp))
                return 0;
 
        if (hello_send(ifp, holdtime)) {
@@ -757,7 +757,7 @@ void pim_hello_restart_triggered(struct interface *ifp)
        /*
         * No need to ever start loopback or vrf device hello's
         */
-       if (pim_if_is_loopback(ifp))
+       if (if_is_loopback_or_vrf(ifp))
                return;
 
        /*
index db89125a98244a3d6be0d7b21f453bb5255c86bb..15cbf6fbc331f5ac464c118063c81237e9a9e889 100644 (file)
@@ -167,6 +167,8 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
                        up->ref_count, up->flags,
                        up->channel_oil->oil_ref_count);
 
+        assert(up->ref_count > 0);
+
        --up->ref_count;
 
        if (up->ref_count >= 1)
index 50711b13b727309b23e8bf4e44d24afdd4f9325d..a7b51a5656f8603e906f0e2e8f01ad493dd4aa8d 100644 (file)
@@ -31,7 +31,7 @@ Commands defined by this snap
 - `frr.readme`:
        Returns this document `cat README_usage.md`
 - `frr.set`:
-       Allows to enable `FPM` module. See FPM section below
+       Allows to enable `FPM` and/or disable RPKIi module. See Module section below
 
 and for debugging defined at this time (May get removed later - do not 
 depend on them). These are mainly intended to debug the Snap
@@ -100,13 +100,13 @@ are named `eth0`, `eth1` and `eth2`, then the additional lines in
 These settings require either a reboot or a manual configuration with
 `sysctl` as well.
 
-FPM Module
+Modules
 ----------
-The `frr.set` allows to turn FPM module on or off.
+The `frr.set` allows to turn FPM module ond the RPKI module on or off.
 
     frr.set fpm {disable|protobuf|netlink}
     
-    Disables FPM or enables FPM with selected mode
+    Disables FPM or enables FPM with selected mode (default: disabled)
 
 By default, the FPM module is disabled, but installed with netlink and
 protobuf support. To enable the FPM module, use the `frr.set fpm protobuf`
@@ -114,6 +114,17 @@ or `frr.set fpm netlink` command. The command will only enable the mode
 for the next restart of zebra. Please reboot or restart zebra after
 changing the mode to become effective.
 
+    frr.set rpki {enable|disable}
+   
+    Disables or enables BGP RPKI (default: enabled)
+
+By default, the RPKI module is enabled. To disable the RPKI module
+use the `frr.set rpki disable` command. The command will only enable
+the module after the next restart of the bgp daemon. Please reboot or 
+restart bgpd after changing the mode to become effective.
+(Normally, there is no need to disable the module as it has no effect
+if there are no RPKI configurations in BGP)
+
 FAQ
 ---
 - frr.vtysh displays `--MORE--` on long output. How to suppress this?
index 4072031eda21faaa0f744d79c29bb358669e3a27..6c3a6f595955a913b54028ce5d90037e465b6037 100644 (file)
@@ -5,9 +5,16 @@ set -e -x
 if ! [ -e $SNAP_DATA/bgpd.conf ]; then
     cp $SNAP/etc/frr/bgpd.conf.default $SNAP_DATA/bgpd.conf
 fi
+# If no RPKI option is specified, then we create a default
+# with RPKI enabled
+if ! [ -e $SNAP_DATA/rpki.conf ]; then
+    echo "-M rpki" > $SNAP_DATA/rpki.conf
+fi
+EXTRA_OPTIONS="`cat $SNAP_DATA/rpki.conf`"
 exec $SNAP/sbin/bgpd \
     -f $SNAP_DATA/bgpd.conf \
     --pid_file $SNAP_DATA/bgpd.pid \
     --socket $SNAP_DATA/zsock \
-    --vty_socket $SNAP_DATA
+    --vty_socket $SNAP_DATA \
+    --moduledir $SNAP/lib/frr/modules $EXTRA_OPTIONS
 
index e76e321ef80c886f9e24034a9543ef1789897716..0637d2ce5dd6f1b80a2e3c960c62fa8715078e29 100755 (executable)
@@ -28,11 +28,34 @@ case $1 in
                 ;;
         esac
         ;;
+    rpki)
+        case $2 in
+            disable)
+                echo "" > $SNAP_DATA/rpki.conf
+                echo "RPKI module disabled. Please restart FRR"
+                ;;
+            enable)
+                echo "-M rpki" > $SNAP_DATA/rpki.conf
+                echo "RPKI module enabled. Please restart FRR"
+                ;;
+            *)
+                echo "Usage:"
+                echo "    ${SNAP_NAME}.set rpki {disable|enable}"
+                echo ""
+                echo "    Disables BGP RPKI module or enables it (default: enabled)"
+                echo "    Mode will be saved for next restart of bgpd, but bgpd"
+                echo "    is not automatically restarted"
+                exit 1
+                ;;
+        esac
+        ;;
     *)
         echo "Usage:"
         echo "    ${SNAP_NAME}.set fpm {disable|protobuf|netlink}"
+        echo "    ${SNAP_NAME}.set rpki {disable|enable}"
         echo ""
-        echo "    Disables FPM or enables FPM with selected mode"
+        echo "    fpm: Disables FPM or enables FPM with selected mode"
+        echo "    rpki: Disables BGP RPKI or enables it (default: enabled)"
         exit 1
         ;;
 esac
index 563a05c5a790cf6f33bfe4b60491c4149b0fe19d..b70d6efee2c094dba976ad2a841c0faf240301f6 100644 (file)
@@ -136,7 +136,7 @@ apps:
             - network-bind
             - network-control
     bgpd-debug:
-        command: sbin/bgpd -f $SNAP_DATA/bgpd.conf --pid_file $SNAP_DATA/bgpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA
+        command: sbin/bgpd -f $SNAP_DATA/bgpd.conf --pid_file $SNAP_DATA/bgpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA --moduledir $SNAP/lib/frr/modules `cat $SNAP_DATA/rpki.conf 2> /dev/null`
         plugs:
             - network
             - network-bind
@@ -221,8 +221,27 @@ apps:
             - network-control
 
 parts:
+    rtrlib:
+        build-packages:
+           - cmake
+           - make
+           - gcc
+           - libssh-dev
+        stage-packages:
+           - libssh-4
+        prime:
+           - lib/x86_64-linux-gnu/librtr.so*
+           - usr/lib/x86_64-linux-gnu/libssh.so*
+        source: https://github.com/rtrlib/rtrlib.git
+        source-type: git
+        source-tag: v0.5.0
+        plugin: cmake
+        configflags:
+           - -DCMAKE_BUILD_TYPE=Release
     frr: 
-        build-packages: 
+        after: [rtrlib]
+        build-packages:
+           - gcc
            - autoconf
            - automake
            - libtool
@@ -247,6 +266,7 @@ parts:
            - flex
            - python3-dev
            - protobuf-c-compiler
+           - python3-sphinx
         stage-packages:
            - coreutils
            - iproute2
@@ -276,6 +296,7 @@ parts:
             - --enable-ldpd
             - --enable-fpm
             - --enable-protobuf
+            - --enable-rpki
             - --enable-configfile-mask=0640
             - --enable-logfile-mask=0640 
             - --localstatedir=/var/run
index 98153f71497d7ba34d2f3d0fd37f4699e71d836a..771d8d1de37a5c0cbe445ca122b54c90c97eca0e 100644 (file)
@@ -766,7 +766,7 @@ DEFPY(ip_route_blackhole,
       "Table to configure\n"
       "The table number to configure\n")
 {
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -805,7 +805,7 @@ DEFPY(ip_route_blackhole_vrf,
        VTY_DECLVAR_CONTEXT(vrf, vrf);
        struct static_vrf *svrf = vrf->info;
 
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && !vrf_is_mapped_on_netns(vrf)) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -868,7 +868,7 @@ DEFPY(ip_route_address_interface,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -924,7 +924,7 @@ DEFPY(ip_route_address_interface_vrf,
        struct static_vrf *svrf = vrf->info;
        struct static_vrf *nh_svrf;
 
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && !vrf_is_mapped_on_netns(vrf)) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -984,7 +984,7 @@ DEFPY(ip_route,
        struct static_vrf *nh_svrf;
        const char *flag = NULL;
 
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -1049,7 +1049,7 @@ DEFPY(ip_route_vrf,
        struct static_vrf *nh_svrf;
        const char *flag = NULL;
 
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && !vrf_is_mapped_on_netns(vrf)) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -1104,7 +1104,7 @@ DEFPY(ipv6_route_blackhole,
       "Table to configure\n"
       "The table number to configure\n")
 {
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -1144,7 +1144,7 @@ DEFPY(ipv6_route_blackhole_vrf,
        VTY_DECLVAR_CONTEXT(vrf, vrf);
        struct static_vrf *svrf = vrf->info;
 
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && !vrf_is_mapped_on_netns(vrf)) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -1195,7 +1195,7 @@ DEFPY(ipv6_route_address_interface,
        struct static_vrf *svrf;
        struct static_vrf *nh_svrf;
 
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -1255,7 +1255,7 @@ DEFPY(ipv6_route_address_interface_vrf,
        struct static_vrf *svrf = vrf->info;
        struct static_vrf *nh_svrf;
 
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && !vrf_is_mapped_on_netns(vrf)) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -1309,7 +1309,7 @@ DEFPY(ipv6_route,
        struct static_vrf *svrf;
        struct static_vrf *nh_svrf;
 
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
@@ -1368,7 +1368,7 @@ DEFPY(ipv6_route_vrf,
        struct static_vrf *svrf = vrf->info;
        struct static_vrf *nh_svrf;
 
-       if (table_str && !vrf_is_backend_netns()) {
+       if (table_str && !vrf_is_mapped_on_netns(vrf)) {
                vty_out(vty,
                        "%% table param only available when running on netns-based vrfs\n");
                return CMD_WARNING_CONFIG_FAILED;
index f3175e91faf3569e7f6e80be66020a5b78b1383a..a87dc074dfc07e2d5f1bfcd41adae3917dc2dde2 100644 (file)
@@ -34,6 +34,7 @@
 #include "log.h"
 #include "nexthop.h"
 #include "nexthop_group.h"
+#include "hash.h"
 
 #include "static_vrf.h"
 #include "static_routes.h"
@@ -43,6 +44,7 @@
 
 /* Zebra structure to hold current status. */
 struct zclient *zclient;
+static struct hash *static_nht_hash;
 
 static struct interface *zebra_interface_if_lookup(struct stream *s)
 {
@@ -176,10 +178,16 @@ static void zebra_connected(struct zclient *zclient)
        zclient_send_reg_requests(zclient, VRF_DEFAULT);
 }
 
+struct static_nht_data {
+       struct prefix *nh;
+       uint32_t refcount;
+       uint8_t nh_num;
+};
 
 static int static_zebra_nexthop_update(int command, struct zclient *zclient,
                                       zebra_size_t length, vrf_id_t vrf_id)
 {
+       struct static_nht_data *nhtd, lookup;
        struct zapi_route nhr;
        afi_t afi = AFI_IP;
 
@@ -191,6 +199,14 @@ static int static_zebra_nexthop_update(int command, struct zclient *zclient,
        if (nhr.prefix.family == AF_INET6)
                afi = AFI_IP6;
 
+       memset(&lookup, 0, sizeof(lookup));
+       lookup.nh = &nhr.prefix;
+
+       nhtd = hash_lookup(static_nht_hash, &lookup);
+       if (nhtd)
+               nhtd->nh_num = nhr.nexthop_num;
+
+
        static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, vrf_id);
        return 1;
 }
@@ -200,10 +216,50 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap)
        mpls_enabled = cap->mpls_enabled;
 }
 
+static unsigned int static_nht_hash_key(void *data)
+{
+       struct static_nht_data *nhtd = data;
+
+       return prefix_hash_key(nhtd->nh);
+}
+
+static int static_nht_hash_cmp(const void *d1, const void *d2)
+{
+       const struct static_nht_data *nhtd1 = d1;
+       const struct static_nht_data *nhtd2 = d2;
+
+       return prefix_same(nhtd1->nh, nhtd2->nh);
+}
+
+static void *static_nht_hash_alloc(void *data)
+{
+       struct static_nht_data *copy = data;
+       struct static_nht_data *new;
+
+       new = XMALLOC(MTYPE_TMP, sizeof(*new));
+
+       new->nh = prefix_new();
+       prefix_copy(new->nh, copy->nh);
+       new->refcount = 0;
+       new->nh_num = 0;
+
+       return new;
+}
+
+static void static_nht_hash_free(void *data)
+{
+       struct static_nht_data *nhtd = data;
+
+       prefix_free(nhtd->nh);
+       XFREE(MTYPE_TMP, nhtd);
+}
+
 void static_zebra_nht_register(struct static_route *si, bool reg)
 {
+       struct static_nht_data *nhtd, lookup;
        uint32_t cmd;
        struct prefix p;
+       afi_t afi = AFI_IP;
 
        cmd = (reg) ?
                ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
@@ -224,20 +280,48 @@ void static_zebra_nht_register(struct static_route *si, bool reg)
                p.family = AF_INET;
                p.prefixlen = IPV4_MAX_BITLEN;
                p.u.prefix4 = si->addr.ipv4;
+               afi = AFI_IP;
                break;
        case STATIC_IPV6_GATEWAY:
        case STATIC_IPV6_GATEWAY_IFNAME:
                p.family = AF_INET6;
                p.prefixlen = IPV6_MAX_BITLEN;
                p.u.prefix6 = si->addr.ipv6;
+               afi = AFI_IP6;
                break;
        }
 
+       memset(&lookup, 0, sizeof(lookup));
+       lookup.nh = &p;
+
+       si->nh_registered = reg;
+
+       if (reg) {
+               nhtd = hash_get(static_nht_hash, &lookup,
+                               static_nht_hash_alloc);
+               nhtd->refcount++;
+
+               if (nhtd->refcount > 1) {
+                       static_nht_update(nhtd->nh, nhtd->nh_num,
+                                         afi, si->nh_vrf_id);
+                       return;
+               }
+       } else {
+               nhtd = hash_lookup(static_nht_hash, &lookup);
+               if (!nhtd)
+                       return;
+
+               nhtd->refcount--;
+               if (nhtd->refcount >= 1)
+                       return;
+
+               hash_release(static_nht_hash, nhtd);
+               static_nht_hash_free(nhtd);
+       }
+
        if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0)
                zlog_warn("%s: Failure to send nexthop to zebra",
                          __PRETTY_FUNCTION__);
-
-       si->nh_registered = reg;
 }
 
 extern void static_zebra_route_add(struct route_node *rn,
@@ -273,9 +357,10 @@ extern void static_zebra_route_add(struct route_node *rn,
                SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
                api.tag = si_changed->tag;
        }
-       api.tableid = si_changed->table_id;
-
-       zlog_debug("Distance sent down: %d %d", si_changed->distance, install);
+       if (si_changed->table_id != 0) {
+               SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
+               api.tableid = si_changed->table_id;
+       }
        for (/*loaded above*/; si; si = si->next) {
                api_nh = &api.nexthops[nh_num];
                if (si->nh_vrf_id == VRF_UNKNOWN)
@@ -372,4 +457,8 @@ void static_zebra_init(void)
        zclient->interface_address_delete = interface_address_delete;
        zclient->route_notify_owner = route_notify_owner;
        zclient->nexthop_update = static_zebra_nexthop_update;
+
+       static_nht_hash = hash_create(static_nht_hash_key,
+                                     static_nht_hash_cmp,
+                                     "Static Nexthop Tracking hash");
 }
index 4612bdc26b0adc737e792c74c2255639153433a0..fef7d39ff5904923733dbcc45c26c16d5d977cbc 100644 (file)
@@ -821,7 +821,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
        switch (type) {
        case CAPABILITY:
                len += 2; /* to cover the OPT-Param header */
-               __attribute__ ((fallthrough));
+               _FALLTHROUGH
        case OPT_PARAM:
                printf("len: %u\n", len);
                /* peek_for_as4 wants getp at capibility*/
index 5dc751a1b252f1048fc29274a37a42067d2bda59..2ecfc879428427451a33d93a2006f28a6c0ce9dc 100644 (file)
@@ -57,7 +57,7 @@ int main(void)
 
        print_stream(s);
 
-       stream_resize(s, stream_get_endp(s));
+       stream_resize_inplace(&s, stream_get_endp(s));
 
        print_stream(s);
 
index ef4d1a083506fcc83d89a57b00d069a2a2688dfc..c249115fd372d8468cb2e5f887c98f6ddc70912b 100644 (file)
@@ -1435,24 +1435,6 @@ DEFUNSH(VTYSH_BGPD,
        return CMD_SUCCESS;
 }
 
-DEFUNSH(VTYSH_BGPD,
-       rpki_exit,
-       rpki_exit_cmd,
-       "exit",
-       "Exit current mode and down to previous mode\n")
-{
-       vty->node = CONFIG_NODE;
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_BGPD,
-       rpki_quit,
-       rpki_quit_cmd,
-       "quit",
-       "Exit current mode and down to previous mode\n")
-{
-       return rpki_exit(self, vty, argc, argv);
-}
 #endif
 
 DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
@@ -1790,6 +1772,7 @@ static int vtysh_exit(struct vty *vty)
        case VTY_NODE:
        case KEYCHAIN_NODE:
        case BFD_NODE:
+       case RPKI_NODE:
                vtysh_execute("end");
                vtysh_execute("configure terminal");
                vty->node = CONFIG_NODE;
@@ -1883,7 +1866,23 @@ DEFUNSH(VTYSH_BGPD, exit_vnc_config, exit_vnc_config_cmd, "exit-vnc",
            || vty->node == BGP_VNC_L2_GROUP_NODE)
                vty->node = BGP_NODE;
        return CMD_SUCCESS;
+
+}
+
+#if defined(HAVE_RPKI)
+DEFUNSH(VTYSH_BGPD, rpki_exit, rpki_exit_cmd, "exit",
+       "Exit current mode and down to previous mode\n")
+{
+       vtysh_exit(vty);
+       return CMD_SUCCESS;
+}
+
+DEFUNSH(VTYSH_BGPD, rpki_quit, rpki_quit_cmd, "quit",
+       "Exit current mode and down to previous mode\n")
+{
+       return rpki_exit(self, vty, argc, argv);
 }
+#endif /* HAVE_RPKI */
 
 DEFUNSH(VTYSH_PIMD|VTYSH_ZEBRA, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf",
        "Exit from VRF configuration mode\n")
diff --git a/zebra/GNOME-PRODUCT-ZEBRA-MIB b/zebra/GNOME-PRODUCT-ZEBRA-MIB
deleted file mode 100644 (file)
index 96bcec5..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-GNOME-PRODUCT-ZEBRA-MIB DEFINITIONS ::= BEGIN\r
-\r
-IMPORTS\r
-       MODULE-IDENTITY,\r
-       OBJECT-IDENTITY\r
-               FROM SNMPv2-SMI\r
-       gnomeProducts\r
-               FROM GNOME-SMI;\r
-\r
-zebra MODULE-IDENTITY\r
-       LAST-UPDATED "200004250000Z"\r
-       ORGANIZATION "GNOME project"\r
-       CONTACT-INFO\r
-               "GNU Network Object Model Environment project\r
-               \r
-               see http://www.gnome.org for contact persons of a particular\r
-               area or subproject of GNOME.\r
-\r
-               Administrative contact for MIB module:\r
-\r
-               Jochen Friedrich\r
-               Wingertstr. 70/1\r
-               68809 Neulussheim\r
-               Germany \r
-\r
-               email: snmp@gnome.org"\r
-       DESCRIPTION\r
-               "The product registrations for the various zebra subdeamons.\r
-               These registrations are guaranteed to be unique and are used\r
-               for SMUX registration by default (if not overridden manually)."\r
-       ::= { gnomeProducts 2 }\r
-\r
-zserv OBJECT-IDENTITY\r
-       STATUS  current\r
-       DESCRIPTION\r
-               "zserv is part of the zebra project which again is a GNU\r
-               endorsed internet routing program.\r
-               zserv is the main zebra process which implements routing\r
-               entries with the kernel and handles routing updates between\r
-               other routing protocols."\r
-       ::= { zebra 1 }\r
-\r
-bgpd OBJECT-IDENTITY\r
-       STATUS  current\r
-       DESCRIPTION\r
-               "bgpd is part of the zebra project which again is a GNU\r
-               endorsed internet routing program."\r
-       ::= { zebra 2 }\r
-\r
-ripd OBJECT-IDENTITY\r
-       STATUS  current\r
-       DESCRIPTION\r
-               "ripd is part of the zebra project which again is a GNU\r
-               endorsed internet routing program."\r
-       ::= { zebra 3 }\r
-\r
-ripngd OBJECT-IDENTITY\r
-       STATUS  current\r
-       DESCRIPTION\r
-               "ripngd is part of the zebra project which again is a GNU\r
-               endorsed internet routing program."\r
-       ::= { zebra 4 }\r
-\r
-ospfd OBJECT-IDENTITY\r
-       STATUS  current\r
-       DESCRIPTION\r
-               "ospfd is part of the zebra project which again is a GNU\r
-               endorsed internet routing program."\r
-       ::= { zebra 5 }\r
-\r
-ospf6d OBJECT-IDENTITY\r
-       STATUS  current\r
-       DESCRIPTION\r
-               "ospf6d is part of the zebra project which again is a GNU\r
-               endorsed internet routing program."\r
-       ::= { zebra 6 }\r
-\r
-END\r
diff --git a/zebra/GNOME-SMI b/zebra/GNOME-SMI
deleted file mode 100644 (file)
index 164732b..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-GNOME-SMI DEFINITIONS ::= BEGIN\r
-\r
-IMPORTS\r
-       MODULE-IDENTITY,\r
-       OBJECT-IDENTITY,\r
-       enterprises\r
-               FROM SNMPv2-SMI;\r
-\r
-gnome MODULE-IDENTITY\r
-       LAST-UPDATED "9809010000Z"\r
-       ORGANIZATION "GNOME project"\r
-       CONTACT-INFO\r
-               "GNU Network Object Model Environment project\r
-               \r
-               see http://www.gnome.org for contact persons of a particular\r
-               area or subproject of GNOME.\r
-\r
-               Administrative contact for MIB module:\r
-\r
-               Jochen Friedrich\r
-               Wingertstr. 70/1\r
-               68809 Neulussheim\r
-               Germany \r
-\r
-               email: snmp@gnome.org"\r
-       DESCRIPTION\r
-               "The Structure of GNOME."\r
-       ::= { enterprises 3317 }        -- assigned by IANA\r
-\r
-gnomeProducts OBJECT-IDENTITY\r
-       STATUS  current\r
-       DESCRIPTION\r
-               "gnomeProducts is the root OBJECT IDENTIFIER from\r
-               which sysObjectID values are assigned."\r
-       ::= { gnome 1 }\r
-\r
-gnomeMgmt OBJECT-IDENTITY\r
-       STATUS  current\r
-       DESCRIPTION\r
-               "gnomeMgmt defines the subtree for production GNOME related\r
-               MIB registrations."\r
-       ::= { gnome 2 }\r
-\r
-gnomeTest OBJECT-IDENTITY\r
-       STATUS  current\r
-       DESCRIPTION\r
-               "gnomeTest defines the subtree for testing GNOME related\r
-               MIB registrations."\r
-       ::= { gnome 3 }\r
-\r
--- more to come if necessary.\r
-\r
-END\r
diff --git a/zebra/client_main.c b/zebra/client_main.c
deleted file mode 100644 (file)
index 1ead7ee..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * GNU Zebra client test main routine.
- * Copyright (C) 1997 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra 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 "prefix.h"
-#include "stream.h"
-#include "zclient.h"
-#include "thread.h"
-#include "table.h"
-#include "zebra/rib.h"
-#include "zebra/zserv.h"
-
-struct thread *master;
-
-/* Zebra client structure. */
-struct zclient *zclient = NULL;
-
-/* Zebra socket. */
-int sock;
-
-/* IPv4 route add and delete test. */
-void zebra_test_ipv4(int command, int type, char *prefix, char *gateway,
-                    uint8_t distance)
-{
-       struct zapi_ipv4 api;
-       struct prefix_ipv4 p;
-       struct in_addr gate;
-       struct in_addr *gpnt;
-
-       str2prefix_ipv4(prefix, &p);
-       if (!inet_aton(gateway, &gate)) {
-               printf("Gateway specified: %s is illegal\n", gateway);
-               return;
-       }
-
-       gpnt = &gate;
-
-       api.vrf_id = VRF_DEFAULT;
-       api.type = type;
-       api.flags = 0;
-
-       api.message = 0;
-       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
-       api.nexthop_num = 1;
-       api.nexthop = &gpnt;
-       api.ifindex_num = 0;
-       if (distance) {
-               SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
-               api.distance = distance;
-       }
-
-
-       switch (command) {
-       case ZEBRA_IPV4_ROUTE_ADD:
-               zapi_ipv4_add(zclient, &p, &api);
-               break;
-       case ZEBRA_IPV4_ROUTE_DELETE:
-               zapi_ipv4_delete(zclient, &p, &api);
-               break;
-       }
-}
-
-/* IPv6 route add and delete test. */
-void zebra_test_v6(int sock)
-{
-       struct prefix_ipv6 p;
-       struct in6_addr nexthop;
-
-       str2prefix_ipv6("3ffe:506::2/128", &p);
-       inet_pton(AF_INET6, "::1", &nexthop);
-
-       /* zebra_ipv6_add (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */
-
-       sleep(5);
-       /* zebra_ipv6_delete (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */
-}
-
-/* Print out usage and exit. */
-void usage_exit()
-{
-       fprintf(stderr, "Usage: client filename\n");
-       exit(1);
-}
-
-struct zebra_info {
-       char *str;
-       int type;
-} zebra_type[] = {{"static", ZEBRA_ROUTE_STATIC},
-                 {"rip", ZEBRA_ROUTE_RIP},
-                 {"ripng", ZEBRA_ROUTE_RIPNG},
-                 {"ospf", ZEBRA_ROUTE_OSPF},
-                 {"ospf6", ZEBRA_ROUTE_OSPF6},
-                 {"bgp", ZEBRA_ROUTE_BGP},
-                 {"nhrp", ZEBRA_ROUTE_NHRP},
-                 {"pim", ZEBRA_ROUTE_PIM},
-                 {NULL, 0}};
-
-/* Zebra route simulator. */
-void zebra_sim(FILE *fp)
-{
-       char buf[BUFSIZ];
-       char distance_str[BUFSIZ];
-       uint8_t distance;
-
-       while (fgets(buf, sizeof buf, fp)) {
-               int i;
-               int ret;
-               int type;
-               char str[BUFSIZ], command[BUFSIZ], prefix[BUFSIZ],
-                       gateway[BUFSIZ];
-
-               distance = 0;
-
-               if (*buf == '#')
-                       continue;
-
-               type = ZEBRA_ROUTE_STATIC;
-
-               ret = sscanf(buf, "%s %s %s %s %s\n", command, str, prefix,
-                            gateway, distance_str);
-
-               if (ret == 5) {
-                       distance = atoi(distance_str);
-               } else {
-                       ret = sscanf(buf, "%s %s %s %s\n", command, str, prefix,
-                                    gateway);
-
-                       if (ret != 4)
-                               continue;
-               }
-
-               i = 0;
-               while (zebra_type[i++].str) {
-                       if (strcmp(zebra_type[i].str, str) == 0) {
-                               type = zebra_type[i].type;
-                               break;
-                       }
-               }
-
-               if (strcmp(command, "add") == 0) {
-                       zebra_test_ipv4(ZEBRA_IPV4_ROUTE_ADD, type, prefix,
-                                       gateway, distance);
-                       printf("%s", buf);
-                       continue;
-               }
-
-               if (strcmp(command, "del") == 0) {
-                       zebra_test_ipv4(ZEBRA_IPV4_ROUTE_DELETE, type, prefix,
-                                       gateway, distance);
-                       printf("%s", buf);
-                       continue;
-               }
-       }
-}
-
-/* Test zebra client main routine. */
-int main(int argc, char **argv)
-{
-       struct thread_master *master;
-       FILE *fp;
-
-       if (argc == 1)
-               usage_exit();
-
-       master = thread_master_create(NULL);
-       /* Establish connection to zebra. */
-       zclient = zclient_new_notify(master, &zclient_options_default);
-       zclient->enable = 1;
-       zclient_socket_connect(zclient);
-
-       /* Open simulation file. */
-       fp = fopen(argv[1], "r");
-       if (fp == NULL) {
-               fprintf(stderr,
-                       "%% Can't open configuration file %s due to '%s'\n",
-                       argv[1], safe_strerror(errno));
-               exit(1);
-       }
-
-       /* Do main work. */
-       zebra_sim(fp);
-
-       sleep(100);
-
-       fclose(fp);
-       close(sock);
-
-       return 0;
-}
index d17a9cf4986df3f18096dfc1bccbdff51bacb579..176bb2bbad591dda7fba121f171861af7cb29b46 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "zebra/interface.h"
 #include "zebra/rib.h"
+#include "zebra/rt.h"
 
 #include <ifaddrs.h>
 
index ef7c26c9dfbf30a9e5d7566c88192180014cf6be..545b4d9d6db868548a83cf12cca69ad321871435 100644 (file)
@@ -467,6 +467,18 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta,
        }
 }
 
+/**
+ * netlink_parse_rtattr_nested() - Parses a nested route attribute
+ * @tb:         Pointer to array for storing rtattr in.
+ * @max:        Max number to store.
+ * @rta:        Pointer to rtattr to look for nested items in.
+ */
+void netlink_parse_rtattr_nested(struct rtattr **tb, int max,
+                                struct rtattr *rta)
+{
+       netlink_parse_rtattr(tb, max, RTA_DATA(rta), RTA_PAYLOAD(rta));
+}
+
 int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
              const void *data, unsigned int alen)
 {
index 65df15599d134fdf421645d6be6364c24eaa2c7b..af0cc83f4ab99bc68dc34198bcbfd49c4c371a47 100644 (file)
@@ -28,6 +28,8 @@
 
 extern void netlink_parse_rtattr(struct rtattr **tb, int max,
                                 struct rtattr *rta, int len);
+extern void netlink_parse_rtattr_nested(struct rtattr **tb, int max,
+                                       struct rtattr *rta);
 extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
                     const void *data, unsigned int alen);
 extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
index e3101fbe72c262bcfce9116ddb8020553680e28b..640d58e17e83595722cf752a009a9cb58a4aa5f3 100644 (file)
@@ -715,7 +715,7 @@ int zebra_import_table_config(struct vty *vty)
        return write;
 }
 
-void zebra_import_table_rm_update()
+void zebra_import_table_rm_update(const char *rmap)
 {
        afi_t afi;
        int i;
@@ -730,9 +730,8 @@ void zebra_import_table_rm_update()
                                continue;
 
                        rmap_name = zebra_get_import_table_route_map(afi, i);
-                       if (!rmap_name)
-                               return;
-
+                       if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0))
+                               continue;
                        table = zebra_vrf_other_route_table(afi, i,
                                                            VRF_DEFAULT);
                        for (rn = route_top(table); rn; rn = route_next(rn)) {
index a0fbd13cf96d43a96d31e4fd193784e37b167455..f67480da9ccbc313f04debc6c3e78f7130220664 100644 (file)
@@ -71,6 +71,5 @@ extern int is_zebra_import_table_enabled(afi_t, uint32_t table_id);
 
 extern int zebra_import_table_config(struct vty *);
 
-extern void zebra_import_table_rm_update(void);
-
+extern void zebra_import_table_rm_update(const char *rmap);
 #endif /* _ZEBRA_REDISTRIBUTE_H */
index a37b2bf221881cb71cc45b775fca5bc254b5aaef..f821c6edb4cfa0377d0202437d78aa08d6e6584d 100644 (file)
@@ -325,6 +325,8 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
                                           vrf_id_t vrf_id);
 
 extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event);
+extern void rib_update_table(struct route_table *table,
+                            rib_update_event_t event);
 extern void rib_sweep_route(void);
 extern void rib_sweep_table(struct route_table *table);
 extern void rib_close_table(struct route_table *table);
index 6a258e68539b16c65735085130d26deb11e984da..cab3f43b19570910506337ac86f8ca59b5a4c048 100644 (file)
@@ -246,6 +246,33 @@ static vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
        return VRF_DEFAULT;
 }
 
+/**
+ * @parse_encap_mpls() - Parses encapsulated mpls attributes
+ * @tb:         Pointer to rtattr to look for nested items in.
+ * @labels:     Pointer to store labels in.
+ *
+ * Return:      Number of mpls labels found.
+ */
+static int parse_encap_mpls(struct rtattr *tb, mpls_label_t *labels)
+{
+       struct rtattr *tb_encap[MPLS_IPTUNNEL_MAX + 1] = {0};
+       mpls_lse_t *lses = NULL;
+       int num_labels = 0;
+       uint32_t ttl = 0;
+       uint32_t bos = 0;
+       uint32_t exp = 0;
+       mpls_label_t label = 0;
+
+       netlink_parse_rtattr_nested(tb_encap, MPLS_IPTUNNEL_MAX, tb);
+       lses = (mpls_lse_t *)RTA_DATA(tb_encap[MPLS_IPTUNNEL_DST]);
+       while (!bos && num_labels < MPLS_MAX_LABELS) {
+               mpls_lse_decode(lses[num_labels], &label, &ttl, &exp, &bos);
+               labels[num_labels++] = label;
+       }
+
+       return num_labels;
+}
+
 /* Looking up routing table by netlink interface. */
 static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
                                             int startup)
@@ -274,6 +301,10 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
        void *src = NULL;     /* IPv6 srcdest   source prefix */
        enum blackhole_type bh_type = BLACKHOLE_UNSPEC;
 
+       /* MPLS labels */
+       mpls_label_t labels[MPLS_MAX_LABELS] = {0};
+       int num_labels = 0;
+
        rtm = NLMSG_DATA(h);
 
        if (startup && h->nlmsg_type != RTM_NEWROUTE)
@@ -508,6 +539,17 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
                        }
                        nh.vrf_id = nh_vrf_id;
 
+                       if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
+                           && *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE])
+                                      == LWTUNNEL_ENCAP_MPLS) {
+                               num_labels =
+                                       parse_encap_mpls(tb[RTA_ENCAP], labels);
+                       }
+
+                       if (num_labels)
+                               nexthop_add_labels(&nh, ZEBRA_LSP_STATIC,
+                                                  num_labels, labels);
+
                        rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
                                &src_p, &nh, table, metric, mtu, distance, tag);
                } else {
@@ -532,6 +574,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
                        re->tag = tag;
 
                        for (;;) {
+                               struct nexthop *nh = NULL;
                                vrf_id_t nh_vrf_id;
                                if (len < (int)sizeof(*rtnh)
                                    || rtnh->rtnh_len > len)
@@ -569,35 +612,46 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
                                        if (tb[RTA_GATEWAY])
                                                gate = RTA_DATA(
                                                        tb[RTA_GATEWAY]);
+                                       if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
+                                           && *(uint16_t *)RTA_DATA(
+                                                      tb[RTA_ENCAP_TYPE])
+                                                      == LWTUNNEL_ENCAP_MPLS) {
+                                               num_labels = parse_encap_mpls(
+                                                       tb[RTA_ENCAP], labels);
+                                       }
                                }
 
                                if (gate) {
                                        if (rtm->rtm_family == AF_INET) {
                                                if (index)
-                                                       route_entry_nexthop_ipv4_ifindex_add(
+                                                       nh = route_entry_nexthop_ipv4_ifindex_add(
                                                                re, gate,
                                                                prefsrc, index,
                                                                nh_vrf_id);
                                                else
-                                                       route_entry_nexthop_ipv4_add(
+                                                       nh = route_entry_nexthop_ipv4_add(
                                                                re, gate,
                                                                prefsrc,
                                                                nh_vrf_id);
                                        } else if (rtm->rtm_family
                                                   == AF_INET6) {
                                                if (index)
-                                                       route_entry_nexthop_ipv6_ifindex_add(
+                                                       nh = route_entry_nexthop_ipv6_ifindex_add(
                                                                re, gate, index,
                                                                nh_vrf_id);
                                                else
-                                                       route_entry_nexthop_ipv6_add(
+                                                       nh = route_entry_nexthop_ipv6_add(
                                                                re, gate,
                                                                nh_vrf_id);
                                        }
                                } else
-                                       route_entry_nexthop_ifindex_add(
+                                       nh = route_entry_nexthop_ifindex_add(
                                                re, index, nh_vrf_id);
 
+                               if (nh && num_labels)
+                                       nexthop_add_labels(nh, ZEBRA_LSP_STATIC,
+                                                          num_labels, labels);
+
                                if (rtnh->rtnh_len == 0)
                                        break;
 
index f44574b2367a9a747e3e751ef39f105eeb558a64..5dc3750315b14b4ac789700120b9f65cb152f476 100644 (file)
@@ -141,13 +141,3 @@ if DEV_BUILD
 zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_dt.c
 endif
 endif
-
-EXTRA_DIST += \
-       zebra/GNOME-SMI \
-       zebra/GNOME-PRODUCT-ZEBRA-MIB \
-       # end
-
-# -- unmaintained --
-# noinst_PROGRAMS += zebra/client
-# zebra_client_SOURCES = zebra/client_main.c
-# zebra_client_LDADD = lib/libfrr.la
index 008fc8f066c4554afe4c4aa4f843d947b70ec7e7..d95f78109cbea829aa8c86813f4637246354d855 100644 (file)
@@ -1022,6 +1022,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
        unsigned short l = 0;
        uint8_t flags = 0;
        uint16_t type = cmd2type[hdr->command];
+       bool exist;
 
        if (IS_ZEBRA_DEBUG_NHT)
                zlog_debug(
@@ -1064,7 +1065,10 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
                                p.family);
                        return;
                }
-               rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type);
+               rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type, &exist);
+               if (!rnh)
+                       return;
+
                if (type == RNH_NEXTHOP_TYPE) {
                        if (flags
                            && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
@@ -1084,7 +1088,9 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
 
                zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
                /* Anything not AF_INET/INET6 has been filtered out above */
-               zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p);
+               if (!exist)
+                       zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type,
+                                          &p);
        }
 
 stream_failure:
@@ -1584,202 +1590,6 @@ static void zread_route_del(ZAPI_HANDLER_ARGS)
        }
 }
 
-/* This function support multiple nexthop. */
-/*
- * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and
- * add kernel route.
- */
-static void zread_ipv4_add(ZAPI_HANDLER_ARGS)
-{
-       int i;
-       struct route_entry *re;
-       struct prefix p;
-       uint8_t message;
-       struct in_addr nhop_addr;
-       uint8_t nexthop_num;
-       uint8_t nexthop_type;
-       struct stream *s;
-       ifindex_t ifindex;
-       safi_t safi;
-       int ret;
-       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 = msg;
-
-       /* Allocate new re. */
-       re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
-
-       /* Type, flags, message. */
-       STREAM_GETC(s, re->type);
-       if (re->type > ZEBRA_ROUTE_MAX) {
-               zlog_warn("%s: Specified route type %d is not a legal value\n",
-                         __PRETTY_FUNCTION__, re->type);
-               XFREE(MTYPE_RE, re);
-               return;
-       }
-       STREAM_GETW(s, re->instance);
-       STREAM_GETL(s, re->flags);
-       STREAM_GETC(s, message);
-       STREAM_GETW(s, safi);
-       re->uptime = time(NULL);
-
-       /* IPv4 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv4));
-       p.family = AF_INET;
-       STREAM_GETC(s, p.prefixlen);
-       if (p.prefixlen > IPV4_MAX_BITLEN) {
-               zlog_warn(
-                       "%s: Specified prefix length %d is greater than what v4 can be",
-                       __PRETTY_FUNCTION__, p.prefixlen);
-               XFREE(MTYPE_RE, re);
-               return;
-       }
-       STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
-
-       /* VRF ID */
-       re->vrf_id = zvrf_id(zvrf);
-
-       /* Nexthop parse. */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
-               STREAM_GETC(s, nexthop_num);
-               zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
-                                      nexthop_num);
-
-               if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
-                       label_type = lsp_type_from_re_type(client->proto);
-
-               for (i = 0; i < nexthop_num; i++) {
-                       STREAM_GETC(s, nexthop_type);
-
-                       switch (nexthop_type) {
-                       case NEXTHOP_TYPE_IFINDEX:
-                               STREAM_GETL(s, ifindex);
-                               route_entry_nexthop_ifindex_add(re, ifindex,
-                                                               re->vrf_id);
-                               break;
-                       case NEXTHOP_TYPE_IPV4:
-                               STREAM_GET(&nhop_addr.s_addr, s,
-                                          IPV4_MAX_BYTELEN);
-                               nexthop = route_entry_nexthop_ipv4_add(
-                                       re, &nhop_addr, NULL, re->vrf_id);
-                               /*
-                                * For labeled-unicast, each nexthop is followed
-                                * by the label.
-                                */
-                               if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) {
-                                       STREAM_GETL(s, label);
-                                       nexthop_add_labels(nexthop, label_type,
-                                                          1, &label);
-                               }
-                               break;
-                       case NEXTHOP_TYPE_IPV4_IFINDEX:
-                               STREAM_GET(&nhop_addr.s_addr, s,
-                                          IPV4_MAX_BYTELEN);
-                               STREAM_GETL(s, ifindex);
-                               route_entry_nexthop_ipv4_ifindex_add(
-                                       re, &nhop_addr, NULL, ifindex,
-                                       re->vrf_id);
-                               break;
-                       case NEXTHOP_TYPE_IPV6:
-                               zlog_warn(
-                                       "%s: Please use ZEBRA_ROUTE_ADD if you want to pass v6 nexthops",
-                                       __PRETTY_FUNCTION__);
-                               nexthops_free(re->ng.nexthop);
-                               XFREE(MTYPE_RE, re);
-                               return;
-                       case NEXTHOP_TYPE_BLACKHOLE:
-                               route_entry_nexthop_blackhole_add(re, bh_type);
-                               break;
-                       default:
-                               zlog_warn(
-                                       "%s: Specified nexthop type: %d does not exist",
-                                       __PRETTY_FUNCTION__, nexthop_type);
-                               nexthops_free(re->ng.nexthop);
-                               XFREE(MTYPE_RE, re);
-                               return;
-                       }
-               }
-       }
-
-       /* Distance. */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
-               STREAM_GETC(s, re->distance);
-
-       /* Metric. */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
-               STREAM_GETL(s, re->metric);
-
-       /* Tag */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
-               STREAM_GETL(s, re->tag);
-       else
-               re->tag = 0;
-
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
-               STREAM_GETL(s, re->mtu);
-       else
-               re->mtu = 0;
-
-       /* Table */
-       re->table = zvrf->table_id;
-
-       ret = rib_add_multipath(AFI_IP, safi, &p, NULL, re);
-
-       /* Stats */
-       if (ret > 0)
-               client->v4_route_add_cnt++;
-       else if (ret < 0)
-               client->v4_route_upd8_cnt++;
-
-       return;
-
-stream_failure:
-       nexthops_free(re->ng.nexthop);
-       XFREE(MTYPE_RE, re);
-}
-
-/* Zebra server IPv4 prefix delete function. */
-static void zread_ipv4_delete(ZAPI_HANDLER_ARGS)
-{
-       struct stream *s;
-       struct zapi_ipv4 api;
-       struct prefix p;
-       uint32_t table_id;
-
-       s = msg;
-
-       /* Type, flags, message. */
-       STREAM_GETC(s, api.type);
-       STREAM_GETW(s, api.instance);
-       STREAM_GETL(s, api.flags);
-       STREAM_GETC(s, api.message);
-       STREAM_GETW(s, api.safi);
-
-       /* IPv4 prefix. */
-       memset(&p, 0, sizeof(struct prefix));
-       p.family = AF_INET;
-       STREAM_GETC(s, p.prefixlen);
-       if (p.prefixlen > IPV4_MAX_BITLEN) {
-               zlog_warn("%s: Passed in prefixlen %d is impossible",
-                         __PRETTY_FUNCTION__, p.prefixlen);
-               return;
-       }
-       STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
-
-       table_id = zvrf->table_id;
-
-       rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
-                  api.flags, &p, NULL, NULL, table_id, 0, 0, false);
-       client->v4_route_del_cnt++;
-
-stream_failure:
-       return;
-}
-
 /* MRIB Nexthop lookup for IPv4. */
 static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS)
 {
@@ -1794,417 +1604,6 @@ stream_failure:
        return;
 }
 
-/* Zebra server IPv6 prefix add function. */
-static void zread_ipv4_route_ipv6_nexthop_add(ZAPI_HANDLER_ARGS)
-{
-       unsigned int i;
-       struct stream *s;
-       struct in6_addr nhop_addr;
-       struct route_entry *re;
-       uint8_t message;
-       uint8_t nexthop_num;
-       uint8_t nexthop_type;
-       struct prefix p;
-       safi_t safi;
-       static struct in6_addr nexthops[MULTIPATH_NUM];
-       static unsigned int ifindices[MULTIPATH_NUM];
-       int ret;
-       static mpls_label_t labels[MULTIPATH_NUM];
-       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 = msg;
-
-       memset(&nhop_addr, 0, sizeof(struct in6_addr));
-
-       /* Allocate new re. */
-       re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
-
-       /* Type, flags, message. */
-       STREAM_GETC(s, re->type);
-       if (re->type > ZEBRA_ROUTE_MAX) {
-               zlog_warn("%s: Specified route type: %d is not a legal value\n",
-                         __PRETTY_FUNCTION__, re->type);
-               XFREE(MTYPE_RE, re);
-               return;
-       }
-       STREAM_GETW(s, re->instance);
-       STREAM_GETL(s, re->flags);
-       STREAM_GETC(s, message);
-       STREAM_GETW(s, safi);
-       re->uptime = time(NULL);
-
-       /* IPv4 prefix. */
-       memset(&p, 0, sizeof(struct prefix_ipv4));
-       p.family = AF_INET;
-       STREAM_GETC(s, p.prefixlen);
-       if (p.prefixlen > IPV4_MAX_BITLEN) {
-               zlog_warn(
-                       "%s: Prefix Length %d is greater than what a v4 address can use",
-                       __PRETTY_FUNCTION__, p.prefixlen);
-               XFREE(MTYPE_RE, re);
-               return;
-       }
-       STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen));
-
-       /* VRF ID */
-       re->vrf_id = zvrf_id(zvrf);
-
-       /*
-        * We need to give nh-addr, nh-ifindex with the same next-hop object
-        * to the re to ensure that IPv6 multipathing works; need to coalesce
-        * these. Clients should send the same number of paired set of
-        * next-hop-addr/next-hop-ifindices.
-        */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
-               unsigned int nh_count = 0;
-               unsigned int if_count = 0;
-               unsigned int max_nh_if = 0;
-
-               STREAM_GETC(s, nexthop_num);
-               zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
-                                      nexthop_num);
-
-               if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
-                       label_type = lsp_type_from_re_type(client->proto);
-
-               for (i = 0; i < nexthop_num; i++) {
-                       STREAM_GETC(s, nexthop_type);
-
-                       switch (nexthop_type) {
-                       case NEXTHOP_TYPE_IPV6:
-                               STREAM_GET(&nhop_addr, s, 16);
-                               if (nh_count < MULTIPATH_NUM) {
-                                       /*
-                                        * For labeled-unicast, each nexthop is
-                                        * followed by the label.
-                                        */
-                                       if (CHECK_FLAG(message,
-                                                      ZAPI_MESSAGE_LABEL)) {
-                                               STREAM_GETL(s, label);
-                                               labels[nh_count] = label;
-                                       }
-                                       nexthops[nh_count] = nhop_addr;
-                                       nh_count++;
-                               }
-                               break;
-                       case NEXTHOP_TYPE_IFINDEX:
-                               if (if_count < multipath_num)
-                                       STREAM_GETL(s, ifindices[if_count++]);
-                               break;
-                       case NEXTHOP_TYPE_BLACKHOLE:
-                               route_entry_nexthop_blackhole_add(re, bh_type);
-                               break;
-                       default:
-                               zlog_warn(
-                                       "%s: Please use ZEBRA_ROUTE_ADD if you want to pass non v6 nexthops",
-                                       __PRETTY_FUNCTION__);
-                               nexthops_free(re->ng.nexthop);
-                               XFREE(MTYPE_RE, re);
-                               return;
-                       }
-               }
-
-               max_nh_if = (nh_count > if_count) ? nh_count : if_count;
-               for (i = 0; i < max_nh_if; i++) {
-                       if ((i < nh_count)
-                           && !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) {
-                               if ((i < if_count) && ifindices[i])
-                                       nexthop =
-                                               route_entry_nexthop_ipv6_ifindex_add(
-                                                       re, &nexthops[i],
-                                                       ifindices[i],
-                                                       re->vrf_id);
-                               else
-                                       nexthop = route_entry_nexthop_ipv6_add(
-                                               re, &nexthops[i], re->vrf_id);
-
-                               if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
-                                       nexthop_add_labels(nexthop, label_type,
-                                                          1, &labels[i]);
-                       } else {
-                               if ((i < if_count) && ifindices[i])
-                                       route_entry_nexthop_ifindex_add(
-                                               re, ifindices[i], re->vrf_id);
-                       }
-               }
-       }
-
-       /* Distance. */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
-               STREAM_GETC(s, re->distance);
-
-       /* Metric. */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
-               STREAM_GETL(s, re->metric);
-
-       /* Tag */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
-               STREAM_GETL(s, re->tag);
-       else
-               re->tag = 0;
-
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
-               STREAM_GETL(s, re->mtu);
-       else
-               re->mtu = 0;
-
-       /* Table */
-       re->table = zvrf->table_id;
-
-       ret = rib_add_multipath(AFI_IP6, safi, &p, NULL, re);
-       /* Stats */
-       if (ret > 0)
-               client->v4_route_add_cnt++;
-       else if (ret < 0)
-               client->v4_route_upd8_cnt++;
-
-       return;
-
-stream_failure:
-       nexthops_free(re->ng.nexthop);
-       XFREE(MTYPE_RE, re);
-}
-
-static void zread_ipv6_add(ZAPI_HANDLER_ARGS)
-{
-       unsigned int i;
-       struct stream *s;
-       struct in6_addr nhop_addr;
-       ifindex_t ifindex;
-       struct route_entry *re;
-       uint8_t message;
-       uint8_t nexthop_num;
-       uint8_t nexthop_type;
-       struct prefix p;
-       struct prefix_ipv6 src_p, *src_pp;
-       safi_t safi;
-       static struct in6_addr nexthops[MULTIPATH_NUM];
-       static unsigned int ifindices[MULTIPATH_NUM];
-       int ret;
-       static mpls_label_t labels[MULTIPATH_NUM];
-       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 = msg;
-
-       memset(&nhop_addr, 0, sizeof(struct in6_addr));
-
-       /* Allocate new re. */
-       re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
-
-       /* Type, flags, message. */
-       STREAM_GETC(s, re->type);
-       if (re->type > ZEBRA_ROUTE_MAX) {
-               zlog_warn("%s: Specified route type: %d is not a legal value\n",
-                         __PRETTY_FUNCTION__, re->type);
-               XFREE(MTYPE_RE, re);
-               return;
-       }
-       STREAM_GETW(s, re->instance);
-       STREAM_GETL(s, re->flags);
-       STREAM_GETC(s, message);
-       STREAM_GETW(s, safi);
-       re->uptime = time(NULL);
-
-       /* IPv6 prefix. */
-       memset(&p, 0, sizeof(p));
-       p.family = AF_INET6;
-       STREAM_GETC(s, p.prefixlen);
-       if (p.prefixlen > IPV6_MAX_BITLEN) {
-               zlog_warn(
-                       "%s: Specified prefix length %d is to large for v6 prefix",
-                       __PRETTY_FUNCTION__, p.prefixlen);
-               XFREE(MTYPE_RE, re);
-               return;
-       }
-       STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen));
-
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) {
-               memset(&src_p, 0, sizeof(src_p));
-               src_p.family = AF_INET6;
-               STREAM_GETC(s, src_p.prefixlen);
-               if (src_p.prefixlen > IPV6_MAX_BITLEN) {
-                       zlog_warn(
-                               "%s: Specified src prefix length %d is to large for v6 prefix",
-                               __PRETTY_FUNCTION__, src_p.prefixlen);
-                       XFREE(MTYPE_RE, re);
-                       return;
-               }
-               STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen));
-               src_pp = &src_p;
-       } else
-               src_pp = NULL;
-
-       /* VRF ID */
-       re->vrf_id = zvrf_id(zvrf);
-
-       /*
-        * We need to give nh-addr, nh-ifindex with the same next-hop object
-        * to the re to ensure that IPv6 multipathing works; need to coalesce
-        * these. Clients should send the same number of paired set of
-        * next-hop-addr/next-hop-ifindices.
-        */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
-               unsigned int nh_count = 0;
-               unsigned int if_count = 0;
-               unsigned int max_nh_if = 0;
-
-               STREAM_GETC(s, nexthop_num);
-               zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
-                                      nexthop_num);
-
-               if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
-                       label_type = lsp_type_from_re_type(client->proto);
-
-               for (i = 0; i < nexthop_num; i++) {
-                       STREAM_GETC(s, nexthop_type);
-
-                       switch (nexthop_type) {
-                       case NEXTHOP_TYPE_IPV6:
-                               STREAM_GET(&nhop_addr, s, 16);
-                               if (nh_count < MULTIPATH_NUM) {
-                                       /*
-                                        * For labeled-unicast, each nexthop is
-                                        * followed by label.
-                                        */
-                                       if (CHECK_FLAG(message,
-                                                      ZAPI_MESSAGE_LABEL)) {
-                                               STREAM_GETL(s, label);
-                                               labels[nh_count] = label;
-                                       }
-                                       nexthops[nh_count++] = nhop_addr;
-                               }
-                               break;
-                       case NEXTHOP_TYPE_IPV6_IFINDEX:
-                               STREAM_GET(&nhop_addr, s, 16);
-                               STREAM_GETL(s, ifindex);
-                               route_entry_nexthop_ipv6_ifindex_add(
-                                       re, &nhop_addr, ifindex, re->vrf_id);
-                               break;
-                       case NEXTHOP_TYPE_IFINDEX:
-                               if (if_count < multipath_num)
-                                       STREAM_GETL(s, ifindices[if_count++]);
-                               break;
-                       case NEXTHOP_TYPE_BLACKHOLE:
-                               route_entry_nexthop_blackhole_add(re, bh_type);
-                               break;
-                       default:
-                               zlog_warn(
-                                       "%s: Please use ZEBRA_ROUTE_ADD if you want to pass non v6 nexthops",
-                                       __PRETTY_FUNCTION__);
-                               nexthops_free(re->ng.nexthop);
-                               XFREE(MTYPE_RE, re);
-                               return;
-                       }
-               }
-
-               max_nh_if = (nh_count > if_count) ? nh_count : if_count;
-               for (i = 0; i < max_nh_if; i++) {
-                       if ((i < nh_count)
-                           && !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) {
-                               if ((i < if_count) && ifindices[i])
-                                       nexthop =
-                                               route_entry_nexthop_ipv6_ifindex_add(
-                                                       re, &nexthops[i],
-                                                       ifindices[i],
-                                                       re->vrf_id);
-                               else
-                                       nexthop = route_entry_nexthop_ipv6_add(
-                                               re, &nexthops[i], re->vrf_id);
-                               if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL))
-                                       nexthop_add_labels(nexthop, label_type,
-                                                          1, &labels[i]);
-                       } else {
-                               if ((i < if_count) && ifindices[i])
-                                       route_entry_nexthop_ifindex_add(
-                                               re, ifindices[i], re->vrf_id);
-                       }
-               }
-       }
-
-       /* Distance. */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE))
-               STREAM_GETC(s, re->distance);
-
-       /* Metric. */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC))
-               STREAM_GETL(s, re->metric);
-
-       /* Tag */
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG))
-               STREAM_GETL(s, re->tag);
-       else
-               re->tag = 0;
-
-       if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU))
-               STREAM_GETL(s, re->mtu);
-       else
-               re->mtu = 0;
-
-       re->table = zvrf->table_id;
-
-       ret = rib_add_multipath(AFI_IP6, safi, &p, src_pp, re);
-       /* Stats */
-       if (ret > 0)
-               client->v6_route_add_cnt++;
-       else if (ret < 0)
-               client->v6_route_upd8_cnt++;
-
-       return;
-
-stream_failure:
-       nexthops_free(re->ng.nexthop);
-       XFREE(MTYPE_RE, re);
-}
-
-/* Zebra server IPv6 prefix delete function. */
-static void zread_ipv6_delete(ZAPI_HANDLER_ARGS)
-{
-       struct stream *s;
-       struct zapi_ipv6 api;
-       struct prefix p;
-       struct prefix_ipv6 src_p, *src_pp;
-
-       s = msg;
-
-       /* Type, flags, message. */
-       STREAM_GETC(s, api.type);
-       STREAM_GETW(s, api.instance);
-       STREAM_GETL(s, api.flags);
-       STREAM_GETC(s, api.message);
-       STREAM_GETW(s, api.safi);
-
-       /* IPv4 prefix. */
-       memset(&p, 0, sizeof(struct prefix));
-       p.family = AF_INET6;
-       STREAM_GETC(s, p.prefixlen);
-       STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen));
-
-       if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) {
-               memset(&src_p, 0, sizeof(struct prefix_ipv6));
-               src_p.family = AF_INET6;
-               STREAM_GETC(s, src_p.prefixlen);
-               STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen));
-               src_pp = &src_p;
-       } else
-               src_pp = NULL;
-
-       rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
-                  api.flags, &p, src_pp, NULL, client->rtm_table, 0, 0, false);
-
-       client->v6_route_del_cnt++;
-
-stream_failure:
-       return;
-}
-
 /* Register zebra server router-id information.  Send current router-id */
 static void zread_router_id_add(ZAPI_HANDLER_ARGS)
 {
@@ -3011,11 +2410,6 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
        [ZEBRA_INTERFACE_DELETE] = zread_interface_delete,
        [ZEBRA_ROUTE_ADD] = zread_route_add,
        [ZEBRA_ROUTE_DELETE] = zread_route_del,
-       [ZEBRA_IPV4_ROUTE_ADD] = zread_ipv4_add,
-       [ZEBRA_IPV4_ROUTE_DELETE] = zread_ipv4_delete,
-       [ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD] = zread_ipv4_route_ipv6_nexthop_add,
-       [ZEBRA_IPV6_ROUTE_ADD] = zread_ipv6_add,
-       [ZEBRA_IPV6_ROUTE_DELETE] = zread_ipv6_delete,
        [ZEBRA_REDISTRIBUTE_ADD] = zebra_redistribute_add,
        [ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete,
        [ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add,
index b477cd4706d0a9f106b1df8615872eff8145171c..ab07549ec26d13054dde6d5368ebdb2db3a02e74 100644 (file)
@@ -1501,17 +1501,37 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
 
        /* filter route selection in following order:
         * - connected beats other types
+        * - if both connected, loopback or vrf wins
         * - lower distance beats higher
         * - lower metric beats higher for equal distance
         * - last, hence oldest, route wins tie break.
         */
 
-       /* Connected routes. Pick the last connected
+       /* Connected routes. Check to see if either are a vrf
+        * or loopback interface.  If not, pick the last connected
         * route of the set of lowest metric connected routes.
         */
        if (alternate->type == ZEBRA_ROUTE_CONNECT) {
-               if (current->type != ZEBRA_ROUTE_CONNECT
-                   || alternate->metric <= current->metric)
+               if (current->type != ZEBRA_ROUTE_CONNECT)
+                       return alternate;
+
+               /* both are connected.  are either loop or vrf? */
+               struct nexthop *nexthop = NULL;
+
+               for (ALL_NEXTHOPS(alternate->ng, nexthop)) {
+                       if (if_is_loopback_or_vrf(if_lookup_by_index(
+                                   nexthop->ifindex, alternate->vrf_id)))
+                               return alternate;
+               }
+
+               for (ALL_NEXTHOPS(current->ng, nexthop)) {
+                       if (if_is_loopback_or_vrf(if_lookup_by_index(
+                                   nexthop->ifindex, current->vrf_id)))
+                               return current;
+               }
+
+               /* Neither are loop or vrf so pick best metric  */
+               if (alternate->metric <= current->metric)
                        return alternate;
 
                return current;
@@ -2651,8 +2671,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
 }
 
 /* Schedule routes of a particular table (address-family) based on event. */
-static void rib_update_table(struct route_table *table,
-                            rib_update_event_t event)
+void rib_update_table(struct route_table *table, rib_update_event_t event)
 {
        struct route_node *rn;
        struct route_entry *re, *next;
@@ -2732,12 +2751,18 @@ void rib_update(vrf_id_t vrf_id, rib_update_event_t event)
 
        /* Process routes of interested address-families. */
        table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
-       if (table)
+       if (table) {
+               if (IS_ZEBRA_DEBUG_EVENT)
+                       zlog_debug("%s : AFI_IP event %d", __func__, event);
                rib_update_table(table, event);
+       }
 
        table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
-       if (table)
+       if (table) {
+               if (IS_ZEBRA_DEBUG_EVENT)
+                       zlog_debug("%s : AFI_IP6 event %d", __func__, event);
                rib_update_table(table, event);
+       }
 }
 
 /* Delete self installed routes after zebra is relaunched.  */
index 156600c1056ddcafa168ffe6fbf9aa9ac3eb9744..0b585af6a0316b701fc933f8ab53ef8f6931966d 100644 (file)
@@ -103,7 +103,8 @@ char *rnh_str(struct rnh *rnh, char *buf, int size)
        return buf;
 }
 
-struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
+struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
+                         bool *exists)
 {
        struct route_table *table;
        struct route_node *rn;
@@ -119,6 +120,7 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
                prefix2str(p, buf, sizeof(buf));
                zlog_warn("%u: Add RNH %s type %d - table not found", vrfid,
                          buf, type);
+               exists = false;
                return NULL;
        }
 
@@ -136,7 +138,9 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
                route_lock_node(rn);
                rn->info = rnh;
                rnh->node = rn;
-       }
+               *exists = false;
+       } else
+               *exists = true;
 
        route_unlock_node(rn);
        return (rn->info);
@@ -190,6 +194,14 @@ void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
        route_unlock_node(rn);
 }
 
+/*
+ * This code will send to the registering client
+ * the looked up rnh.
+ * For a rnh that was created, there is no data
+ * so it will send an empty nexthop group
+ * If rnh exists then we know it has been evaluated
+ * and as such it will have a resolved rnh.
+ */
 void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
                          rnh_type_t type, vrf_id_t vrf_id)
 {
@@ -201,8 +213,7 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
        }
        if (!listnode_lookup(rnh->client_list, client)) {
                listnode_add(rnh->client_list, client);
-               send_client(rnh, client, type,
-                           vrf_id); // Pending: check if its needed
+               send_client(rnh, client, type, vrf_id);
        }
 }
 
@@ -247,9 +258,10 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw)
 {
        struct prefix nh;
        struct rnh *rnh;
+       bool exists;
 
        addr2hostprefix(pw->af, &pw->nexthop, &nh);
-       rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE);
+       rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE, &exists);
        if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) {
                listnode_add(rnh->zebra_pseudowire_list, pw);
                pw->rnh = rnh;
index 9e09a1bc6f1ed54a9bf790b95f6aa942041461db..f4b4b56390a7c526266cd7bae3eef4d7f915afa5 100644 (file)
@@ -68,7 +68,7 @@ static inline int rnh_resolve_via_default(int family)
 }
 
 extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
-                                rnh_type_t type);
+                                rnh_type_t type, bool *exists);
 extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
                                    rnh_type_t type);
 extern void zebra_free_rnh(struct rnh *rnh);
index fc17ee3491024e386784a0861a209c5441dcc43c..7a6bc6684d331d3698fc8d60f26b35937afb8a52 100644 (file)
@@ -1033,13 +1033,13 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = {
 /* `match ip address prefix-list PREFIX_LIST' */
 
 static route_map_result_t
-route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
-                                  route_map_object_t type, void *object)
+route_match_address_prefix_list(void *rule, const struct prefix *prefix,
+                       route_map_object_t type, void *object, afi_t afi)
 {
        struct prefix_list *plist;
 
        if (type == RMAP_ZEBRA) {
-               plist = prefix_list_lookup(AFI_IP, (char *)rule);
+               plist = prefix_list_lookup(afi, (char *)rule);
                if (plist == NULL)
                        return RMAP_NOMATCH;
 
@@ -1050,21 +1050,41 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
        return RMAP_NOMATCH;
 }
 
-static void *route_match_ip_address_prefix_list_compile(const char *arg)
+static route_map_result_t
+route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
+                                  route_map_object_t type, void *object)
+{
+       return (route_match_address_prefix_list(rule, prefix, type, object,
+                                               AFI_IP));
+}
+
+static void *route_match_address_prefix_list_compile(const char *arg)
 {
        return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
 }
 
-static void route_match_ip_address_prefix_list_free(void *rule)
+static void route_match_address_prefix_list_free(void *rule)
 {
        XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
 }
 
 static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
        "ip address prefix-list", route_match_ip_address_prefix_list,
-       route_match_ip_address_prefix_list_compile,
-       route_match_ip_address_prefix_list_free};
+       route_match_address_prefix_list_compile,
+       route_match_address_prefix_list_free};
 
+static route_map_result_t
+route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
+                                       route_map_object_t type, void *object)
+{
+       return (route_match_address_prefix_list(rule, prefix, type, object,
+                                               AFI_IP6));
+}
+
+static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
+       "ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
+       route_match_address_prefix_list_compile,
+       route_match_address_prefix_list_free};
 
 /* `match ip address prefix-len PREFIXLEN' */
 
@@ -1281,11 +1301,101 @@ static struct route_map_rule_cmd route_set_src_cmd = {
        "src", route_set_src, route_set_src_compile, route_set_src_free,
 };
 
+/* The function checks if the changed routemap specified by parameter rmap
+ * matches the configured protocol routemaps in proto_rm table. If there is
+ * a match then rib_update_table() to process the routes.
+ */
+static void zebra_rib_table_rm_update(const char *rmap)
+{
+       int i = 0;
+       struct route_table *table;
+       char *rmap_name;
+       char afi_ip = 0;
+       char afi_ipv6 = 0;
+
+       for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
+       /* Check for ip routemap table */
+               rmap_name = proto_rm[AFI_IP][i];
+               if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
+                       if (IS_ZEBRA_DEBUG_EVENT)
+                               zlog_debug("%s : AFI_IP rmap %s, route type %s",
+                               __func__, rmap, zebra_route_string(i));
+                       /* There is single rib table for all protocols */
+                       if (afi_ip == 0) {
+                               table = zebra_vrf_table(AFI_IP, SAFI_UNICAST,
+                                               VRF_DEFAULT);
+                               if (table) {
+                                       afi_ip = 1;
+                                       rib_update_table(table,
+                                               RIB_UPDATE_RMAP_CHANGE);
+                               }
+                       }
+               }
+
+               /* Check for ipv6 routemap table */
+               rmap_name = proto_rm[AFI_IP6][i];
+               if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
+                       if (IS_ZEBRA_DEBUG_EVENT)
+                               zlog_debug("%s : AFI_IP6 rmap %s,route type %s",
+                               __func__, rmap, zebra_route_string(i));
+                       if (afi_ipv6 == 0) {
+                               table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST,
+                                               VRF_DEFAULT);
+                               if (table) {
+                                       afi_ipv6 = 1;
+                                       rib_update_table(table,
+                                               RIB_UPDATE_RMAP_CHANGE);
+                               }
+                       }
+               }
+       }
+}
+
+/* The function checks if the changed routemap specified by parameter rmap
+ * matches the configured protocol routemaps in nht_rm table. If there is
+ * a match then zebra_evaluate_rnh() to process the nexthops.
+ */
+static void zebra_nht_rm_update(const char *rmap)
+{
+       int i = 0;
+       char *rmap_name;
+       char afi_ip = 0;
+       char afi_ipv6 = 0;
+
+       for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
+               rmap_name = nht_rm[AFI_IP][i];
+               if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
+                       if (IS_ZEBRA_DEBUG_EVENT)
+                               zlog_debug("%s : AFI_IP rmap %s route type %s",
+                                       __func__, rmap, zebra_route_string(i));
+                       if (afi_ip == 0) {
+                               afi_ip = 1;
+                               zebra_evaluate_rnh(0, AF_INET, 1,
+                                       RNH_NEXTHOP_TYPE, NULL);
+                       }
+               }
+               rmap_name = nht_rm[AFI_IP6][i];
+               if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
+                       if (IS_ZEBRA_DEBUG_EVENT)
+                               zlog_debug("%s : AFI_IP6 rmap %s route type %s",
+                                       __func__, rmap, zebra_route_string(i));
+                       if (afi_ipv6 == 0) {
+                               afi_ipv6 = 1;
+                               zebra_evaluate_rnh(0, AF_INET6, 1,
+                                       RNH_NEXTHOP_TYPE, NULL);
+                       }
+               }
+       }
+}
+
 static void zebra_route_map_process_update_cb(char *rmap_name)
 {
        if (IS_ZEBRA_DEBUG_EVENT)
                zlog_debug("Event handler for route-map: %s",
                           rmap_name);
+       zebra_import_table_rm_update(rmap_name);
+       zebra_rib_table_rm_update(rmap_name);
+       zebra_nht_rm_update(rmap_name);
 }
 
 static int zebra_route_map_update_timer(struct thread *thread)
@@ -1307,11 +1417,6 @@ static int zebra_route_map_update_timer(struct thread *thread)
         * 1) VRF Aware <sigh>
         * 2) Route-map aware
         */
-       zebra_import_table_rm_update();
-       rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
-       zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
-       zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
-
        return (0);
 }
 
@@ -1555,12 +1660,19 @@ void zebra_route_map_init()
        route_map_match_tag_hook(generic_match_add);
        route_map_no_match_tag_hook(generic_match_delete);
 
+       route_map_match_ipv6_address_hook(generic_match_add);
+       route_map_no_match_ipv6_address_hook(generic_match_delete);
+
+       route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
+       route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
+
        route_map_install_match(&route_match_tag_cmd);
        route_map_install_match(&route_match_interface_cmd);
        route_map_install_match(&route_match_ip_next_hop_cmd);
        route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
        route_map_install_match(&route_match_ip_address_cmd);
        route_map_install_match(&route_match_ip_address_prefix_list_cmd);
+       route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
        route_map_install_match(&route_match_ip_address_prefix_len_cmd);
        route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
        route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
index 79c2bb03e6a5cd8c88877ecbae747cb04e204fb9..9dfbfe6ce2b9b311cb0e2fdb67625d8981bff6ed 100644 (file)
@@ -1555,7 +1555,9 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n)
        struct zebra_if *zif;
        struct zebra_l2info_vxlan *vxl;
        struct interface *vlan_if;
+#ifdef GNU_LINUX
        uint8_t flags;
+#endif
        int ret = 0;
 
        if (!(n->flags & ZEBRA_NEIGH_REMOTE))
@@ -1966,6 +1968,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
        uint32_t old_mac_seq = 0, mac_new_seq = 0;
        bool upd_mac_seq = false;
        bool neigh_mac_change = false;
+       bool check_rbit = false;
 
        /* Check if the MAC exists. */
        zmac = zvni_mac_lookup(zvni, macaddr);
@@ -2018,43 +2021,53 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                /* Set "local" forwarding info. */
                SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
                n->ifindex = ifp->ifindex;
+               check_rbit = true;
        } else {
                if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
                        /* If there is no MAC change, BGP isn't interested. */
+                       if (router_flag !=
+                           (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)
+                                       ? 1 : 0))
+                               check_rbit = true;
+
                        if (memcmp(n->emac.octet, macaddr->octet,
                                   ETH_ALEN) == 0) {
                                /* Update any params and return - client doesn't
                                 * care about a purely local change.
                                 */
                                n->ifindex = ifp->ifindex;
-                               return 0;
-                       }
+                       } else {
 
-                       /* 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.
-                        * We also need to update the MAC's sequence number
-                        * in different situations.
-                        */
-                       if (IS_ZEBRA_NEIGH_ACTIVE(n))
-                               zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
-                                                             &n->emac, 0);
-                       old_zmac = zvni_mac_lookup(zvni, &n->emac);
-                       if (old_zmac) {
-                               old_mac_seq = CHECK_FLAG(old_zmac->flags,
-                                                        ZEBRA_MAC_REMOTE) ?
-                                       old_zmac->rem_seq : old_zmac->loc_seq;
-                               neigh_mac_change = upd_mac_seq = true;
-                               listnode_delete(old_zmac->neigh_list, n);
-                               zvni_deref_ip2mac(zvni, old_zmac, 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. We also need to
+                                * update the MAC's sequence number
+                                * in different situations.
+                                */
+                               if (IS_ZEBRA_NEIGH_ACTIVE(n))
+                                       zvni_neigh_send_del_to_client(
+                                               zvni->vni, &n->ip, &n->emac, 0);
+                               old_zmac = zvni_mac_lookup(zvni, &n->emac);
+                               if (old_zmac) {
+                                       old_mac_seq =
+                                               CHECK_FLAG(old_zmac->flags,
+                                                          ZEBRA_MAC_REMOTE) ?
+                                                       old_zmac->rem_seq :
+                                                       old_zmac->loc_seq;
+                                       neigh_mac_change = upd_mac_seq = true;
+                                       listnode_delete(
+                                               old_zmac->neigh_list, n);
+                                       zvni_deref_ip2mac(zvni, old_zmac, 0);
+                               }
 
-                       /* Update the forwarding info. */
-                       n->ifindex = ifp->ifindex;
-                       memcpy(&n->emac, macaddr, ETH_ALEN);
+                               /* Update the forwarding info. */
+                               n->ifindex = ifp->ifindex;
+                               memcpy(&n->emac, macaddr, ETH_ALEN);
 
-                       /* Link to new MAC */
-                       listnode_add_sort(zmac->neigh_list, n);
+                               /* Link to new MAC */
+                               listnode_add_sort(zmac->neigh_list, n);
+                       }
 
                } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
                        /*
@@ -2086,6 +2099,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                        n->r_vtep_ip.s_addr = 0;
                        SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
                        n->ifindex = ifp->ifindex;
+                       check_rbit = true;
                }
        }
 
@@ -2102,6 +2116,12 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                              MAX(seq1, seq2) : zmac->loc_seq;
        }
 
+       /*Mark Router flag (R-bit) */
+       if (router_flag)
+               SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
+       else
+               UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
+
        /* Before we program this in BGP, we need to check if MAC is locally
         * learnt. If not, force neighbor to be inactive and reset its seq.
         */
@@ -2112,9 +2132,9 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                return 0;
        }
 
-       /* Set router flag (R-bit) */
-       if (router_flag)
-               SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
+       if (!check_rbit) {
+               return 0;
+       }
 
        /* If the MAC's sequence number has changed, inform the MAC and all
         * neighbors associated with the MAC to BGP, else just inform this
@@ -3399,7 +3419,9 @@ static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
  */
 static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
 {
+#ifdef GNU_LINUX
        uint8_t flags;
+#endif
        int ret = 0;
 
        if (!is_l3vni_oper_up(zl3vni))
@@ -4023,6 +4045,7 @@ static void process_remote_macip_add(vni_t vni,
        uint32_t tmp_seq;
        uint8_t sticky = 0;
        u_char remote_gw = 0;
+       uint8_t router_flag = 0;
 
        /* Locate VNI hash entry - expected to exist. */
        zvni = zvni_lookup(vni);
@@ -4062,6 +4085,7 @@ static void process_remote_macip_add(vni_t vni,
 
        sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
        remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
+       router_flag = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
 
        mac = zvni_mac_lookup(zvni, macaddr);
 
@@ -4180,6 +4204,8 @@ static void process_remote_macip_add(vni_t vni,
            || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
            || (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0)
            || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)
+           || ((CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) ? 1 : 0)
+               != router_flag)
            || seq != n->rem_seq)
                update_neigh = 1;
 
@@ -4258,6 +4284,8 @@ static void process_remote_macip_add(vni_t vni,
                /* Set router flag (R-bit) to this Neighbor entry */
                if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG))
                        SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
+               else
+                       UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
 
                /* Install the entry. */
                zvni_neigh_install(zvni, n);
@@ -5384,10 +5412,11 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
 
        if (IS_ZEBRA_DEBUG_VXLAN)
                zlog_debug(
-                       "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
+                       "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
                        ipaddr2str(ip, buf2, sizeof(buf2)),
                        prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
                        ifp->ifindex, state, ext_learned ? "ext-learned " : "",
+                       router_flag ? "router " : "",
                        zvni->vni);
 
        /* Is this about a local neighbor or a remote one? */
@@ -5520,7 +5549,6 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
                                flags, seq, inet_ntoa(vtep_ip),
                                zebra_route_string(client->proto));
 
-
                process_remote_macip_add(vni, &macaddr, ipa_len, &ip,
                                         flags, seq, vtep_ip);
        }