]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #2641 from donaldsharp/pim_igmp_dr
authorRuss White <russ@riw.us>
Mon, 23 Jul 2018 20:50:59 +0000 (16:50 -0400)
committerGitHub <noreply@github.com>
Mon, 23 Jul 2018 20:50:59 +0000 (16:50 -0400)
pimd: Do not create upstream state when not DR for igmp request

70 files changed:
Makefile.am
bgpd/bgp_mplsvpn.c
bgpd/bgp_mplsvpn.h
bgpd/bgp_route.c
bgpd/bgp_routemap.c
bgpd/bgp_rpki.c
bgpd/bgp_table.c
bgpd/bgp_table.h
bgpd/bgp_vty.c
bgpd/bgpd.c
configure.ac
doc/Makefile.am
doc/developer/maintainer-release-build.rst [new file with mode: 0644]
doc/developer/modules.rst
doc/developer/workflow.rst
doc/user/bgp.rst
doc/user/installation.rst
doc/user/rpki.rst
docker/alpine/Dockerfile-coverage [new file with mode: 0644]
isisd/isis_circuit.c
lib/compiler.h
lib/filter.c
lib/if.c
lib/linklist.h
lib/module.c
lib/nexthop_group.h
lib/srcdest_table.c
lib/srcdest_table.h
lib/stream.h
lib/vrf.c
lib/workqueue.h
lib/zclient.h
ospf6d/ospf6_top.c
pimd/pim_cmd.c
pimd/pim_ifchannel.c
pimd/pim_igmp.c
pimd/pim_nht.c
pimd/pim_nht.h
pimd/pim_rp.c
pimd/pim_rpf.c
pimd/pim_zebra.c
redhat/frr.spec.in
tests/.gitignore
tests/Makefile.am
tests/bgpd/test_bgp_table.c [new file with mode: 0644]
tests/bgpd/test_bgp_table.py [new file with mode: 0644]
tests/lib/test_srcdest_table.c
tools/frr-reload.py
zebra/if_netlink.c
zebra/kernel_netlink.c
zebra/kernel_netlink.h
zebra/main.c
zebra/redistribute.c
zebra/redistribute.h
zebra/rib.h
zebra/rt.h
zebra/rt_netlink.c
zebra/rt_socket.c
zebra/zapi_msg.c
zebra/zapi_msg.h
zebra/zebra_mpls.c
zebra/zebra_netns_notify.c
zebra/zebra_ptm.c
zebra/zebra_rib.c
zebra/zebra_routemap.c
zebra/zebra_routemap.h
zebra/zebra_static.c
zebra/zebra_static.h
zebra/zebra_vty.c
zebra/zserv.c

index 5dc80b4983d57969e9f1f4d1042ed9dc1c406b25..f9fb231962c7e99405c4189dbe60743f67f11737 100644 (file)
@@ -5,8 +5,7 @@ include common.am
 
 AM_CPPFLAGS += -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/lib \
              -I$(top_builddir) -I$(top_builddir)/include -I$(top_builddir)/lib
-VERSION_TYPE := $(shell if echo $(VERSION) | grep -q '^[0-9\.]*$$'; then echo RELEASE ; else echo DEV ; fi)
-DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE) -DVERSION_TYPE_$(VERSION_TYPE)
+DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE)
 LIBCAP = @LIBCAP@
 
 EXTRA_DIST =
@@ -115,3 +114,23 @@ noinst_HEADERS += defaults.h
 
 indent:
        tools/indent.py `find sharpd bgpd eigrpd include isisd lib nhrpd ospf6d ospfd pimd qpb ripd vtysh zebra -name '*.[ch]' | grep -v include/linux`
+
+if HAVE_GCOV
+
+coverage: check
+       @ find . -name '*.o' -exec gcov {} \;
+
+yorn:
+       @ echo "OK to upload coverage to https://coverage.io [y/N]:"
+       @ read yn; test "$$yn" = "y"
+
+upload-check-coverage:
+       @ if [ "x${COMMIT}" = "x" ]; then echo "COMMIT required"; exit 1; fi
+       @ if [ "x${TOKEN}" = "x" ]; then echo "TOKEN required"; exit 1; fi
+       curl -s https://codecov.io/bash | bash -s - -C ${COMMIT} -t ${TOKEN}
+
+force-check-coverage: coverage upload-check-coverage
+
+check-coverage: coverage yorn upload-check-coverage
+
+endif
index 847129fbe55b2284bde6c99726bdf29abb3a5b59..f72104dd33d6bda1c1b1abdb2a8be0f4fef1d17c 100644 (file)
@@ -490,7 +490,7 @@ leak_update(
         * (only one hop back to ultimate parent for vrf-vpn-vrf scheme).
         * Using a loop here supports more complex intra-bgp import-export
         * schemes that could be implemented in the future.
-        * 
+        *
         */
        for (bi_ultimate = source_bi;
                bi_ultimate->extra && bi_ultimate->extra->parent;
@@ -1356,8 +1356,7 @@ void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, /* to */
        struct bgp_node *prn;
        safi_t safi = SAFI_MPLS_VPN;
 
-       if (!bgp_vpn)
-               return;
+       assert(bgp_vpn);
 
        /*
         * Walk vpn table
@@ -2253,3 +2252,66 @@ vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey)
        }
        return VRF_UNKNOWN;
 }
+
+/*
+ * The purpose of this function is to process leaks that were deferred
+ * from earlier per-vrf configuration due to not-yet-existing default
+ * vrf, in other words, configuration such as:
+ *
+ *     router bgp MMM vrf FOO
+ *       address-family ipv4 unicast
+ *         rd vpn export 1:1
+ *       exit-address-family
+ *
+ *     router bgp NNN
+ *       ...
+ *
+ * This function gets called when the default instance ("router bgp NNN")
+ * is created.
+ */
+void vpn_leak_postchange_all(void)
+{
+       struct listnode *next;
+       struct bgp *bgp;
+       struct bgp *bgp_default = bgp_get_default();
+
+       assert(bgp_default);
+
+       /* First, do any exporting from VRFs to the single VPN RIB */
+       for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
+
+               if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+                       continue;
+
+               vpn_leak_postchange(
+                       BGP_VPN_POLICY_DIR_TOVPN,
+                       AFI_IP,
+                       bgp_default,
+                       bgp);
+
+               vpn_leak_postchange(
+                       BGP_VPN_POLICY_DIR_TOVPN,
+                       AFI_IP6,
+                       bgp_default,
+                       bgp);
+       }
+
+       /* Now, do any importing to VRFs from the single VPN RIB */
+       for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
+
+               if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+                       continue;
+
+               vpn_leak_postchange(
+                       BGP_VPN_POLICY_DIR_FROMVPN,
+                       AFI_IP,
+                       bgp_default,
+                       bgp);
+
+               vpn_leak_postchange(
+                       BGP_VPN_POLICY_DIR_FROMVPN,
+                       AFI_IP6,
+                       bgp_default,
+                       bgp);
+       }
+}
index 384108dc0c475bc7af4ce81265705c146bfd3571..b0add40da9f94f0982ceaaa2785773ef09c9e98a 100644 (file)
@@ -182,6 +182,10 @@ static inline void vpn_leak_prechange(vpn_policy_direction_t direction,
                                      afi_t afi, struct bgp *bgp_vpn,
                                      struct bgp *bgp_vrf)
 {
+       /* Detect when default bgp instance is not (yet) defined by config */
+       if (!bgp_vpn)
+               return;
+
        if ((direction == BGP_VPN_POLICY_DIR_FROMVPN) &&
                vpn_leak_from_vpn_active(bgp_vrf, afi, NULL)) {
 
@@ -198,6 +202,10 @@ static inline void vpn_leak_postchange(vpn_policy_direction_t direction,
                                       afi_t afi, struct bgp *bgp_vpn,
                                       struct bgp *bgp_vrf)
 {
+       /* Detect when default bgp instance is not (yet) defined by config */
+       if (!bgp_vpn)
+               return;
+
        if (direction == BGP_VPN_POLICY_DIR_FROMVPN)
                vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi);
        if (direction == BGP_VPN_POLICY_DIR_TOVPN) {
@@ -216,4 +224,6 @@ extern void vpn_policy_routemap_event(const char *rmap_name);
 
 extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey);
 
+extern void vpn_leak_postchange_all(void);
+
 #endif /* _QUAGGA_BGP_MPLSVPN_H */
index 795bd15613a0c41376c2b291f5903d33f2948331..f10f7425c6a6a6a79de38e1f94db50077bb32bf9 100644 (file)
@@ -8163,7 +8163,7 @@ static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
                           afi_t afi, safi_t safi, enum bgp_show_type type);
 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
                              const char *comstr, int exact, afi_t afi,
-                             safi_t safi);
+                             safi_t safi, uint8_t use_json);
 
 
 static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
@@ -9038,7 +9038,6 @@ DEFUN (show_ip_bgp,
            |prefix-list WORD\
            |filter-list WORD\
            |statistics\
-           |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown> [exact-match]\
            |community-list <(1-500)|WORD> [exact-match]\
            |A.B.C.D/M longer-prefixes\
            |X:X::X:X/M longer-prefixes\
@@ -9058,13 +9057,6 @@ 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"
-       "Exact match of the communities\n"
        "Display routes matching the community-list\n"
        "community-list number\n"
        "community-list name\n"
@@ -9079,7 +9071,6 @@ DEFUN (show_ip_bgp,
        int exact_match = 0;
        struct bgp *bgp = NULL;
        int idx = 0;
-       int idx_community_type = 0;
 
        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
                                            &bgp);
@@ -9106,24 +9097,6 @@ DEFUN (show_ip_bgp,
                return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
                                          safi, bgp_show_type_route_map);
 
-       if (argv_find(argv, argc, "community", &idx)) {
-               /* show a specific community */
-               if (argv_find(argv, argc, "local-AS", &idx_community_type)
-                   || argv_find(argv, argc, "no-advertise",
-                                &idx_community_type)
-                   || argv_find(argv, argc, "no-export", &idx_community_type)
-                   || argv_find(argv, argc, "graceful-shutdown",
-                                &idx_community_type)
-                   || argv_find(argv, argc, "AA:NN", &idx_community_type)) {
-
-                       if (argv_find(argv, argc, "exact-match", &idx))
-                               exact_match = 1;
-                       return bgp_show_community(vty, bgp,
-                                                 argv[idx_community_type]->arg,
-                                                 exact_match, afi, safi);
-               }
-       }
-
        if (argv_find(argv, argc, "community-list", &idx)) {
                const char *clist_number_or_name = argv[++idx]->arg;
                if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
@@ -9148,7 +9121,7 @@ DEFUN (show_ip_bgp_json,
           [<\
              cidr-only\
              |dampening <flap-statistics|dampened-paths>\
-             |community \
+             |community [<AA:NN|local-AS|no-advertise|no-export|graceful-shutdown>] [exact-match]\
           >] [json]",
        SHOW_STR
        IP_STR
@@ -9161,6 +9134,12 @@ DEFUN (show_ip_bgp_json,
        "Display flap statistics of routes\n"
        "Display paths suppressed due to dampening\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"
+       "Exact match of the communities\n"
        JSON_STR)
 {
        afi_t afi = AFI_IP6;
@@ -9168,6 +9147,8 @@ DEFUN (show_ip_bgp_json,
        enum bgp_show_type sh_type = bgp_show_type_normal;
        struct bgp *bgp = NULL;
        int idx = 0;
+       int idx_community_type = 0;
+       int exact_match = 0;
 
        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
                                            &bgp);
@@ -9193,10 +9174,31 @@ DEFUN (show_ip_bgp_json,
        }
 
        if (argv_find(argv, argc, "community", &idx)) {
-               /* show all communities */
-               return bgp_show(vty, bgp, afi, safi,
-                               bgp_show_type_community_all, NULL, uj);
+
+               /* show a specific community */
+               if (argv_find(argv, argc, "local-AS", &idx_community_type) ||
+                       argv_find(argv, argc, "no-advertise",
+                                       &idx_community_type) ||
+                       argv_find(argv, argc, "no-export",
+                                       &idx_community_type) ||
+                       argv_find(argv, argc, "graceful-shutdown",
+                                       &idx_community_type) ||
+                       argv_find(argv, argc, "AA:NN", &idx_community_type)) {
+                       if (argv_find(argv, argc, "exact-match", &idx))
+                               exact_match = 1;
+
+                       return (bgp_show_community(vty, bgp,
+                                               argv[idx_community_type]->arg,
+                                               exact_match, afi, safi, uj));
+               } else {
+
+                       /* show all communities */
+                       return (bgp_show(vty, bgp, afi, safi,
+                                       bgp_show_type_community_all, NULL,
+                                       uj));
+               }
        }
+
        return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj);
 }
 
@@ -9403,7 +9405,7 @@ static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
 
 static int bgp_show_community(struct vty *vty, struct bgp *bgp,
                              const char *comstr, int exact, afi_t afi,
-                             safi_t safi)
+                             safi_t safi, uint8_t use_json)
 {
        struct community *com;
        int ret = 0;
@@ -9417,7 +9419,7 @@ static int bgp_show_community(struct vty *vty, struct bgp *bgp,
        ret = bgp_show(vty, bgp, afi, safi,
                       (exact ? bgp_show_type_community_exact
                              : bgp_show_type_community),
-                      com, 0);
+                      com, use_json);
        community_free(com);
 
        return ret;
index f7c79f873df0b84d35cf7d4e3f2180b84981798c..f9f5142cd08260763a85793dee15788474928518 100644 (file)
@@ -1298,6 +1298,9 @@ static route_map_result_t route_set_ip_nexthop(void *rule,
                        bgp_info->attr->nexthop = *rins->address;
                        SET_FLAG(bgp_info->attr->rmap_change_flags,
                                 BATTR_RMAP_IPV4_NHOP_CHANGED);
+                       /* case for MP-BGP : MPLS VPN */
+                       bgp_info->attr->mp_nexthop_global_in = *rins->address;
+                       bgp_info->attr->mp_nexthop_len = sizeof(*rins->address);
                }
        }
 
index 317d451b6ddf0544d66eca141f45e6454da37914..774c4847843d6ccb4e49849b713665f57381de6f 100644 (file)
@@ -47,6 +47,7 @@
 #include "bgpd/bgp_attr.h"
 #include "bgpd/bgp_aspath.h"
 #include "bgpd/bgp_route.h"
+#include "lib/thread.h"
 #include "rtrlib/rtrlib.h"
 #include "rtrlib/rtr_mgr.h"
 #include "rtrlib/lib/ip.h"
@@ -128,16 +129,22 @@ static void route_match_free(void *rule);
 static route_map_result_t route_match(void *rule, struct prefix *prefix,
                                      route_map_object_t type, void *object);
 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 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 int rpki_debug;
 static unsigned int polling_period;
 static unsigned int expire_interval;
 static unsigned int retry_interval;
 static unsigned int timeout;
 static unsigned int initial_synchronisation_timeout;
+static int rpki_sync_socket_rtr;
+static int rpki_sync_socket_bgpd;
 
 static struct cmd_node rpki_node = {RPKI_NODE, "%s(config-rpki)# ", 1};
 static struct route_map_rule_cmd route_match_rpki_cmd = {
@@ -185,6 +192,14 @@ static void free_tr_socket(struct cache *cache)
 static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
                                struct prefix *prefix);
 
+static void ipv6_addr_to_network_byte_order(const uint32_t *src, uint32_t *dest)
+{
+       int i;
+
+       for (i = 0; i < 4; i++)
+               dest[i] = htonl(src[i]);
+}
+
 static void ipv6_addr_to_host_byte_order(const uint32_t *src, uint32_t *dest)
 {
        int i;
@@ -303,10 +318,159 @@ inline int is_running(void)
        return rtr_is_running;
 }
 
+static struct prefix *pfx_record_to_prefix(struct pfx_record *record)
+{
+       struct prefix *prefix = prefix_new();
+
+       prefix->prefixlen = record->min_len;
+
+       if (record->prefix.ver == LRTR_IPV4) {
+               prefix->family = AF_INET;
+               prefix->u.prefix4.s_addr = htonl(record->prefix.u.addr4.addr);
+       } else {
+               prefix->family = AF_INET6;
+               ipv6_addr_to_network_byte_order(record->prefix.u.addr6.addr,
+                                               prefix->u.prefix6.s6_addr32);
+       }
+
+       return prefix;
+}
+
+static int bgpd_sync_callback(struct thread *thread)
+{
+       struct bgp *bgp;
+       struct listnode *node;
+       struct prefix *prefix;
+       struct pfx_record rec;
+
+       thread_add_read(bm->master, bgpd_sync_callback, NULL,
+                       rpki_sync_socket_bgpd, NULL);
+       int retval =
+               read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
+       if (retval != sizeof(struct pfx_record)) {
+               RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
+               return retval;
+       }
+       prefix = pfx_record_to_prefix(&rec);
+
+       afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
+
+       for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
+               safi_t safi;
+
+               for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+                       if (!bgp->rib[afi][safi])
+                               continue;
+
+                       struct list *matches = list_new();
+
+                       matches->del = (void (*)(void *))bgp_unlock_node;
+
+                       bgp_table_range_lookup(bgp->rib[afi][safi], prefix,
+                                              rec.max_len, matches);
+
+
+                       struct bgp_node *bgp_node;
+
+                       for (ALL_LIST_ELEMENTS_RO(matches, node, bgp_node))
+                               revalidate_bgp_node(bgp_node, afi, safi);
+
+                       list_delete_and_null(&matches);
+               }
+       }
+
+       prefix_free(prefix);
+       return 0;
+}
+
+static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
+                               safi_t safi)
+{
+       struct bgp_adj_in *ain;
+
+       for (ain = bgp_node->adj_in; ain; ain = ain->next) {
+               int ret;
+               struct bgp_info *bgp_info = bgp_node->info;
+               mpls_label_t *label = NULL;
+               uint32_t num_labels = 0;
+
+               if (bgp_info && bgp_info->extra) {
+                       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);
+
+               if (ret < 0) {
+                       bgp_unlock_node(bgp_node);
+                       return;
+               }
+       }
+}
+
+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;
+
+                       for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+                               if (!bgp->rib[afi][safi])
+                                       continue;
+
+                               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);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+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)
+               return;
+
+       int retval =
+               write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
+       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];
+
+       RPKI_DEBUG("initializing sync socket");
+       if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
+               RPKI_DEBUG("Could not open rpki sync socket");
+               return;
+       }
+       rpki_sync_socket_rtr = fds[0];
+       rpki_sync_socket_bgpd = fds[1];
+       thread_add_read(bm->master, bgpd_sync_callback, NULL,
+                       rpki_sync_socket_bgpd, NULL);
+}
+
 static int bgp_rpki_init(struct thread_master *master)
 {
        rpki_debug = 0;
        rtr_is_running = 0;
+       rtr_is_stopping = 0;
 
        cache_list = list_new();
        cache_list->del = (void (*)(void *)) & free_cache;
@@ -318,6 +482,7 @@ static int bgp_rpki_init(struct thread_master *master)
        initial_synchronisation_timeout =
                INITIAL_SYNCHRONISATION_TIMEOUT_DEFAULT;
        install_cli_commands();
+       rpki_init_sync_socket();
        return 0;
 }
 
@@ -326,6 +491,9 @@ static int bgp_rpki_fini(void)
        stop();
        list_delete_and_null(&cache_list);
 
+       close(rpki_sync_socket_rtr);
+       close(rpki_sync_socket_bgpd);
+
        return 0;
 }
 
@@ -344,6 +512,9 @@ static int start(void)
        unsigned int waiting_time = 0;
        int ret;
 
+       rtr_is_stopping = 0;
+       rtr_is_starting = 1;
+
        if (list_isempty(cache_list)) {
                RPKI_DEBUG(
                        "No caches were found in config. Prefix validation is off.");
@@ -353,9 +524,10 @@ static int start(void)
        int groups_len = listcount(cache_list);
        struct rtr_mgr_group *groups = get_groups();
 
+       RPKI_DEBUG("Polling period: %d", polling_period);
        ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period,
-                          expire_interval, retry_interval, NULL, NULL, NULL,
-                          NULL);
+                          expire_interval, retry_interval,
+                          rpki_update_cb_sync_rtr, NULL, NULL, NULL);
        if (ret == RTR_ERROR) {
                RPKI_DEBUG("Init rtr_mgr failed.");
                return ERROR;
@@ -378,9 +550,13 @@ static int start(void)
        }
        if (rtr_mgr_conf_in_sync(rtr_config)) {
                RPKI_DEBUG("Got synchronisation with at least one RPKI cache!");
+               RPKI_DEBUG("Forcing revalidation.");
+               rtr_is_starting = 0;
+               revalidate_all_routes();
        } else {
                RPKI_DEBUG(
                        "Timeout expired! Proceeding without RPKI validation data.");
+               rtr_is_starting = 0;
        }
 
        XFREE(MTYPE_BGP_RPKI_CACHE_GROUP, groups);
@@ -390,6 +566,7 @@ static int start(void)
 
 static void stop(void)
 {
+       rtr_is_stopping = 1;
        if (rtr_is_running) {
                rtr_mgr_stop(rtr_config);
                rtr_mgr_free(rtr_config);
index 613b924d0d7ace099115d19cb4672a6496cd98c9..94e2d83cfe1ff287f99fbb6430c0a3a1e72f66c3 100644 (file)
@@ -114,3 +114,65 @@ struct bgp_table *bgp_table_init(struct bgp *bgp, afi_t afi, safi_t safi)
 
        return rt;
 }
+
+static struct bgp_node *
+bgp_route_next_until_maxlen(struct bgp_node *node, const struct bgp_node *limit,
+                           const uint8_t maxlen)
+{
+       if (node->l_left && node->p.prefixlen < maxlen
+           && node->l_left->p.prefixlen <= maxlen) {
+               return bgp_node_from_rnode(node->l_left);
+       }
+       if (node->l_right && node->p.prefixlen < maxlen
+           && node->l_right->p.prefixlen <= maxlen) {
+               return bgp_node_from_rnode(node->l_right);
+       }
+
+       while (node->parent && node != limit) {
+               if (bgp_node_from_rnode(node->parent->l_left) == node
+                   && node->parent->l_right) {
+                       return bgp_node_from_rnode(node->parent->l_right);
+               }
+               node = bgp_node_from_rnode(node->parent);
+       }
+       return NULL;
+}
+
+void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p,
+                           uint8_t maxlen, struct list *matches)
+{
+       struct bgp_node *node = bgp_node_from_rnode(table->route_table->top);
+       struct bgp_node *matched = NULL;
+
+       if (node == NULL)
+               return;
+
+       while (node && node->p.prefixlen <= p->prefixlen
+              && prefix_match(&node->p, p)) {
+               if (node->info && node->p.prefixlen == p->prefixlen) {
+                       matched = node;
+                       break;
+               }
+               node = bgp_node_from_rnode(node->link[prefix_bit(
+                       &p->u.prefix, node->p.prefixlen)]);
+       }
+
+       if ((matched == NULL && node->p.prefixlen > maxlen) || !node->parent)
+               return;
+       else if (matched == NULL)
+               matched = node = bgp_node_from_rnode(node->parent);
+
+       if (matched->info) {
+               bgp_lock_node(matched);
+               listnode_add(matches, matched);
+       }
+
+       while ((node = bgp_route_next_until_maxlen(node, matched, maxlen))) {
+               if (prefix_match(p, &node->p)) {
+                       if (node->info) {
+                               bgp_lock_node(node);
+                               listnode_add(matches, node);
+                       }
+               }
+       }
+}
index 388c2472270572ded9e058ff8c50815f29915611..60c2cbd4a483c3e646595ebc4434b2f16badd6ff 100644 (file)
@@ -24,6 +24,7 @@
 #include "mpls.h"
 #include "table.h"
 #include "queue.h"
+#include "linklist.h"
 
 struct bgp_table {
        /* table belongs to this instance */
@@ -309,4 +310,7 @@ static inline uint64_t bgp_table_version(struct bgp_table *table)
        return table->version;
 }
 
+void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p,
+                           uint8_t maxlen, struct list *matches);
+
 #endif /* _QUAGGA_BGP_TABLE_H */
index 641628d4b73ed3a24e9f2de9a3a4726b625dd0ea..f63d591d6f89f86a1c54132633c48f25142593a1 100644 (file)
@@ -772,7 +772,7 @@ static void bgp_clear_star_soft_out(struct vty *vty, const char *name)
 #endif
 
 /* BGP global configuration.  */
-#if defined(VERSION_TYPE_DEV) && (CONFDATE > 20190601)
+#if (CONFDATE > 20190601)
 CPP_NOTICE("bgpd: time to remove deprecated bgp multiple-instance")
 CPP_NOTICE("This includes BGP_OPT_MULTIPLE_INSTANCE")
 #endif
@@ -806,7 +806,7 @@ DEFUN_HIDDEN (no_bgp_multiple_instance,
        return CMD_SUCCESS;
 }
 
-#if defined(VERSION_TYPE_DEV) && (CONFDATE > 20190601)
+#if (CONFDATE > 20190601)
 CPP_NOTICE("bgpd: time to remove deprecated cli bgp config-type cisco")
 CPP_NOTICE("This includes BGP_OPT_CISCO_CONFIG")
 #endif
@@ -928,6 +928,14 @@ DEFUN_NOSH (router_bgp,
                        return CMD_WARNING_CONFIG_FAILED;
                }
 
+               /*
+                * If we just instantiated the default instance, complete
+                * any pending VRF-VPN leaking that was configured via
+                * earlier "router bgp X vrf FOO" blocks.
+                */
+               if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+                       vpn_leak_postchange_all();
+
                /* Pending: handle when user tries to change a view to vrf n vv.
                 */
        }
@@ -2005,7 +2013,7 @@ DEFUN (no_bgp_fast_external_failover,
 }
 
 /* "bgp enforce-first-as" configuration. */
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180517
+#if CONFDATE > 20180517
 CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands")
 #endif
 
@@ -9107,6 +9115,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, uint8_t use_json,
                json_object_string_add(
                        json_neigh, "remoteRouterId",
                        inet_ntop(AF_INET, &p->remote_id, buf1, sizeof(buf1)));
+               json_object_string_add(
+                       json_neigh, "localRouterId",
+                       inet_ntop(AF_INET, &bgp->router_id, buf1,
+                                       sizeof(buf1)));
 
                /* Confederation */
                if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
@@ -9126,7 +9138,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, uint8_t use_json,
                        uptime -= p->uptime;
                        epoch_tbuf = time(NULL) - uptime;
 
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20200101
+#if CONFDATE > 20200101
                        CPP_NOTICE(
                                "bgpTimerUp should be deprecated and can be removed now");
 #endif
index e5b269eb70c27e1f5968aaff4b88df558f8b0129..b5fb653bae1294512e628726b2b8b45ee2d848f3 100644 (file)
@@ -7356,7 +7356,7 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
 }
 
 /* clang-format off */
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180517
+#if CONFDATE > 20180517
 CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write")
 #endif
 /* clang-format on */
index 3ec29cc38fd8637e8b30d33a7a01c673fd60602f..69a55d01eccc5d1455a53967721660efec2fbb89 100755 (executable)
@@ -226,7 +226,14 @@ AC_ARG_ENABLE([memory-sanitizer], AS_HELP_STRING([--enable-memory-sanitizer], \
               ])
 
 dnl if the user has specified any CFLAGS, override our settings
-if test "x${enable_dev_build}" = "xyes"; then
+if test "x${enable_gcov}" = "xyes"; then
+   if test "z$orig_cflags" = "z"; then
+      AC_C_FLAG([-coverage])
+      AC_C_FLAG([-O0])
+   fi
+
+   LDFLAGS="${LDFLAGS} -lgcov"
+elif test "x${enable_dev_build}" = "xyes"; then
    AC_DEFINE(DEV_BUILD,,Build for development)
    if test "z$orig_cflags" = "z"; then
       AC_C_FLAG([-g3])
@@ -441,6 +448,8 @@ AC_ARG_ENABLE([clippy-only],
   AS_HELP_STRING([--enable-clippy-only], [Only build clippy]))
 AC_ARG_ENABLE([numeric_version],
   AS_HELP_STRING([--enable-numeric-version], [Only numeric digits allowed in version (for Alpine)]))
+AC_ARG_ENABLE([gcov],
+  AS_HELP_STRING([--enable-gcov], [Add code coverage information]))
 
 AS_IF([test "${enable_clippy_only}" != "yes"], [
 AC_CHECK_HEADERS(json-c/json.h)
@@ -692,6 +701,11 @@ AC_DEFINE_UNQUOTED(MULTIPATH_NUM, $MPATH_NUM, Maximum number of paths for a rout
 
 AC_DEFINE_UNQUOTED(VTYSH_PAGER, "$VTYSH_PAGER", [What pager to use])
 
+dnl --------------------
+dnl Enable code coverage
+dnl --------------------
+AM_CONDITIONAL([HAVE_GCOV],[test '!' "$enable_gcov" = no])
+
 dnl ------------------------------------
 dnl Alpine only accepts numeric versions
 dnl ------------------------------------
@@ -1818,7 +1832,13 @@ AM_CONDITIONAL([ZEROMQ], test "x$ZEROMQ" = "xtrue")
 dnl ----------
 dnl configure date
 dnl ----------
-CONFDATE=`date '+%Y%m%d'`
+dev_version=`echo $VERSION | grep dev`
+#don't expire deprecated code in non 'dev' branch
+if test "${dev_version}" = ""; then
+   CONFDATE=0
+else
+   CONFDATE=`date '+%Y%m%d'`
+fi
 AC_SUBST(CONFDATE)
 
 dnl ------------------------------
index 1f27e4a8e7fdc42e0794ea41e282a511a5cf2184..62cb3c2edb452e7e859fe6eafef2d863c7ca4a08 100644 (file)
@@ -183,6 +183,7 @@ EXTRA_DIST = frr-sphinx.mk \
        developer/ldpd-basic-test-setup.md \
        developer/library.rst \
        developer/Makefile.in \
+       developer/maintainer-release-build.rst \
        developer/memtypes.rst \
        developer/modules.rst \
        developer/next-hop-tracking.rst \
diff --git a/doc/developer/maintainer-release-build.rst b/doc/developer/maintainer-release-build.rst
new file mode 100644 (file)
index 0000000..907bd14
--- /dev/null
@@ -0,0 +1,89 @@
+Release Build Procedure for FRR maintainers
+=========================================================
+
+1. Rename branch (if needed)
+
+.. code-block:: shell
+
+   git clone git@github.com:FRRouting/frr.git
+   cd frr
+   git checkout dev/5.0
+   git push origin :refs/heads/dev/5.0
+   git push origin dev/5.0:refs/heads/stable/5.0
+
+2. Checkout the new stable branch:
+
+.. code-block:: shell
+
+   git checkout stable/5.0
+
+3. Update Changelog for RedHat Package:
+
+   Edit :file:`redhat/frr.spec.in` and look for the ``%changelog`` section:
+
+   - Change last (top of list) entry from ``%{version}`` to previous fixed
+     version number, i.e.::
+
+        * Tue Nov  7 2017 Martin Winter <mwinter@opensourcerouting.org> - %{version}
+
+     to::
+
+        * Tue Nov  7 2017 Martin Winter <mwinter@opensourcerouting.org> - 3.0.2
+
+   - Add new entry to the top of the list with ``%{version}`` tag and changelog
+     for version.
+     Make sure to watch the format, i.e. the day is always 2 characters, with
+     the 1st character being a space if the day is one digit.
+
+4. Update Changelog for Debian Packages:
+
+   Edit :file:`debianpkg/changelog.in`:
+
+   - Change last (top of list) entry from ``@VERSION@`` to previous fixed
+     version number, i.e.::
+
+        frr (@VERSION@) RELEASED; urgency=medium
+
+     to::
+
+        frr (3.0.2) RELEASED; urgency=medium
+
+   - Add a new entry to the top of the list with a ``@VERSION@`` tag and
+     changelog for version.
+
+5. Change main version number:
+
+    - Edit :file:`configure.ac` and change version in the ``AC_INIT`` command
+    - Create a new entry with the version as ``%{version}`` tag
+
+6. Test building at least a Red Hat and Ubuntu package (or create a PR to have
+   the CI system test them)
+
+7. Commit the changes, adding the changelog to the commit message
+
+8. Create a git tag for the version:
+
+   .. code-block:: shell
+
+      git tag -a frr-5.0 -m "FRRouting Release 5.0"
+
+9. Push the commit and tag(s) and watch for errors on CI:
+
+   .. code-block:: shell
+
+      git push
+      git push --tags
+
+10. Kick off the Release build plan on the CI system for the correct release
+
+11. Send a Release Announcement with changes to
+    ``announce@lists.frrouting.org``
+
+12. Kick off the Snapcraft build plan for the correct release
+
+13. After CI plans succeed, release on GitHub by going to
+    https://github.com/FRRouting/frr/releases and selecting "Draft a new
+    release".
+
+14. Deploy Snapcraft release (after CI system finishes the tests for snapcraft
+    testplan)
index b832413a6cc1e6521e989123ba67d0f6231a1ed5..bde7682e4e30bd740c602a60cd69bdfcaa8f84d0 100644 (file)
@@ -100,6 +100,15 @@ a function that removes all of a module's installed hooks.
 There's also the ``frr_module`` symbol in modules, pretty much a
 standard entry point for loadable modules.
 
+Command line parameters
+-----------------------
+
+Command line parameters can be passed directly to a module by appending a 
+colon to the module name when loading it, e.g. ``-M mymodule:myparameter``. 
+The text after the colon will be accessible in the module's code through 
+``THIS_MODULE->load_args``. For example, see how the format parameter is
+configured in the ``zfpm_init()`` function inside ``zebra_fpm.c``.
+
 Hooks
 -----
 
index b29769da4947592de6355697719b502d69989020..358cb9ac7bf79434e8fe09e147ba954e2755d990 100644 (file)
@@ -300,6 +300,37 @@ Documentation should be written in reStructuredText. Sphinx extensions may be
 utilized but pure ReST is preferred where possible. See
 :ref:`documentation`.
 
+Code Reviews
+============
+
+Code quality is paramount for any large program. Consequently we require
+reviews of all submitted patches by at least one person other than the
+submitter before the patch is merged.
+
+Because of the nature of the software, FRR's maintainer list (i.e. those with
+commit permissions) tends to contain employees / members of various
+organizations. In order to prevent conflicts of interest, we use an honor
+system in which submissions from an individual representing one company should
+be merged by someone unaffiliated with that company.
+
+Guidelines for code review
+""""""""""""""""""""""""""
+
+- As a rule of thumb, the depth of the review should be proportional to the
+  scope and / or impact of the patch.
+
+- Anyone may review a patch.
+
+- When using GitHub reviews, marking "Approve" on a code review indicates
+  willingness to merge the PR.
+
+- For individuals with merge rights, marking "Changes requested" is equivalent
+  to a NAK.
+
+- For a PR you marked with "Changes requested", please respond to updates in a
+  timely manner to avoid impeding the flow of development.
+
+
 Coding Practices & Style
 ========================
 
@@ -745,7 +776,7 @@ annotations must be ignored non-development branches. For example:
 
 .. code-block:: c
 
-   #if defined(VERSION_TYPE_DEV) && CONFDATE > 20180403
+   #if CONFDATE > 20180403
    CPP_NOTICE("Use of <XYZ> is deprecated, please use <ABC>")
    #endif
 
index 0fb27441b21188aa484b811ce5ab785164f8ee69..579b0b6497edeee2f0909af0962b8da281409ff3 100644 (file)
@@ -1783,8 +1783,8 @@ kernel routing tables.
        neighbor 10.0.0.3 remote-as 4
        neighbor 10.0.0.4 remote-as 5
 
-.. index:: show ip bgp view NAME
-.. clicmd:: show ip bgp view NAME
+.. index:: show [ip] bgp view NAME
+.. clicmd:: show [ip] bgp view NAME
 
    Display the routing table of BGP view ``NAME``.
 
@@ -1981,17 +1981,27 @@ Other BGP Commands
 Displaying BGP Information
 ==========================
 
+The following four commands display the IPv6 and IPv4 routing tables, depending
+on whether or not the ``ip`` keyword is used.
+Actually, :clicmd:`show ip bgp` command was used on older `Quagga` routing
+daemon project, while :clicmd:`show bgp` command is the new format. The choice
+has been done to keep old format with IPv4 routing table, while new format
+displays IPv6 routing table.
+
 .. index:: show ip bgp
 .. clicmd:: show ip bgp
 
 .. index:: show ip bgp A.B.C.D
 .. clicmd:: show ip bgp A.B.C.D
 
-.. index:: show ip bgp X:X::X:X
-.. clicmd:: show ip bgp X:X::X:X
+.. index:: show bgp
+.. clicmd:: show bgp
+
+.. index:: show bgp X:X::X:X
+.. clicmd:: show bgp X:X::X:X
 
    These commands display BGP routes. When no route is specified, the default
-   is to display all IPv4 BGP routes.
+   is to display all BGP routes.
 
    ::
 
@@ -2004,31 +2014,56 @@ Displaying BGP Information
 
          Total number of prefixes 1
 
-.. index:: show ip bgp regexp LINE
-.. clicmd:: show ip bgp regexp LINE
+Some other commands provide additional options for filtering the output.
+
+.. index:: show [ip] bgp regexp LINE
+.. clicmd:: show [ip] bgp regexp LINE
 
    This command displays BGP routes using AS path regular expression
    (:ref:`bgp-regular-expressions`).
 
-.. index:: show bgp <ipv4|ipv6> summary
-.. clicmd:: show bgp <ipv4|ipv6> summary
+.. index:: show [ip] bgp summary
+.. clicmd:: show [ip] bgp summary
 
    Show a bgp peer summary for the specified address family.
 
-.. index:: show bgp <ipv4|ipv6> neighbor [PEER]
-.. clicmd:: show bgp <ipv4|ipv6> neighbor [PEER]
+The old command structure :clicmd:`show ip bgp` may be removed in the future
+and should no longer be used. In order to reach the other BGP routing tables
+other than the IPv6 routing table given by :clicmd:`show bgp`, the new command
+structure is extended with :clicmd:`show bgp [afi] [safi]`.
+
+.. index:: show bgp [afi] [safi]
+.. clicmd:: show bgp [afi] [safi]
+
+.. index:: show bgp <ipv4|ipv6> <unicast|multicast|vpn|labeled-unicast>
+.. clicmd:: show bgp <ipv4|ipv6> <unicast|multicast|vpn|labeled-unicast>
+
+   These commands display BGP routes for the specific routing table indicated by
+   the selected afi and the selected safi. If no afi and no safi value is given,
+   the command falls back to the default IPv6 routing table
+
+.. index:: show bgp [afi] [safi] summary
+.. clicmd:: show bgp [afi] [safi] summary
+
+   Show a bgp peer summary for the specified address family, and subsequent
+   address-family.
+
+.. index:: show bgp [afi] [safi] neighbor [PEER]
+.. clicmd:: show bgp [afi] [safi] neighbor [PEER]
 
-   This command shows information on a specific BGP `peer`.
+   This command shows information on a specific BGP peer of the relevant
+   afi and safi selected.
 
-.. index:: show bgp <ipv4|ipv6> dampening dampened-paths
-.. clicmd:: show bgp <ipv4|ipv6> dampening dampened-paths
+.. index:: show bgp [afi] [safi] dampening dampened-paths
+.. clicmd:: show bgp [afi] [safi] dampening dampened-paths
 
-   Display paths suppressed due to dampening.
+   Display paths suppressed due to dampening of the selected afi and safi
+   selected.
 
-.. index:: show bgp <ipv4|ipv6> dampening flap-statistics
-.. clicmd:: show bgp <ipv4|ipv6> dampening flap-statistics
+.. index:: show bgp [afi] [safi] dampening flap-statistics
+.. clicmd:: show bgp [afi] [safi] dampening flap-statistics
 
-   Display flap statistics of routes.
+   Display flap statistics of routes of the selected afi and safi selected.
 
 .. _bgp-display-routes-by-community:
 
@@ -2073,11 +2108,11 @@ Displaying Routes by AS Path
    This commands displays BGP routes that matches a regular
    expression `line` (:ref:`bgp-regular-expressions`).
 
-.. index:: show ip bgp ipv4 vpn
-.. clicmd:: show ip bgp ipv4 vpn
+.. index:: show [ip] bgp ipv4 vpn
+.. clicmd:: show [ip] bgp ipv4 vpn
 
-.. index:: show ip bgp ipv6 vpn
-.. clicmd:: show ip bgp ipv6 vpn
+.. index:: show [ip] bgp ipv6 vpn
+.. clicmd:: show [ip] bgp ipv6 vpn
 
    Print active IPV4 or IPV6 routes advertised via the VPN SAFI.
 
index 26d30f1e10e71ca00ab934a16243a647b3a71412..158e2c8595243418b726194b38d873d8a682e8ad 100644 (file)
@@ -205,6 +205,15 @@ options from the list below.
    hardcoded arrays that FRR builds towards, so we need to know how big to
    make these arrays at build time.
 
+.. option:: --enable-gcov
+
+   Code coverage reports from gcov require adjustments to the C and LD flags.
+   With this option, gcov instrumentation is added to the build and coverage
+   reports are created during execution.  The check-coverage make target is
+   also created to ease report uploading to codecov.io.  The upload requires
+   the COMMIT (git hash) and TOKEN (codecov upload token) environment variables
+   be set.
+
 You may specify any combination of the above options to the configure
 script. By default, the executables are placed in :file:`/usr/local/sbin`
 and the configuration files in :file:`/usr/local/etc`. The :file:`/usr/local/`
index 93a8e4396a261d113ea2e13f992ebcb530fe8447..38b2b68e98e022520f1b01f0cf3bf83ed7099ed4 100644 (file)
@@ -44,6 +44,9 @@ In a nutshell, the current implementation provides the following features
 - Route maps can be configured to match a specific RPKI validation state. This
   allows the creation of local policies, which handle BGP routes based on the
   outcome of the Prefix Origin Validation.
+- Updates from the RPKI cache servers are directly applied and path selection
+  is updated accordingly. (Soft reconfiguration **must** be enabled for this
+  to work).
 
 
 .. _enabling-rpki:
@@ -65,6 +68,32 @@ Enabling RPKI
 
 .. _configuring-rpki-rtr-cache-servers:
 
+.. index:: daemons.conf
+
+   When first installing FRR with RPKI support from the pre-packaged binaries. Remember
+   to append '-M rpki' in the /etc/frr/daemons.conf file to the bgpd_options.
+   
+   bgpd_options="   --daemon -A 127.0.0.1 -M rpki"
+   instead of the default setting
+   bgpd_options="   --daemon -A 127.0.0.1"
+   
+
+   Else you will encounter an error when trying to enter RPKI configuration mode. Because
+   the rpki module is not loaded when the BGP daemon is initialized.
+
+   Examples of the error:
+
+   router(config)# debug rpki
+   % [BGP] Unknown command: debug rpki
+   
+   router(config)# rpki
+   % [BGP] Unknown command: rpki
+   
+   Note that the rpki commands will be available in vtysh when running 'find rpki'.
+   Even if the RPKI module is NOT loaded.
+   The RPKI commands will be unavailable if you try running the same command in the
+   cli specific to the BGP daemon.
+
 Configuring RPKI/RTR Cache Servers
 ----------------------------------
 
diff --git a/docker/alpine/Dockerfile-coverage b/docker/alpine/Dockerfile-coverage
new file mode 100644 (file)
index 0000000..5fdb117
--- /dev/null
@@ -0,0 +1,12 @@
+FROM alpine:3.7
+ARG commit
+ARG token
+ENV COMMIT=${commit}
+ENV TOKEN=${token}
+ADD . /src
+RUN cd /src && \
+       source alpine/APKBUILD.in && \
+       apk add --no-cache alpine-sdk $makedepends $checkdepends && \
+       ./bootstrap.sh && \
+       ./configure --enable-gcov
+ENTRYPOINT [ "/bin/sh", "-c", "cd /src && make && make -j 1 check-coverage" ]
index f8df33d3ee99df7f2afa07d7f21cd7380cc8021c..d51f31ff3728d7055848e5ee27cba29675c77ec9 100644 (file)
@@ -638,7 +638,7 @@ int isis_circuit_up(struct isis_circuit *circuit)
                        thread_add_timer(master, isis_run_dr_l2, circuit,
                                         2 * circuit->hello_interval[1],
                                         &circuit->u.bc.t_run_dr[1]);
-       } else {
+       } else if (circuit->circ_type == CIRCUIT_T_P2P) {
                /* initializing the hello send threads
                 * for a ptp IF
                 */
@@ -682,9 +682,6 @@ int isis_circuit_up(struct isis_circuit *circuit)
 
 void isis_circuit_down(struct isis_circuit *circuit)
 {
-       if (circuit->state != C_STATE_UP)
-               return;
-
        /* Clear the flags for all the lsps of the circuit. */
        isis_circuit_update_all_srmflags(circuit, 0);
 
@@ -756,10 +753,12 @@ void isis_circuit_down(struct isis_circuit *circuit)
        }
 
        /* send one gratuitous hello to spead up convergence */
-       if (circuit->is_type & IS_LEVEL_1)
-               send_hello(circuit, IS_LEVEL_1);
-       if (circuit->is_type & IS_LEVEL_2)
-               send_hello(circuit, IS_LEVEL_2);
+       if (circuit->state == C_STATE_UP) {
+               if (circuit->is_type & IS_LEVEL_1)
+                       send_hello(circuit, IS_LEVEL_1);
+               if (circuit->is_type & IS_LEVEL_2)
+                       send_hello(circuit, IS_LEVEL_2);
+       }
 
        circuit->upadjcount[0] = 0;
        circuit->upadjcount[1] = 0;
index 773a52e742eb20bb1adb93b31116f541c6b7e430..b19c33f65e6b3de860ae46f58e791429c67b4c65 100644 (file)
@@ -76,6 +76,7 @@
 
 #else
 #define CPP_WARN(text)
+#define CPP_NOTICE(text)
 #endif
 
 #endif /* _FRR_COMPILER_H */
index 5f391aa7670435486d46e773b1ad96ac8de70b19..670c65374a0fbc1fefd3afef7cbc9a6d679a89ec 100644 (file)
@@ -549,8 +549,7 @@ static int vty_access_list_remark_unset(struct vty *vty, afi_t afi,
                access->remark = NULL;
        }
 
-       if (access->head == NULL && access->tail == NULL
-           && access->remark == NULL)
+       if (access->head == NULL && access->tail == NULL)
                access_list_delete(access);
 
        return CMD_SUCCESS;
index 2541e6e45affd5893f278a532c06c54eb8c298ec..2320093a15c6e6428d461c6ee8f4d9d3d831c725 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -222,18 +222,6 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
        struct vrf *vrf;
        struct interface if_tmp;
 
-       if (vrf_id == VRF_UNKNOWN) {
-               struct interface *ifp;
-
-               RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
-                       ifp = if_lookup_by_index(ifindex, vrf->vrf_id);
-                       if (ifp)
-                               return ifp;
-               }
-
-               return NULL;
-       }
-
        vrf = vrf_lookup_by_id(vrf_id);
        if (!vrf)
                return NULL;
index 1e2631ea46157157d05f406adb052cbcb9524637..cee6c1e505e54a4b565df32cec9bc49823760f71 100644 (file)
@@ -232,7 +232,7 @@ extern void list_sort(struct list *list,
  * and remove list_delete_original and the list_delete #define
  * Additionally remove list_free entirely
  */
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20181001
+#if CONFDATE > 20181001
 CPP_NOTICE("list_delete without double pointer is deprecated, please fixup")
 #endif
 
index 0c853640035a9c34d7aca1e1056e597513b51bc3..7d5671290bc75c28e056d4bde0bacb5eea476c9e 100644 (file)
@@ -85,7 +85,7 @@ struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err,
                *args++ = '\0';
 
        if (!strchr(name, '/')) {
-               if (!handle && execname) {
+               if (execname) {
                        snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", dir,
                                 execname, name);
                        handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
index a44f4e35426e65f21b072d0347975d7a3fa43af5..473ecb34fc4df110bf0b3d27be0261f5e9a5ba21 100644 (file)
@@ -56,6 +56,11 @@ void copy_nexthops(struct nexthop **tnh, struct nexthop *nh,
        (nhop);                                                         \
        (nhop) = nexthop_next(nhop)
 
+#define ALL_NEXTHOPS_PTR(head, nhop)                                   \
+       (nhop) = ((head)->nexthop);                                     \
+       (nhop);                                                         \
+       (nhop) = nexthop_next(nhop)
+
 
 struct nexthop_hold {
        char *nhvrf_name;
index a70574cff2022e4cba51be92a462a574a45da7ce..32f8e8ca5b473d6c7eb21185edc00648ac6535ee 100644 (file)
@@ -127,7 +127,7 @@ route_table_delegate_t _srcdest_srcnode_delegate = {
 
 /* NB: read comments in code for refcounting before using! */
 static struct route_node *srcdest_srcnode_get(struct route_node *rn,
-                                             struct prefix_ipv6 *src_p)
+                                             const struct prefix_ipv6 *src_p)
 {
        struct srcdest_rnode *srn;
 
@@ -158,11 +158,12 @@ static struct route_node *srcdest_srcnode_get(struct route_node *rn,
                route_unlock_node(rn);
        }
 
-       return route_node_get(srn->src_table, (struct prefix *)src_p);
+       return route_node_get(srn->src_table, (const struct prefix *)src_p);
 }
 
-static struct route_node *srcdest_srcnode_lookup(struct route_node *rn,
-                                                struct prefix_ipv6 *src_p)
+static struct route_node *srcdest_srcnode_lookup(
+       struct route_node *rn,
+       const struct prefix_ipv6 *src_p)
 {
        struct srcdest_rnode *srn;
 
@@ -180,7 +181,7 @@ static struct route_node *srcdest_srcnode_lookup(struct route_node *rn,
        if (!srn->src_table)
                return NULL;
 
-       return route_node_lookup(srn->src_table, (struct prefix *)src_p);
+       return route_node_lookup(srn->src_table, (const struct prefix *)src_p);
 }
 
 /* ----- exported functions ----- */
@@ -233,25 +234,25 @@ struct route_node *srcdest_route_next(struct route_node *rn)
 }
 
 struct route_node *srcdest_rnode_get(struct route_table *table,
-                                    union prefixptr dst_pu,
-                                    struct prefix_ipv6 *src_p)
+                                    union prefixconstptr dst_pu,
+                                    const struct prefix_ipv6 *src_p)
 {
-       struct prefix_ipv6 *dst_p = dst_pu.p6;
+       const struct prefix_ipv6 *dst_p = dst_pu.p6;
        struct route_node *rn;
 
-       rn = route_node_get(table, (struct prefix *)dst_p);
+       rn = route_node_get(table, (const struct prefix *)dst_p);
        return srcdest_srcnode_get(rn, src_p);
 }
 
 struct route_node *srcdest_rnode_lookup(struct route_table *table,
-                                       union prefixptr dst_pu,
-                                       struct prefix_ipv6 *src_p)
+                                       union prefixconstptr dst_pu,
+                                       const struct prefix_ipv6 *src_p)
 {
-       struct prefix_ipv6 *dst_p = dst_pu.p6;
+       const struct prefix_ipv6 *dst_p = dst_pu.p6;
        struct route_node *rn;
        struct route_node *srn;
 
-       rn = route_node_lookup_maynull(table, (struct prefix *)dst_p);
+       rn = route_node_lookup_maynull(table, (const struct prefix *)dst_p);
        srn = srcdest_srcnode_lookup(rn, src_p);
 
        if (rn != NULL && rn == srn && !rn->info) {
@@ -263,8 +264,8 @@ struct route_node *srcdest_rnode_lookup(struct route_table *table,
        return srn;
 }
 
-void srcdest_rnode_prefixes(struct route_node *rn, struct prefix **p,
-                           struct prefix **src_p)
+void srcdest_rnode_prefixes(struct route_node *rn, const struct prefix **p,
+                           const struct prefix **src_p)
 {
        if (rnode_is_srcnode(rn)) {
                struct route_node *dst_rn = rn->table->info;
@@ -282,7 +283,7 @@ void srcdest_rnode_prefixes(struct route_node *rn, struct prefix **p,
 
 const char *srcdest_rnode2str(struct route_node *rn, char *str, int size)
 {
-       struct prefix *dst_p, *src_p;
+       const struct prefix *dst_p, *src_p;
        char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN];
 
        srcdest_rnode_prefixes(rn, &dst_p, &src_p);
index 669068a79b4f7ec095e6a2197e117bd5c143f0ba..5f97f02bacfd757707dba9b87eba39ebc8eddd80 100644 (file)
@@ -56,13 +56,14 @@ extern route_table_delegate_t _srcdest_srcnode_delegate;
 
 extern struct route_table *srcdest_table_init(void);
 extern struct route_node *srcdest_rnode_get(struct route_table *table,
-                                           union prefixptr dst_pu,
-                                           struct prefix_ipv6 *src_p);
+                                           union prefixconstptr dst_pu,
+                                           const struct prefix_ipv6 *src_p);
 extern struct route_node *srcdest_rnode_lookup(struct route_table *table,
-                                              union prefixptr dst_pu,
-                                              struct prefix_ipv6 *src_p);
-extern void srcdest_rnode_prefixes(struct route_node *rn, struct prefix **p,
-                                  struct prefix **src_p);
+                                              union prefixconstptr dst_pu,
+                                              const struct prefix_ipv6 *src_p);
+extern void srcdest_rnode_prefixes(struct route_node *rn,
+                                  const struct prefix **p,
+                                  const struct prefix **src_p);
 extern const char *srcdest_rnode2str(struct route_node *rn, char *str,
                                     int size);
 extern struct route_node *srcdest_route_next(struct route_node *rn);
index 11af85c663d086438a270f4879742f2c547eaef3..e808f039c623c07468df2ade9792c85648931a06 100644 (file)
@@ -133,7 +133,7 @@ struct stream_fifo {
 #define STREAM_CONCAT_REMAIN(S1, S2, size) ((size) - (S1)->endp - (S2)->endp)
 
 /* deprecated macros - do not use in new code */
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20181128
+#if CONFDATE > 20181128
 CPP_NOTICE("lib: time to remove deprecated stream.h macros")
 #endif
 #define STREAM_PNT(S)   stream_pnt((S))
index 643ad29cf865782d0e4a0f12c57248f8bcdc87c8..ca50c1e70e8578f7d09b9047ca54598b4d0b4903 100644 (file)
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -628,7 +628,7 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
        }
        if (vrf->ns_ctxt != NULL) {
                ns = (struct ns *)vrf->ns_ctxt;
-               if (ns && 0 != strcmp(ns->name, pathname)) {
+               if (!strcmp(ns->name, pathname)) {
                        if (vty)
                                vty_out(vty,
                                        "VRF %u already configured with NETNS %s\n",
@@ -661,8 +661,7 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
        ns->vrf_ctxt = (void *)vrf;
        vrf->ns_ctxt = (void *)ns;
        /* update VRF netns NAME */
-       if (vrf)
-               strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ);
+       strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ);
 
        if (!ns_enable(ns, vrf_update_vrf_id)) {
                if (vty)
index 6085820393d65865809bd06760c1b70759b2eb99..fe1700f8ded5aaf79eff7b3a232d9e51c1cdac29 100644 (file)
@@ -154,7 +154,7 @@ extern struct work_queue *work_queue_new(struct thread_master *, const char *);
  * The usage of work_queue_free is being transitioned to pass
  * in the double pointer to remove use after free's.
  */
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20190205
+#if CONFDATE > 20190205
 CPP_NOTICE("work_queue_free without double pointer is deprecated, please fixup")
 #endif
 extern void work_queue_free_and_null(struct work_queue **);
index ad98b8db8776d39d7bd2f65839184e5dc4893f57..10a1723010ba4e4c893bbacc21ac5c299f131f1a 100644 (file)
@@ -457,7 +457,7 @@ struct zclient_options {
 extern struct zclient *zclient_new(struct thread_master *);
 
 /* clang-format off */
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20181101
+#if CONFDATE > 20181101
 CPP_NOTICE("zclient_new_notify can take over or zclient_new now");
 #endif
 /* clang-format on */
@@ -598,7 +598,7 @@ 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 defined(VERSION_TYPE_DEV) && CONFDATE > 20180823
+#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 */
index 7bf099fbbfb2dd33bc0c008e41ca7a6812e12e88..fde47c74fef9e8a148ee522de1d24f734af5cb00 100644 (file)
@@ -425,13 +425,13 @@ DEFUN(no_ospf6_router_id,
        return CMD_SUCCESS;
 }
 
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180828
+#if CONFDATE > 20180828
 CPP_NOTICE("ospf6: `router-id A.B.C.D` deprecated 2017/08/28")
 #endif
 ALIAS_HIDDEN(ospf6_router_id, ospf6_router_id_hdn_cmd, "router-id A.B.C.D",
             "Configure OSPF6 Router-ID\n" V4NOTATION_STR)
 
-#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180828
+#if CONFDATE > 20180828
 CPP_NOTICE("ospf6: `no router-id A.B.C.D` deprecated 2017/08/28")
 #endif
 ALIAS_HIDDEN(no_ospf6_router_id, no_ospf6_router_id_hdn_cmd,
index ae2daf40aa709834126c393e9fd4027937ca3a60..460bbfeae71e6cffafef255ae37c429a5d9a5c1d 100644 (file)
@@ -4252,7 +4252,7 @@ DEFUN (show_ip_pim_nexthop_lookup,
        "Source/RP address\n"
        "Multicast Group address\n")
 {
-       struct pim_nexthop_cache pnc;
+       struct pim_nexthop_cache *pnc = NULL;
        struct prefix nht_p;
        int result = 0;
        struct in_addr src_addr, grp_addr;
@@ -4264,6 +4264,7 @@ DEFUN (show_ip_pim_nexthop_lookup,
        char grp_str[PREFIX_STRLEN];
        int idx = 2;
        struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+       struct pim_rpf rpf;
 
        if (!vrf)
                return CMD_WARNING;
@@ -4301,7 +4302,6 @@ DEFUN (show_ip_pim_nexthop_lookup,
                                      grp_addr))
                return CMD_SUCCESS;
 
-       memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
        nht_p.family = AF_INET;
        nht_p.prefixlen = IPV4_MAX_BITLEN;
        nht_p.u.prefix4 = vif_source;
@@ -4310,12 +4310,18 @@ DEFUN (show_ip_pim_nexthop_lookup,
        grp.u.prefix4 = grp_addr;
        memset(&nexthop, 0, sizeof(nexthop));
 
-       if (pim_find_or_track_nexthop(vrf->info, &nht_p, NULL, NULL, &pnc))
-               result = pim_ecmp_nexthop_search(vrf->info, &pnc, &nexthop,
+       memset(&rpf, 0, sizeof(struct pim_rpf));
+       rpf.rpf_addr.family = AF_INET;
+       rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
+       rpf.rpf_addr.u.prefix4 = vif_source;
+
+       pnc = pim_nexthop_cache_find(vrf->info, &rpf);
+       if (pnc)
+               result = pim_ecmp_nexthop_search(vrf->info, pnc, &nexthop,
                                                 &nht_p, &grp, 0);
        else
-               result = pim_ecmp_nexthop_lookup(vrf->info, &nexthop,
-                                                vif_source, &nht_p, &grp, 0);
+               result = pim_ecmp_nexthop_lookup(vrf->info, &nexthop, &nht_p,
+                                                &grp, 0);
 
        if (!result) {
                vty_out(vty,
index e82a7589b719a72447cbf1fcff1fbfffbf2cdbd2..eb3307589ec0b826e8470974157a3385c44dd77a 100644 (file)
@@ -136,9 +136,8 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
                        mask = PIM_OIF_FLAG_PROTO_IGMP;
 
                /* SGRpt entry could have empty oil */
-               if (ch->upstream->channel_oil)
-                       pim_channel_del_oif(ch->upstream->channel_oil,
-                                           ch->interface, mask);
+               pim_channel_del_oif(ch->upstream->channel_oil, ch->interface,
+                                   mask);
                /*
                 * Do we have any S,G's that are inheriting?
                 * Nuke from on high too.
index 42bdd80ce226614b4653865dc377c7efbcf3a4a9..b46f1b5e9dde1870297c7fcb633d64bcc2a3fa83 100644 (file)
@@ -909,10 +909,9 @@ static int pim_igmp_read(struct thread *t)
        socklen_t fromlen = sizeof(from);
        socklen_t tolen = sizeof(to);
        ifindex_t ifindex = -1;
-       int cont = 1;
        int len;
 
-       while (cont) {
+       while (1) {
                len = pim_socket_recvfromto(igmp->fd, buf, sizeof(buf), &from,
                                            &fromlen, &to, &tolen, &ifindex);
                if (len < 0) {
index ac49373da07a07fccc7c1508ebcc7b91c4983b7a..78152b266f0fad8fec0e8e75c51ef737097ef32b 100644 (file)
@@ -418,12 +418,14 @@ int pim_ecmp_nexthop_search(struct pim_instance *pim,
                            struct pim_nexthop *nexthop, struct prefix *src,
                            struct prefix *grp, int neighbor_needed)
 {
-       struct pim_neighbor *nbr = NULL;
+       struct pim_neighbor *nbrs[MULTIPATH_NUM], *nbr;
+       struct interface *ifps[MULTIPATH_NUM];
        struct nexthop *nh_node = NULL;
        ifindex_t first_ifindex;
        struct interface *ifp = NULL;
        uint32_t hash_val = 0, mod_val = 0;
        uint8_t nh_iter = 0, found = 0;
+       uint32_t i, num_nbrs = 0;
 
        if (!pnc || !pnc->nexthop_num || !nexthop)
                return 0;
@@ -487,16 +489,41 @@ int pim_ecmp_nexthop_search(struct pim_instance *pim,
                        }
                }
        }
+
+       /*
+        * Look up all interfaces and neighbors,
+        * store for later usage
+        */
+       for (nh_node = pnc->nexthop, i = 0; nh_node;
+            nh_node = nh_node->next, i++) {
+               ifps[i] = if_lookup_by_index(nh_node->ifindex, pim->vrf_id);
+               if (ifps[i]) {
+                       nbrs[i] = pim_neighbor_find(ifps[i],
+                                                   nh_node->gate.ipv4);
+                       if (nbrs[i] || pim_if_connected_to_source(ifps[i],
+
+                                                                 src->u.prefix4))
+                               num_nbrs++;
+               }
+       }
        if (pim->ecmp_enable) {
+               uint32_t consider = pnc->nexthop_num;
+
+               if (neighbor_needed && num_nbrs < consider)
+                       consider = num_nbrs;
+
+               if (consider == 0)
+                       return 0;
+
                // PIM ECMP flag is enable then choose ECMP path.
                hash_val = pim_compute_ecmp_hash(src, grp);
-               mod_val = hash_val % pnc->nexthop_num;
+               mod_val = hash_val % consider;
        }
 
        for (nh_node = pnc->nexthop; nh_node && (found == 0);
             nh_node = nh_node->next) {
                first_ifindex = nh_node->ifindex;
-               ifp = if_lookup_by_index(first_ifindex, pim->vrf_id);
+               ifp = ifps[nh_iter];
                if (!ifp) {
                        if (PIM_DEBUG_PIM_NHT) {
                                char addr_str[INET_ADDRSTRLEN];
@@ -532,7 +559,7 @@ int pim_ecmp_nexthop_search(struct pim_instance *pim,
 
                if (neighbor_needed
                    && !pim_if_connected_to_source(ifp, src->u.prefix4)) {
-                       nbr = pim_neighbor_find(ifp, nh_node->gate.ipv4);
+                       nbr = nbrs[nh_iter];
                        if (!nbr && !if_is_loopback(ifp)) {
                                if (PIM_DEBUG_PIM_NHT)
                                        zlog_debug(
@@ -767,22 +794,23 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient,
 }
 
 int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
-                           struct pim_nexthop *nexthop, struct in_addr addr,
-                           struct prefix *src, struct prefix *grp,
-                           int neighbor_needed)
+                           struct pim_nexthop *nexthop, struct prefix *src,
+                           struct prefix *grp, int neighbor_needed)
 {
        struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
-       struct pim_neighbor *nbr = NULL;
+       struct pim_neighbor *nbrs[MULTIPATH_NUM], *nbr = NULL;
        int num_ifindex;
-       struct interface *ifp;
+       struct interface *ifps[MULTIPATH_NUM], *ifp;
        int first_ifindex;
        int found = 0;
        uint8_t i = 0;
        uint32_t hash_val = 0, mod_val = 0;
+       uint32_t num_nbrs = 0;
+       char addr_str[PREFIX_STRLEN];
 
        if (PIM_DEBUG_PIM_NHT) {
-               char addr_str[INET_ADDRSTRLEN];
-               pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
+               pim_inet4_dump("<addr?>", src->u.prefix4, addr_str,
+                              sizeof(addr_str));
                zlog_debug("%s: Looking up: %s(%s), last lookup time: %lld",
                           __PRETTY_FUNCTION__, addr_str, pim->vrf->name,
                           nexthop->last_lookup_time);
@@ -790,44 +818,63 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
 
        memset(nexthop_tab, 0,
               sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM);
-       num_ifindex = zclient_lookup_nexthop(pim, nexthop_tab, MULTIPATH_NUM,
-                                            addr, PIM_NEXTHOP_LOOKUP_MAX);
+       num_ifindex =
+               zclient_lookup_nexthop(pim, nexthop_tab, MULTIPATH_NUM,
+                                      src->u.prefix4, PIM_NEXTHOP_LOOKUP_MAX);
        if (num_ifindex < 1) {
-               if (PIM_DEBUG_PIM_NHT) {
-                       char addr_str[INET_ADDRSTRLEN];
-                       pim_inet4_dump("<addr?>", addr, addr_str,
-                                      sizeof(addr_str));
+               if (PIM_DEBUG_PIM_NHT)
                        zlog_warn(
                                "%s: could not find nexthop ifindex for address %s(%s)",
                                __PRETTY_FUNCTION__, addr_str, pim->vrf->name);
-               }
                return 0;
        }
 
+       /*
+        * Look up all interfaces and neighbors,
+        * store for later usage
+        */
+       for (i = 0; i < num_ifindex; i++) {
+               ifps[i] = if_lookup_by_index(nexthop_tab[i].ifindex,
+                                            pim->vrf_id);
+               if (ifps[i]) {
+                       nbrs[i] = pim_neighbor_find(
+                               ifps[i], nexthop_tab[i].nexthop_addr.u.prefix4);
+                       if (nbrs[i]
+                           || pim_if_connected_to_source(ifps[i],
+                                                         src->u.prefix4))
+                               num_nbrs++;
+               }
+       }
+
        // If PIM ECMP enable then choose ECMP path.
        if (pim->ecmp_enable) {
+               uint32_t consider = num_ifindex;
+
+               if (neighbor_needed && num_nbrs < consider)
+                       consider = num_nbrs;
+
+               if (consider == 0)
+                       return 0;
+
                hash_val = pim_compute_ecmp_hash(src, grp);
-               mod_val = hash_val % num_ifindex;
+               mod_val = hash_val % consider;
                if (PIM_DEBUG_PIM_NHT_DETAIL)
                        zlog_debug("%s: hash_val %u mod_val %u",
                                   __PRETTY_FUNCTION__, hash_val, mod_val);
        }
 
+       i = 0;
        while (!found && (i < num_ifindex)) {
                first_ifindex = nexthop_tab[i].ifindex;
 
-               ifp = if_lookup_by_index(first_ifindex, pim->vrf_id);
+               ifp = ifps[i];
                if (!ifp) {
-                       if (PIM_DEBUG_PIM_NHT) {
-                               char addr_str[INET_ADDRSTRLEN];
-                               pim_inet4_dump("<addr?>", addr, addr_str,
-                                              sizeof(addr_str));
+                       if (PIM_DEBUG_PIM_NHT)
                                zlog_debug(
                                        "%s %s: could not find interface for ifindex %d (address %s(%s))",
                                        __FILE__, __PRETTY_FUNCTION__,
                                        first_ifindex, addr_str,
                                        pim->vrf->name);
-                       }
                        if (i == mod_val)
                                mod_val++;
                        i++;
@@ -835,24 +882,20 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
                }
 
                if (!ifp->info) {
-                       if (PIM_DEBUG_PIM_NHT) {
-                               char addr_str[INET_ADDRSTRLEN];
-                               pim_inet4_dump("<addr?>", addr, addr_str,
-                                              sizeof(addr_str));
+                       if (PIM_DEBUG_PIM_NHT)
                                zlog_debug(
                                        "%s: multicast not enabled on input interface %s(%s) (ifindex=%d, RPF for source %s)",
                                        __PRETTY_FUNCTION__, ifp->name,
                                        pim->vrf->name, first_ifindex,
                                        addr_str);
-                       }
                        if (i == mod_val)
                                mod_val++;
                        i++;
                        continue;
                }
-               if (neighbor_needed && !pim_if_connected_to_source(ifp, addr)) {
-                       nbr = pim_neighbor_find(
-                               ifp, nexthop_tab[i].nexthop_addr.u.prefix4);
+               if (neighbor_needed
+                   && !pim_if_connected_to_source(ifp, src->u.prefix4)) {
+                       nbr = nbrs[i];
                        if (PIM_DEBUG_PIM_NHT_DETAIL)
                                zlog_debug("ifp name: %s(%s), pim nbr: %p",
                                           ifp->name, pim->vrf->name, nbr);
@@ -860,16 +903,11 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
                                if (i == mod_val)
                                        mod_val++;
                                i++;
-                               if (PIM_DEBUG_PIM_NHT) {
-                                       char addr_str[INET_ADDRSTRLEN];
-                                       pim_inet4_dump("<addr?>", addr,
-                                                      addr_str,
-                                                      sizeof(addr_str));
+                               if (PIM_DEBUG_PIM_NHT)
                                        zlog_debug(
                                                "%s: NBR not found on input interface %s(%s) (RPF for source %s)",
                                                __PRETTY_FUNCTION__, ifp->name,
                                                pim->vrf->name, addr_str);
-                               }
                                continue;
                        }
                }
@@ -877,12 +915,10 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
                if (i == mod_val) {
                        if (PIM_DEBUG_PIM_NHT) {
                                char nexthop_str[PREFIX_STRLEN];
-                               char addr_str[INET_ADDRSTRLEN];
+
                                pim_addr_dump("<nexthop?>",
                                              &nexthop_tab[i].nexthop_addr,
                                              nexthop_str, sizeof(nexthop_str));
-                               pim_inet4_dump("<addr?>", addr, addr_str,
-                                              sizeof(addr_str));
                                zlog_debug(
                                        "%s: found nhop %s for addr %s interface %s(%s) metric %d dist %d",
                                        __PRETTY_FUNCTION__, nexthop_str,
@@ -898,7 +934,7 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
                                nexthop_tab[i].protocol_distance;
                        nexthop->mrib_route_metric =
                                nexthop_tab[i].route_metric;
-                       nexthop->last_lookup = addr;
+                       nexthop->last_lookup = src->u.prefix4;
                        nexthop->last_lookup_time = pim_time_monotonic_usec();
                        nexthop->nbr = nbr;
                        found = 1;
@@ -913,59 +949,36 @@ int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
 }
 
 int pim_ecmp_fib_lookup_if_vif_index(struct pim_instance *pim,
-                                    struct in_addr addr, struct prefix *src,
-                                    struct prefix *grp)
+                                    struct prefix *src, struct prefix *grp)
 {
-       struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM];
-       int num_ifindex;
+       struct pim_nexthop nhop;
        int vif_index;
-       ifindex_t first_ifindex;
-       uint32_t hash_val = 0, mod_val = 0;
+       ifindex_t ifindex;
+       char addr_str[PREFIX_STRLEN];
 
-       memset(nexthop_tab, 0,
-              sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM);
-       num_ifindex = zclient_lookup_nexthop(pim, nexthop_tab, MULTIPATH_NUM,
-                                            addr, PIM_NEXTHOP_LOOKUP_MAX);
-       if (num_ifindex < 1) {
-               if (PIM_DEBUG_PIM_NHT) {
-                       char addr_str[INET_ADDRSTRLEN];
-                       pim_inet4_dump("<addr?>", addr, addr_str,
-                                      sizeof(addr_str));
+       if (PIM_DEBUG_PIM_NHT)
+               pim_inet4_dump("<addr?>", src->u.prefix4, addr_str,
+                              sizeof(addr_str));
+       if (!pim_ecmp_nexthop_lookup(pim, &nhop, src, grp, 0)) {
+               if (PIM_DEBUG_PIM_NHT)
                        zlog_debug(
                                "%s: could not find nexthop ifindex for address %s(%s)",
                                __PRETTY_FUNCTION__, addr_str, pim->vrf->name);
-               }
                return -1;
        }
 
-       // If PIM ECMP enable then choose ECMP path.
-       if (pim->ecmp_enable) {
-               hash_val = pim_compute_ecmp_hash(src, grp);
-               mod_val = hash_val % num_ifindex;
-               if (PIM_DEBUG_PIM_NHT_DETAIL)
-                       zlog_debug("%s: hash_val %u mod_val %u",
-                                  __PRETTY_FUNCTION__, hash_val, mod_val);
-       }
-
-       first_ifindex = nexthop_tab[mod_val].ifindex;
-
-       if (PIM_DEBUG_PIM_NHT) {
-               char addr_str[INET_ADDRSTRLEN];
-               pim_inet4_dump("<ifaddr?>", addr, addr_str, sizeof(addr_str));
+       ifindex = nhop.interface->ifindex;
+       if (PIM_DEBUG_PIM_NHT)
                zlog_debug(
                        "%s: found nexthop ifindex=%d (interface %s(%s)) for address %s",
-                       __PRETTY_FUNCTION__, first_ifindex,
-                       ifindex2ifname(first_ifindex, pim->vrf_id),
+                       __PRETTY_FUNCTION__, ifindex,
+                       ifindex2ifname(ifindex, pim->vrf_id),
                        pim->vrf->name, addr_str);
-       }
 
-       vif_index = pim_if_find_vifindex_by_ifindex(pim, first_ifindex);
+       vif_index = pim_if_find_vifindex_by_ifindex(pim, ifindex);
 
        if (vif_index < 0) {
                if (PIM_DEBUG_PIM_NHT) {
-                       char addr_str[INET_ADDRSTRLEN];
-                       pim_inet4_dump("<addr?>", addr, addr_str,
-                                      sizeof(addr_str));
                        zlog_debug(
                                "%s: low vif_index=%d(%s) < 1 nexthop for address %s",
                                __PRETTY_FUNCTION__, vif_index, pim->vrf->name,
index 77e25dcd7095a9a5243c1cf32505a0037da8b911..796fbf9731943f2ca58278527ba516341455d630 100644 (file)
@@ -61,13 +61,11 @@ int pim_ecmp_nexthop_search(struct pim_instance *pim,
                            struct pim_nexthop *nexthop, struct prefix *src,
                            struct prefix *grp, int neighbor_needed);
 int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
-                           struct pim_nexthop *nexthop, struct in_addr addr,
-                           struct prefix *src, struct prefix *grp,
-                           int neighbor_needed);
+                           struct pim_nexthop *nexthop, struct prefix *src,
+                           struct prefix *grp, int neighbor_needed);
 void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient,
                           struct pim_nexthop_cache *pnc, int command);
 void pim_resolve_upstream_nh(struct pim_instance *pim, struct prefix *nht_p);
 int pim_ecmp_fib_lookup_if_vif_index(struct pim_instance *pim,
-                                    struct in_addr addr, struct prefix *src,
-                                    struct prefix *grp);
+                                    struct prefix *src, struct prefix *grp);
 #endif
index 7e053d2aa01c36c8293951dbe99900a59bd2c049..cc39b09043609e69af2bef09d46251753301ed7b 100644 (file)
@@ -477,10 +477,9 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
                                            &rp_all->group, 1))
                                        return PIM_RP_NO_PATH;
                        } else {
-                               if (pim_nexthop_lookup(
+                               if (!pim_ecmp_nexthop_lookup(
                                            pim, &rp_all->rp.source_nexthop,
-                                           rp_all->rp.rpf_addr.u.prefix4, 1)
-                                   != 0)
+                                           &nht_p, &rp_all->group, 1))
                                        return PIM_RP_NO_PATH;
                        }
                        pim_rp_check_interfaces(pim, rp_all);
@@ -556,9 +555,8 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
                                             &nht_p, &rp_info->group, 1))
                        return PIM_RP_NO_PATH;
        } else {
-               if (pim_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
-                                      rp_info->rp.rpf_addr.u.prefix4, 1)
-                   != 0)
+               if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
+                                            &nht_p, &rp_info->group, 1))
                        return PIM_RP_NO_PATH;
        }
 
@@ -687,9 +685,9 @@ void pim_rp_setup(struct pim_instance *pim)
                                        "%s: NHT Local Nexthop not found for RP %s ",
                                        __PRETTY_FUNCTION__, buf);
                        }
-                       if (pim_nexthop_lookup(
-                                   pim, &rp_info->rp.source_nexthop,
-                                   rp_info->rp.rpf_addr.u.prefix4, 1) < 0)
+                       if (!pim_ecmp_nexthop_lookup(pim,
+                                                    &rp_info->rp.source_nexthop,
+                                                     &nht_p, &rp_info->group, 1))
                                if (PIM_DEBUG_PIM_NHT_RP)
                                        zlog_debug(
                                                "Unable to lookup nexthop for rp specified");
@@ -854,8 +852,9 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group)
                                        __PRETTY_FUNCTION__, buf, buf1);
                        }
                        pim_rpf_set_refresh_time(pim);
-                       pim_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
-                                          rp_info->rp.rpf_addr.u.prefix4, 1);
+                       pim_ecmp_nexthop_lookup(pim,
+                                               &rp_info->rp.source_nexthop,
+                                               &nht_p, &rp_info->group, 1);
                }
                return (&rp_info->rp);
        }
index da14e8b3eb9528f6d0884ffa9c483683efd9cfec..b02102c8fd88c80f671ec589e9e562e3bd967070 100644 (file)
@@ -203,6 +203,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
        struct prefix nht_p;
        struct pim_nexthop_cache pnc;
        struct prefix src, grp;
+       bool neigh_needed = true;
 
        saved.source_nexthop = rpf->source_nexthop;
        saved.rpf_addr = rpf->rpf_addr;
@@ -226,23 +227,20 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
        grp.prefixlen = IPV4_MAX_BITLEN;
        grp.u.prefix4 = up->sg.grp;
        memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
+
+       if ((up->sg.src.s_addr == INADDR_ANY && I_am_RP(pim, up->sg.grp)) ||
+           PIM_UPSTREAM_FLAG_TEST_FHR(up->flags))
+               neigh_needed = FALSE;
        if (pim_find_or_track_nexthop(pim, &nht_p, up, NULL, &pnc)) {
                if (pnc.nexthop_num) {
-                       if (!pim_ecmp_nexthop_search(
-                                   pim, &pnc, &up->rpf.source_nexthop, &src,
-                                   &grp,
-                                   !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)
-                                           && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(
-                                                      up->flags)))
+                       if (!pim_ecmp_nexthop_search(pim, &pnc,
+                                                    &up->rpf.source_nexthop,
+                                                    &src, &grp, neigh_needed))
                                return PIM_RPF_FAILURE;
                }
        } else {
-               if (!pim_ecmp_nexthop_lookup(
-                           pim, &rpf->source_nexthop, up->upstream_addr, &src,
-                           &grp,
-                           !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)
-                                   && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(
-                                              up->flags)))
+               if (!pim_ecmp_nexthop_lookup(pim, &rpf->source_nexthop, &src,
+                                            &grp, neigh_needed))
                        return PIM_RPF_FAILURE;
        }
 
index eddb4c7763cfa556faed6a6bef61be91291287c7..b947ca06256b1d8c52740ed67932e0cc230ba94d 100644 (file)
@@ -561,7 +561,7 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
                                __PRETTY_FUNCTION__, source_str, group_str);
                }
                input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(
-                       c_oil->pim, vif_source, &src, &grp);
+                       c_oil->pim, &src, &grp);
        }
 
        if (input_iface_vif_index < 1) {
@@ -964,8 +964,8 @@ void igmp_source_forward_start(struct pim_instance *pim,
                        }
                } else
                        input_iface_vif_index =
-                               pim_ecmp_fib_lookup_if_vif_index(
-                                       pim, vif_source, &src, &grp);
+                               pim_ecmp_fib_lookup_if_vif_index(pim, &src,
+                                                                &grp);
 
                if (PIM_DEBUG_ZEBRA) {
                        char buf2[INET_ADDRSTRLEN];
@@ -1154,7 +1154,7 @@ void pim_forward_start(struct pim_ifchannel *ch)
                /* Register addr with Zebra NHT */
                nht_p.family = AF_INET;
                nht_p.prefixlen = IPV4_MAX_BITLEN;
-               nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
+               nht_p.u.prefix4 = up->upstream_addr;
                grp.family = AF_INET;
                grp.prefixlen = IPV4_MAX_BITLEN;
                grp.u.prefix4 = up->sg.grp;
@@ -1205,8 +1205,8 @@ void pim_forward_start(struct pim_ifchannel *ch)
                        }
                } else
                        input_iface_vif_index =
-                               pim_ecmp_fib_lookup_if_vif_index(
-                                       pim, up->upstream_addr, &src, &grp);
+                               pim_ecmp_fib_lookup_if_vif_index(pim, &src,
+                                                                &grp);
 
                if (input_iface_vif_index < 1) {
                        if (PIM_DEBUG_PIM_TRACE) {
index e2be7050d7ad98f406d79b4ae90ae14401f27aa5..85fb309048e9bfc4fe220cd9d425d02cebc51fb1 100644 (file)
@@ -370,6 +370,10 @@ ln -s %{_sbindir}/frr %{buildroot}%{_initddir}/frr
 %endif
 
 install %{zeb_rh_src}/daemons %{buildroot}%{_sysconfdir}/frr
+# add rpki module to daemon
+%if %{with_rpki}
+    sed -i -e 's/^\(bgpd_options=\)\(.*\)\(".*\)/\1\2 -M rpki\3/' %{buildroot}%{_sysconfdir}/frr/daemons
+%endif
 install -m644 %{zeb_rh_src}/frr.pam %{buildroot}%{_sysconfdir}/pam.d/frr
 install -m644 %{zeb_rh_src}/frr.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/frr
 install -d -m750 %{buildroot}%{rundir}
index 5b90b7046c6e5fad8985c6c096e3f467fd955c6f..c8368b39b613985f3c0ed8d99b28e32fdedd72d1 100644 (file)
@@ -21,6 +21,7 @@ TAGS
 __pycache__
 .pytest_cache
 /bgpd/test_aspath
+/bgpd/test_bgp_table
 /bgpd/test_capability
 /bgpd/test_ecommunity
 /bgpd/test_mp_attr
index 32d2db768a0fa8e19aa6a8e3d3a3b5918e345672..a7dec67348218df46fecb8927998c576fe371187 100644 (file)
@@ -21,7 +21,8 @@ TESTS_BGPD = \
        bgpd/test_peer_attr \
        bgpd/test_ecommunity \
        bgpd/test_mp_attr \
-       bgpd/test_mpath
+       bgpd/test_mpath \
+       bgpd/test_bgp_table
 else
 TESTS_BGPD =
 endif
@@ -143,6 +144,7 @@ bgpd_test_peer_attr_SOURCES = bgpd/test_peer_attr.c
 bgpd_test_ecommunity_SOURCES = bgpd/test_ecommunity.c
 bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c
 bgpd_test_mpath_SOURCES = bgpd/test_mpath.c
+bgpd_test_bgp_table_SOURCES = bgpd/test_bgp_table.c
 isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv.c
 nodist_isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv_tests.h
 BUILT_SOURCES=isisd/test_fuzz_isis_tlv_tests.h
@@ -186,6 +188,7 @@ bgpd_test_peer_attr_LDADD = $(BGP_TEST_LDADD)
 bgpd_test_ecommunity_LDADD = $(BGP_TEST_LDADD)
 bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD)
 bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD)
+bgpd_test_bgp_table_LDADD = $(BGP_TEST_LDADD)
 isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD)
 isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD)
 ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD)
diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c
new file mode 100644 (file)
index 0000000..01ce748
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * BGP Routing table range lookup test
+ * Copyright (C) 2012 OSR.
+ * Copyright (C) 2018 Marcel Röthke (marcel.roethke@haw-hamburg.de), for HAW
+ * Hamburg
+ *
+ * This file is part of FRRouting
+ *
+ * Quagga 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.
+ *
+ * Quagga 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 "table.h"
+#include "bgpd/bgp_table.h"
+#include "linklist.h"
+
+/*
+ * test_node_t
+ *
+ * Information that is kept for each node in the radix tree.
+ */
+struct test_node_t {
+
+       /*
+        * Human readable representation of the string. Allocated using
+        * malloc()/dup().
+        */
+       char *prefix_str;
+};
+
+/*
+ * add_node
+ *
+ * Add the given prefix (passed in as a string) to the given table.
+ */
+static void add_node(struct bgp_table *table, const char *prefix_str)
+{
+       struct prefix_ipv4 p;
+       struct test_node_t *node;
+       struct bgp_node *rn;
+
+       assert(prefix_str);
+
+       if (str2prefix_ipv4(prefix_str, &p) <= 0)
+               assert(0);
+
+       rn = bgp_node_get(table, (struct prefix *)&p);
+       if (rn->info) {
+               assert(0);
+               return;
+       }
+
+       node = malloc(sizeof(struct test_node_t));
+       assert(node);
+       node->prefix_str = strdup(prefix_str);
+       assert(node->prefix_str);
+       rn->info = node;
+}
+
+static void print_range_result(struct list *list)
+{
+
+       struct listnode *listnode;
+       struct bgp_node *bnode;
+
+       for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) {
+               char buf[PREFIX2STR_BUFFER];
+
+               prefix2str(&bnode->p, buf, PREFIX2STR_BUFFER);
+               printf("%s\n", buf);
+       }
+}
+
+static void check_lookup_result(struct list *list, va_list arglist)
+{
+       char *prefix_str;
+       unsigned int prefix_count = 0;
+
+       printf("Searching results\n");
+       while ((prefix_str = va_arg(arglist, char *))) {
+               struct listnode *listnode;
+               struct bgp_node *bnode;
+               struct prefix p;
+               bool found = false;
+
+               prefix_count++;
+               printf("Searching for %s\n", prefix_str);
+
+               if (str2prefix(prefix_str, &p) <= 0)
+                       assert(0);
+
+               for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) {
+                       if (prefix_same(&bnode->p, &p))
+                               found = true;
+               }
+
+               assert(found);
+       }
+
+       printf("Checking for unexpected result items\n");
+       printf("Expecting %d found %d\n", prefix_count, listcount(list));
+       assert(prefix_count == listcount(list));
+}
+
+static void do_test(struct bgp_table *table, const char *prefix, uint8_t maxlen,
+                   ...)
+{
+       va_list arglist;
+       struct list *list = list_new();
+       struct prefix p;
+
+       list->del = (void (*)(void *))bgp_unlock_node;
+
+       va_start(arglist, maxlen);
+       printf("\nDoing lookup for %s-%d\n", prefix, maxlen);
+       if (str2prefix(prefix, &p) <= 0)
+               assert(0);
+       bgp_table_range_lookup(table, &p, maxlen, list);
+       print_range_result(list);
+
+       check_lookup_result(list, arglist);
+
+       list_delete_and_null(&list);
+
+       va_end(arglist);
+
+       printf("Checks successfull\n");
+}
+
+/*
+ * test_range_lookup
+ */
+static void test_range_lookup(void)
+{
+       struct bgp_table *table = bgp_table_init(NULL, AFI_IP, SAFI_UNICAST);
+
+       printf("Testing bgp_table_range_lookup\n");
+
+       printf("Setup bgp_table");
+       const char *prefixes[] = {"1.16.0.0/16",   "1.16.128.0/18",
+                                 "1.16.192.0/18", "1.16.64.0/19",
+                                 "1.16.160.0/19", "1.16.32.0/20",
+                                 "1.16.32.0/21",  "16.0.0.0/16"};
+
+       int num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]);
+
+       for (int i = 0; i < num_prefixes; i++)
+               add_node(table, prefixes[i]);
+
+       do_test(table, "1.16.0.0/17", 20, "1.16.64.0/19", "1.16.32.0/20", NULL);
+       do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18",
+               "1.16.160.0/19", NULL);
+
+       do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18",
+               "1.16.160.0/19", NULL);
+
+       do_test(table, "1.16.0.0/16", 18, "1.16.0.0/16", "1.16.128.0/18",
+               "1.16.192.0/18", NULL);
+
+       do_test(table, "1.16.0.0/16", 21, "1.16.0.0/16", "1.16.128.0/18",
+               "1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19",
+               "1.16.32.0/20", "1.16.32.0/21", NULL);
+
+       do_test(table, "1.17.0.0/16", 20, NULL);
+
+       do_test(table, "128.0.0.0/8", 16, NULL);
+
+       do_test(table, "16.0.0.0/8", 16, "16.0.0.0/16", NULL);
+
+       do_test(table, "0.0.0.0/3", 21, "1.16.0.0/16", "1.16.128.0/18",
+               "1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19",
+               "1.16.32.0/20", "1.16.32.0/21", "16.0.0.0/16", NULL);
+}
+
+int main(void)
+{
+       test_range_lookup();
+}
diff --git a/tests/bgpd/test_bgp_table.py b/tests/bgpd/test_bgp_table.py
new file mode 100644 (file)
index 0000000..4423530
--- /dev/null
@@ -0,0 +1,7 @@
+import frrtest
+
+class TestTable(frrtest.TestMultiOut):
+    program = './test_bgp_table'
+
+for i in range(6):
+    TestTable.onesimple('Checks successfull')
index 04e85435d157b11a0dabf45c423e8d391cbd203e..53180564bd950364cb84149a2e834aec32d52da0 100644 (file)
@@ -228,7 +228,8 @@ static void test_dump(struct test_state *test)
 }
 
 static void test_failed(struct test_state *test, const char *message,
-                       struct prefix_ipv6 *dst_p, struct prefix_ipv6 *src_p)
+                       const struct prefix_ipv6 *dst_p,
+                       const struct prefix_ipv6 *src_p)
 {
        char *route_id = format_srcdest(dst_p, src_p);
 
@@ -250,7 +251,7 @@ static void test_state_verify(struct test_state *test)
        /* Verify that there are no elements in the table which have never
         * been added */
        for (rn = route_top(test->table); rn; rn = srcdest_route_next(rn)) {
-               struct prefix_ipv6 *dst_p, *src_p;
+               const struct prefix_ipv6 *dst_p, *src_p;
 
                /* While we are iterating, we hold a lock on the current
                 * route_node,
@@ -288,10 +289,10 @@ static void test_state_verify(struct test_state *test)
                                expected_lock++;
 
                        if (rn->lock != expected_lock) {
-                               struct prefix_ipv6 *dst_p, *src_p;
+                               const struct prefix_ipv6 *dst_p, *src_p;
                                srcdest_rnode_prefixes(
-                                       rn, (struct prefix **)&dst_p,
-                                       (struct prefix **)&src_p);
+                                       rn, (const struct prefix **)&dst_p,
+                                       (const struct prefix **)&src_p);
 
                                test_failed(
                                        test,
@@ -305,8 +306,8 @@ static void test_state_verify(struct test_state *test)
 
                assert(rn->info == (void *)0xdeadbeef);
 
-               srcdest_rnode_prefixes(rn, (struct prefix **)&dst_p,
-                                      (struct prefix **)&src_p);
+               srcdest_rnode_prefixes(rn, (const struct prefix **)&dst_p,
+                                      (const struct prefix **)&src_p);
                memcpy(&hash_entry[0], dst_p, sizeof(*dst_p));
                if (src_p)
                        memcpy(&hash_entry[1], src_p, sizeof(*src_p));
@@ -377,7 +378,7 @@ static void test_state_del_one_route(struct test_state *test, struct prng *prng)
        which_route = prng_rand(prng) % test->log->count;
 
        struct route_node *rn;
-       struct prefix *dst_p, *src_p;
+       const struct prefix *dst_p, *src_p;
        struct prefix_ipv6 dst6_p, src6_p;
 
        for (rn = route_top(test->table); rn; rn = srcdest_route_next(rn)) {
index 208fb116e689aced77130b37b4d1e4b5eba6248f..a9f183ed7ba85f2ffd4ecd4b5c14841c2581f407 100755 (executable)
@@ -403,7 +403,7 @@ end
                 self.save_contexts(ctx_keys, current_context_lines)
                 new_ctx = True
 
-            elif line == "end":
+            elif line in ["end", "exit-vrf"]:
                 self.save_contexts(ctx_keys, current_context_lines)
                 log.debug('LINE %-50s: exiting old context, %-50s', line, ctx_keys)
 
index 5c84219418422842abf7cad504a8da98aa8408dd..8f6e31cfa8864a32c7ef868c4b9f9eddd026398f 100644 (file)
@@ -986,7 +986,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        if (tb[IFA_LABEL])
                label = (char *)RTA_DATA(tb[IFA_LABEL]);
 
-       if (ifp && label && strcmp(ifp->name, label) == 0)
+       if (label && strcmp(ifp->name, label) == 0)
                label = NULL;
 
        /* Register interface address to the interface. */
index d9c663184531acb27f873f4ac1664bed917ceb93..8703b013191f8a94edf3355a8bcaf1d300df274a 100644 (file)
@@ -390,8 +390,8 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta,
        }
 }
 
-int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, void *data,
-             unsigned int alen)
+int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
+             const void *data, unsigned int alen)
 {
        int len;
        struct rtattr *rta;
@@ -415,8 +415,8 @@ int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, void *data,
        return 0;
 }
 
-int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, void *data,
-                 unsigned int alen)
+int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
+                 const void *data, unsigned int alen)
 {
        unsigned int len;
        struct rtattr *subrta;
@@ -829,9 +829,6 @@ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup),
        n->nlmsg_seq = ++nl->seq;
        n->nlmsg_pid = nl->snl.nl_pid;
 
-       /* Request an acknowledgement by setting NLM_F_ACK */
-       n->nlmsg_flags |= NLM_F_ACK;
-
        if (IS_ZEBRA_DEBUG_KERNEL)
                zlog_debug(
                        "netlink_talk: %s type %s(%u), len=%d seq=%u flags 0x%x",
@@ -942,12 +939,20 @@ void kernel_init(struct zebra_ns *zns)
        snprintf(zns->netlink.name, sizeof(zns->netlink.name),
                 "netlink-listen (NS %u)", zns->ns_id);
        zns->netlink.sock = -1;
-       netlink_socket(&zns->netlink, groups, zns->ns_id);
+       if (netlink_socket(&zns->netlink, groups, zns->ns_id) < 0) {
+               zlog_err("Failure to create %s socket",
+                        zns->netlink.name);
+               exit(-1);
+       }
 
        snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name),
                 "netlink-cmd (NS %u)", zns->ns_id);
        zns->netlink_cmd.sock = -1;
-       netlink_socket(&zns->netlink_cmd, 0, zns->ns_id);
+       if (netlink_socket(&zns->netlink_cmd, 0, zns->ns_id) < 0) {
+               zlog_err("Failure to create %s socket",
+                        zns->netlink_cmd.name);
+               exit(-1);
+       }
 
        /*
         * SOL_NETLINK is not available on all platforms yet
@@ -969,23 +974,24 @@ void kernel_init(struct zebra_ns *zns)
 #endif
 
        /* Register kernel socket. */
-       if (zns->netlink.sock > 0) {
-               /* Only want non-blocking on the netlink event socket */
-               if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
-                       zlog_err("Can't set %s socket flags: %s",
-                                zns->netlink.name, safe_strerror(errno));
-
-               /* Set receive buffer size if it's set from command line */
-               if (nl_rcvbufsize)
-                       netlink_recvbuf(&zns->netlink, nl_rcvbufsize);
-
-               netlink_install_filter(zns->netlink.sock,
-                                      zns->netlink_cmd.snl.nl_pid);
-               zns->t_netlink = NULL;
-
-               thread_add_read(zebrad.master, kernel_read, zns,
-                               zns->netlink.sock, &zns->t_netlink);
-       }
+       if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0)
+               zlog_err("Can't set %s socket error: %s(%d)",
+                        zns->netlink.name, safe_strerror(errno), errno);
+
+       if (fcntl(zns->netlink_cmd.sock, F_SETFL, O_NONBLOCK) < 0)
+               zlog_err("Can't set %s socket error: %s(%d)",
+                        zns->netlink_cmd.name, safe_strerror(errno), errno);
+
+       /* Set receive buffer size if it's set from command line */
+       if (nl_rcvbufsize)
+               netlink_recvbuf(&zns->netlink, nl_rcvbufsize);
+
+       netlink_install_filter(zns->netlink.sock,
+                              zns->netlink_cmd.snl.nl_pid);
+       zns->t_netlink = NULL;
+
+       thread_add_read(zebrad.master, kernel_read, zns,
+                       zns->netlink.sock, &zns->t_netlink);
 
        rt_netlink_init();
 }
index 3b4048ff6992147cd6c11be6b469ec66f7fb2292..80bb876e0bc328736d5a40bf6c0c6ecdace70a81 100644 (file)
@@ -29,9 +29,9 @@
 extern void netlink_parse_rtattr(struct rtattr **tb, int max,
                                 struct rtattr *rta, int len);
 extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
-                    void *data, unsigned int alen);
+                    const void *data, unsigned int alen);
 extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type,
-                        void *data, unsigned int alen);
+                        const void *data, unsigned int alen);
 extern int addattr16(struct nlmsghdr *n, unsigned int maxlen, int type,
                     uint16_t data);
 extern int addattr32(struct nlmsghdr *n, unsigned int maxlen, int type,
index c5246999fa47ebe5dcd457f44b724716259e7459..3e44a4170759cf0a4e5e8a6938ae97c589c9336a 100644 (file)
@@ -236,15 +236,15 @@ int main(int argc, char **argv)
                "  -z, --socket          Set path of zebra socket\n"
                "  -e, --ecmp            Specify ECMP to use.\n"
                "  -l, --label_socket    Socket to external label manager\n"
-               "  -k, --keep_kernel     Don't delete old routes which installed by zebra.\n"
+               "  -k, --keep_kernel     Don't delete old routes which were installed by zebra.\n"
                "  -r, --retain          When program terminates, retain added route by zebra.\n"
 #ifdef HAVE_NETLINK
-               "  -n, --vrfwnetns       Set VRF with NetNS\n"
+               "  -n, --vrfwnetns       Use NetNS as VRF backend\n"
                "  -s, --nl-bufsize      Set netlink receive buffer size\n"
                "      --v6-rr-semantics Use v6 RR semantics\n"
 #endif /* HAVE_NETLINK */
 #if defined(HANDLE_ZAPI_FUZZING)
-               "  -c <file>             Bypass normal startup use this file for tetsting of zapi"
+               "  -c <file>             Bypass normal startup and use this file for testing of zapi"
 #endif
        );
 
@@ -349,13 +349,6 @@ int main(int argc, char **argv)
 /* For debug purpose. */
 /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
 
-#if defined(HANDLE_ZAPI_FUZZING)
-       if (fuzzing) {
-               zserv_read_file(fuzzing);
-               exit(0);
-       }
-#endif
-
        /* Process the configuration file. Among other configuration
        *  directives we can meet those installing static routes. Such
        *  requests will not be executed immediately, but queued in
@@ -391,6 +384,14 @@ int main(int argc, char **argv)
        /* RNH init */
        zebra_rnh_init();
 
+#if defined(HANDLE_ZAPI_FUZZING)
+       if (fuzzing) {
+               zserv_read_file(fuzzing);
+               exit(0);
+       }
+#endif
+
+
        frr_run(zebrad.master);
 
        /* Not reached... */
index 1fee675cbfb51399b5335ba8747332a07c974ec7..69c0ebb7ec50474d0f996cd661aeae64a16bfbfe 100644 (file)
@@ -113,7 +113,7 @@ static void zebra_redistribute(struct zserv *client, int type,
 
        for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
                RNODE_FOREACH_RE (rn, newre) {
-                       struct prefix *dst_p, *src_p;
+                       const struct prefix *dst_p, *src_p;
                        char buf[PREFIX_STRLEN];
 
                        srcdest_rnode_prefixes(rn, &dst_p, &src_p);
@@ -147,7 +147,7 @@ static void zebra_redistribute(struct zserv *client, int type,
 
 /* Either advertise a route for redistribution to registered clients or */
 /* withdraw redistribution if add cannot be done for client */
-void redistribute_update(struct prefix *p, struct prefix *src_p,
+void redistribute_update(const struct prefix *p, const struct prefix *src_p,
                         struct route_entry *re, struct route_entry *prev_re)
 {
        struct listnode *node, *nnode;
@@ -216,7 +216,7 @@ void redistribute_update(struct prefix *p, struct prefix *src_p,
        }
 }
 
-void redistribute_delete(struct prefix *p, struct prefix *src_p,
+void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
                         struct route_entry *re)
 {
        struct listnode *node, *nnode;
index 9b4820acd493f8b1f8e23601228a41f4bb7d165e..a0fbd13cf96d43a96d31e4fd193784e37b167455 100644 (file)
@@ -36,9 +36,11 @@ extern void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS);
 extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS);
 /* ----------------- */
 
-extern void redistribute_update(struct prefix *, struct prefix *,
+extern void redistribute_update(const struct prefix *p,
+                               const struct prefix *src_p,
                                struct route_entry *, struct route_entry *);
-extern void redistribute_delete(struct prefix *, struct prefix *,
+extern void redistribute_delete(const struct prefix *p,
+                               const struct prefix *src_p,
                                struct route_entry *);
 
 extern void zebra_interface_up_update(struct interface *);
index 209f085ed13d7fc618d6b35096b3c061c6a2990c..6509cdaba79b0b7e0d1efed3153afc7735efc7c3 100644 (file)
@@ -289,7 +289,7 @@ extern int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
 
 extern int is_zebra_valid_kernel_table(uint32_t table_id);
 extern int is_zebra_main_routing_table(uint32_t table_id);
-extern int zebra_check_addr(struct prefix *p);
+extern int zebra_check_addr(const struct prefix *p);
 
 extern void rib_addnode(struct route_node *rn, struct route_entry *re,
                        int process);
index ad1fe9a1f57704432b8cc55329419cdd9279b0a3..57e62e4f6ee5cc9963ce6ab5ee8e719bc5abb6b2 100644 (file)
@@ -67,8 +67,8 @@ enum dp_req_result {
  * a re-add.
  */
 extern enum dp_req_result kernel_route_rib(struct route_node *rn,
-                                          struct prefix *p,
-                                          struct prefix *src_p,
+                                          const struct prefix *p,
+                                          const struct prefix *src_p,
                                           struct route_entry *old,
                                           struct route_entry *new);
 
@@ -77,7 +77,8 @@ extern enum dp_req_result kernel_route_rib(struct route_node *rn,
  * so let's separate it out and allow the result to
  * be passed back up.
  */
-extern void kernel_route_rib_pass_fail(struct route_node *rn, struct prefix *p,
+extern void kernel_route_rib_pass_fail(struct route_node *rn,
+                                      const struct prefix *p,
                                       struct route_entry *re,
                                       enum dp_results res);
 
index 90334915491e1c9f69c51314602c78fbf4386b3d..485abc3f1230331d214f325be3922f6af3a0fb3d 100644 (file)
@@ -483,7 +483,9 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
                                memcpy(&nh.gate, gate, sz);
 
                        if (index) {
-                               ifp = if_lookup_by_index(index, VRF_UNKNOWN);
+                               ifp = if_lookup_by_index_per_ns(
+                                               zebra_ns_lookup(ns_id),
+                                               index);
                                if (ifp)
                                        nh_vrf_id = ifp->vrf_id;
                        }
@@ -526,8 +528,9 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
                                         * using the last one looked
                                         * up right now
                                         */
-                                       ifp = if_lookup_by_index(index,
-                                                                VRF_UNKNOWN);
+                                       ifp = if_lookup_by_index_per_ns(
+                                                       zebra_ns_lookup(ns_id),
+                                                       index);
                                        if (ifp)
                                                nh_vrf_id = ifp->vrf_id;
                                        else {
@@ -1287,8 +1290,8 @@ _netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe,
  * @param zvrf: The vrf we are in
  * @param tableid: The table we are working on
  */
-static void _netlink_route_debug(int cmd, struct prefix *p,
-                                int family, struct zebra_vrf *zvrf,
+static void _netlink_route_debug(int cmd, const struct prefix *p,
+                                int family, vrf_id_t vrfid,
                                 uint32_t tableid)
 {
        if (IS_ZEBRA_DEBUG_KERNEL) {
@@ -1297,7 +1300,7 @@ static void _netlink_route_debug(int cmd, struct prefix *p,
                        "netlink_route_multipath(): %s %s vrf %u(%u)",
                        nl_msg_type_to_str(cmd),
                        prefix2str(p, buf, sizeof(buf)),
-                       zvrf_id(zvrf), tableid);
+                       vrfid, tableid);
        }
 }
 
@@ -1340,8 +1343,9 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
 
 /* Routing table change via netlink interface. */
 /* Update flag indicates whether this is a "replace" or not. */
-static int netlink_route_multipath(int cmd, struct prefix *p,
-                                  struct prefix *src_p, struct route_entry *re,
+static int netlink_route_multipath(int cmd, const struct prefix *p,
+                                  const struct prefix *src_p,
+                                  struct route_entry *re,
                                   int update)
 {
        int bytelen;
@@ -1416,7 +1420,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p,
                addattr32(&req.n, sizeof req, RTA_TABLE, re->table);
        }
 
-       _netlink_route_debug(cmd, p, family, zvrf, re->table);
+       _netlink_route_debug(cmd, p, family, zvrf_id(zvrf), re->table);
 
        /*
         * If we are not updating the route and we have received
@@ -1699,8 +1703,8 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
 }
 
 enum dp_req_result kernel_route_rib(struct route_node *rn,
-                                   struct prefix *p,
-                                   struct prefix *src_p,
+                                   const struct prefix *p,
+                                   const struct prefix *src_p,
                                    struct route_entry *old,
                                    struct route_entry *new)
 {
index 441f518e9166ff522b7ad7c50dec46a7b5542ec4..cba0376300abe962f47d5fa70108e9e150698bcf 100644 (file)
@@ -386,8 +386,8 @@ static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re)
 }
 
 enum dp_req_result kernel_route_rib(struct route_node *rn,
-                                   struct prefix *p,
-                                   struct prefix *src_p,
+                                   const struct prefix *p,
+                                   const struct prefix *src_p,
                                    struct route_entry *old,
                                    struct route_entry *new)
 {
index 08666bf37dd2316284099188a8081b20bd71282c..c16fa70857d5ac162291e5e406e1a80a5b0e5b3d 100644 (file)
@@ -514,8 +514,9 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp)
        return zserv_send_message(client, s);
 }
 
-int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
-                            struct prefix *src_p, struct route_entry *re)
+int zsend_redistribute_route(int cmd, struct zserv *client,
+                            const struct prefix *p,
+                            const struct prefix *src_p, struct route_entry *re)
 {
        struct zapi_route api;
        struct zapi_nexthop *api_nh;
@@ -677,22 +678,28 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
        return zserv_send_message(client, s);
 }
 
-int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
-                            enum zapi_route_notify_owner note)
+/*
+ * Common utility send route notification, called from a path using a
+ * route_entry and from a path using a dataplane context.
+ */
+static int route_notify_internal(const struct prefix *p, int type,
+                                uint16_t instance, vrf_id_t vrf_id,
+                                uint32_t table_id,
+                                enum zapi_route_notify_owner note)
 {
        struct zserv *client;
        struct stream *s;
        uint8_t blen;
 
-       client = zserv_find_client(re->type, re->instance);
+       client = zserv_find_client(type, instance);
        if (!client || !client->notify_owner) {
                if (IS_ZEBRA_DEBUG_PACKET) {
                        char buff[PREFIX_STRLEN];
 
                        zlog_debug(
                                "Not Notifying Owner: %u about prefix %s(%u) %d vrf: %u",
-                               re->type, prefix2str(p, buff, sizeof(buff)),
-                               re->table, note, re->vrf_id);
+                               type, prefix2str(p, buff, sizeof(buff)),
+                               table_id, note, vrf_id);
                }
                return 0;
        }
@@ -701,14 +708,14 @@ int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
                char buff[PREFIX_STRLEN];
 
                zlog_debug("Notifying Owner: %u about prefix %s(%u) %d vrf: %u",
-                          re->type, prefix2str(p, buff, sizeof(buff)),
-                          re->table, note, re->vrf_id);
+                          type, prefix2str(p, buff, sizeof(buff)),
+                          table_id, note, vrf_id);
        }
 
        s = stream_new(ZEBRA_MAX_PACKET_SIZ);
        stream_reset(s);
 
-       zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, re->vrf_id);
+       zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, vrf_id);
 
        stream_put(s, &note, sizeof(note));
 
@@ -718,13 +725,20 @@ int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
        stream_putc(s, p->prefixlen);
        stream_put(s, &p->u.prefix, blen);
 
-       stream_putl(s, re->table);
+       stream_putl(s, table_id);
 
        stream_putw_at(s, 0, stream_get_endp(s));
 
        return zserv_send_message(client, s);
 }
 
+int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p,
+                            enum zapi_route_notify_owner note)
+{
+       return (route_notify_internal(p, re->type, re->instance, re->vrf_id,
+                                     re->table, note));
+}
+
 void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
                             enum zapi_rule_notify_owner note)
 {
@@ -2820,7 +2834,9 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
                STREAM_GETL(s, ifindex);
 
                if (ifindex) {
-                       zpr.ifp = if_lookup_by_index(ifindex, VRF_UNKNOWN);
+                       zpr.ifp = if_lookup_by_index_per_ns(
+                                               zvrf->zns,
+                                               ifindex);
                        if (!zpr.ifp) {
                                zlog_debug("Failed to lookup ifindex: %u",
                                           ifindex);
index f27897580a98d16e17a23092b91c3ccc15f93684..8289e33c6a66df85e87847637d2cff6e957af1f8 100644 (file)
@@ -56,7 +56,8 @@ extern void nbr_connected_delete_ipv6(struct interface *ifp,
 extern int zsend_interface_update(int cmd, struct zserv *client,
                                  struct interface *ifp);
 extern int zsend_redistribute_route(int cmd, struct zserv *zclient,
-                                   struct prefix *p, struct prefix *src_p,
+                                   const struct prefix *p,
+                                   const struct prefix *src_p,
                                    struct route_entry *re);
 extern int zsend_router_id_update(struct zserv *zclient, struct prefix *p,
                                  vrf_id_t vrf_id);
@@ -65,7 +66,8 @@ extern int zsend_interface_vrf_update(struct zserv *zclient,
 extern int zsend_interface_link_params(struct zserv *zclient,
                                       struct interface *ifp);
 extern int zsend_pw_update(struct zserv *client, struct zebra_pw *pw);
-extern int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
+extern int zsend_route_notify_owner(struct route_entry *re,
+                                   const struct prefix *p,
                                    enum zapi_route_notify_owner note);
 
 extern void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
index fe0837a63a75b6767de74b34bd086b6990fa5a17..cfe208d35b0b9960b544ebc59f673cb58b4c1b81 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "zebra/rib.h"
 #include "zebra/rt.h"
+#include "zebra/interface.h"
 #include "zebra/zserv.h"
 #include "zebra/redistribute.h"
 #include "zebra/debug.h"
@@ -704,6 +705,7 @@ static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe)
 {
        struct nexthop *nexthop;
        struct interface *ifp;
+       struct zebra_ns *zns;
 
        nexthop = nhlfe->nexthop;
        if (!nexthop) // unexpected
@@ -721,7 +723,8 @@ static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe)
                 * which will not be in the default
                 * VRF.  So let's look in all of them
                 */
-               ifp = if_lookup_by_index(nexthop->ifindex, VRF_UNKNOWN);
+               zns = zebra_ns_lookup(NS_DEFAULT);
+               ifp = if_lookup_by_index_per_ns(zns, nexthop->ifindex);
                if (ifp && if_is_operative(ifp))
                        SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
                else
@@ -2752,10 +2755,13 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
 
                                switch (nexthop->type) {
                                case NEXTHOP_TYPE_IFINDEX: {
+                                       struct zebra_ns *zns;
                                        struct interface *ifp;
 
-                                       ifp = if_lookup_by_index(
-                                               nexthop->ifindex, VRF_UNKNOWN);
+                                       zns = zebra_ns_lookup(NS_DEFAULT);
+                                       ifp = if_lookup_by_index_per_ns(
+                                                       zns,
+                                                       nexthop->ifindex);
                                        vty_out(vty, "%15s", ifp->name);
                                        break;
                                }
index d0ea661403d0bdc0ffecce3289ec8a4d3ac540ae..2dd686fd0dbe2bdb3f96d44f82f6b2ed6f4f97a8 100644 (file)
@@ -80,6 +80,8 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name)
        ns_id = zebra_ns_id_get(netnspath);
        if (zserv_privs.change(ZPRIVS_LOWER))
                zlog_err("Can't lower privileges");
+       if (ns_id == NS_UNKNOWN)
+               return;
        ns_id_external = ns_map_nsid_with_external(ns_id, true);
        /* if VRF with NS ID already present */
        vrf = vrf_lookup_by_id((vrf_id_t)ns_id_external);
@@ -103,6 +105,7 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name)
        if (ret != CMD_SUCCESS) {
                zlog_warn("NS notify : failed to create NS %s", netnspath);
                ns_map_nsid_with_external(ns_id, false);
+               vrf_delete(vrf);
                return;
        }
        zlog_info("NS notify : created VRF %s NS %s", name, netnspath);
index 8c23bf34cf1670c080003fafe9dc4ece86d73fb9..5975c4058b99b2454b5b624fbb1486f211de5edf 100644 (file)
@@ -615,7 +615,7 @@ static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt)
 
 int zebra_ptm_sock_read(struct thread *thread)
 {
-       int sock, done = 0;
+       int sock;
        int rc;
 
        errno = 0;
@@ -625,28 +625,24 @@ int zebra_ptm_sock_read(struct thread *thread)
                return -1;
 
        /* PTM communicates in CSV format */
-       while (!done) {
+       do {
                rc = ptm_lib_process_msg(ptm_hdl, sock, ptm_cb.in_data,
                                         ZEBRA_PTM_MAX_SOCKBUF, NULL);
-               if (rc <= 0)
-                       break;
-       }
+       } while (rc > 0);
 
-       if (rc <= 0) {
-               if (((rc == 0) && !errno)
-                   || (errno && (errno != EWOULDBLOCK) && (errno != EAGAIN))) {
-                       zlog_warn("%s routing socket error: %s(%d) bytes %d",
-                                 __func__, safe_strerror(errno), errno, rc);
-
-                       close(ptm_cb.ptm_sock);
-                       ptm_cb.ptm_sock = -1;
-                       zebra_ptm_reset_status(0);
-                       ptm_cb.t_timer = NULL;
-                       thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
-                                        ptm_cb.reconnect_time,
-                                        &ptm_cb.t_timer);
-                       return (-1);
-               }
+       if (((rc == 0) && !errno)
+           || (errno && (errno != EWOULDBLOCK) && (errno != EAGAIN))) {
+               zlog_warn("%s routing socket error: %s(%d) bytes %d",
+                         __func__, safe_strerror(errno), errno, rc);
+
+               close(ptm_cb.ptm_sock);
+               ptm_cb.ptm_sock = -1;
+               zebra_ptm_reset_status(0);
+               ptm_cb.t_timer = NULL;
+               thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
+                                ptm_cb.reconnect_time,
+                                &ptm_cb.t_timer);
+               return (-1);
        }
 
        ptm_cb.t_read = NULL;
index 8935956b2572f94a3e4d02a01ea9e63c4cd8a1c2..9bf6bfa22f08d949d19879a43408b744315e49f4 100644 (file)
@@ -156,7 +156,7 @@ int is_zebra_main_routing_table(uint32_t table_id)
        return 0;
 }
 
-int zebra_check_addr(struct prefix *p)
+int zebra_check_addr(const struct prefix *p)
 {
        if (p->family == AF_INET) {
                uint32_t addr;
@@ -325,7 +325,7 @@ struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re,
        return nexthop;
 }
 
-static void nexthop_set_resolved(afi_t afi, struct nexthop *newhop,
+static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop,
                                 struct nexthop *nexthop)
 {
        struct nexthop *resolved_hop;
@@ -843,7 +843,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
        route_map_result_t ret = RMAP_MATCH;
        int family;
        char buf[SRCDEST2STR_BUFFER];
-       struct prefix *p, *src_p;
+       const struct prefix *p, *src_p;
        srcdest_rnode_prefixes(rn, &p, &src_p);
 
        if (rn->p.family == AF_INET)
@@ -1012,7 +1012,7 @@ int zebra_rib_labeled_unicast(struct route_entry *re)
        return 1;
 }
 
-void kernel_route_rib_pass_fail(struct route_node *rn, struct prefix *p,
+void kernel_route_rib_pass_fail(struct route_node *rn, const struct prefix *p,
                                struct route_entry *re,
                                enum dp_results res)
 {
@@ -1085,7 +1085,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
 {
        struct nexthop *nexthop;
        rib_table_info_t *info = srcdest_rnode_table_info(rn);
-       struct prefix *p, *src_p;
+       const struct prefix *p, *src_p;
        struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
 
        srcdest_rnode_prefixes(rn, &p, &src_p);
@@ -1143,7 +1143,7 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
 {
        struct nexthop *nexthop;
        rib_table_info_t *info = srcdest_rnode_table_info(rn);
-       struct prefix *p, *src_p;
+       const struct prefix *p, *src_p;
        struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
 
        srcdest_rnode_prefixes(rn, &p, &src_p);
@@ -1194,7 +1194,8 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
        }
 
        if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
-               struct prefix *p, *src_p;
+               const struct prefix *p, *src_p;
+
                srcdest_rnode_prefixes(rn, &p, &src_p);
 
                redistribute_delete(p, src_p, re);
@@ -1536,7 +1537,8 @@ static void rib_process(struct route_node *rn)
        char buf[SRCDEST2STR_BUFFER];
        rib_dest_t *dest;
        struct zebra_vrf *zvrf = NULL;
-       struct prefix *p, *src_p;
+       const struct prefix *p, *src_p;
+
        srcdest_rnode_prefixes(rn, &p, &src_p);
        vrf_id_t vrf_id = VRF_UNKNOWN;
 
index ce51f54a65b7d7d68d13abe3857e2aff9b163486..bf6718164f087d9b7d6217f632dc6fae5fe91d82 100644 (file)
@@ -1337,7 +1337,8 @@ void zebra_route_map_write_delay_timer(struct vty *vty)
 }
 
 route_map_result_t zebra_route_map_check(int family, int rib_type,
-                                        uint8_t instance, struct prefix *p,
+                                        uint8_t instance,
+                                        const struct prefix *p,
                                         struct nexthop *nexthop,
                                         vrf_id_t vrf_id, route_tag_t tag)
 {
@@ -1358,7 +1359,8 @@ route_map_result_t zebra_route_map_check(int family, int rib_type,
                rmap = route_map_lookup_by_name(
                        proto_rm[family][ZEBRA_ROUTE_MAX]);
        if (rmap) {
-               ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
+               ret = route_map_apply(rmap, (struct prefix *)p,
+                                     RMAP_ZEBRA, &nh_obj);
        }
 
        return (ret);
index 20d425a2bcebb81a45844572b937bffb2b70f668..688c8b7203d2544f94de5d95c6300e254e86f41e 100644 (file)
@@ -40,7 +40,7 @@ zebra_import_table_route_map_check(int family, int rib_type, uint8_t instance,
                                   const char *rmap_name);
 extern route_map_result_t
 zebra_route_map_check(int family, int rib_type, uint8_t instance,
-                     struct prefix *p, struct nexthop *nexthop,
+                     const struct prefix *p, struct nexthop *nexthop,
                      vrf_id_t vrf_id, route_tag_t tag);
 extern route_map_result_t
 zebra_nht_route_map_check(int family, int client_proto, struct prefix *p,
index 67b2954f35799e5770ae7c6a45f7af8048b74be4..76346f6b663e62aced2cd8f5a4bfeb33afeffddb 100644 (file)
@@ -37,8 +37,9 @@
 #include "zebra/zebra_memory.h"
 
 /* Install static route into rib. */
-void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
-                         struct prefix_ipv6 *src_p, struct static_route *si)
+void static_install_route(afi_t afi, safi_t safi, const struct prefix *p,
+                         const struct prefix_ipv6 *src_p,
+                         struct static_route *si)
 {
        struct route_entry *re;
        struct route_node *rn;
@@ -292,8 +293,9 @@ static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si)
 }
 
 /* Uninstall static route from RIB. */
-void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
-                           struct prefix_ipv6 *src_p, struct static_route *si)
+void static_uninstall_route(afi_t afi, safi_t safi, const struct prefix *p,
+                           const struct prefix_ipv6 *src_p,
+                           struct static_route *si)
 {
        struct route_node *rn;
        struct route_entry *re;
@@ -610,7 +612,7 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
        struct route_table *stable;
        struct route_node *rn;
        struct static_route *si;
-       struct prefix *p, *src_pp;
+       const struct prefix *p, *src_pp;
        struct prefix_ipv6 *src_p;
        struct vrf *vrf;
 
index 7dc47d6190d5227c559a4e9138546ec005bb3200..0be434fff2220e9eea14b1fc714b74567852d031 100644 (file)
@@ -82,11 +82,12 @@ struct static_route {
        uint32_t table_id;
 };
 
-extern void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
-                                struct prefix_ipv6 *src_p,
+extern void static_install_route(afi_t afi, safi_t safi, const struct prefix *p,
+                                const struct prefix_ipv6 *src_p,
                                 struct static_route *si);
-extern void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p,
-                                  struct prefix_ipv6 *src_p,
+extern void static_uninstall_route(afi_t afi, safi_t safi,
+                                  const struct prefix *p,
+                                  const struct prefix_ipv6 *src_p,
                                   struct static_route *si);
 
 extern int static_add_route(afi_t, safi_t safi, uint8_t type, struct prefix *p,
index 55c4f6e916b1106a6cfe10969e9bc56d748590fc..8ee47d2f1b6508c6864eebedb3802dbf8508b2d7 100644 (file)
@@ -1198,7 +1198,8 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
                                break;
                        }
 
-                       if (re->vrf_id != nexthop->vrf_id) {
+                       if ((re->vrf_id != nexthop->vrf_id)
+                            && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
                                struct vrf *vrf =
                                        vrf_lookup_by_id(nexthop->vrf_id);
 
@@ -1415,7 +1416,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
                                break;
                        }
 
-                       if (nexthop->vrf_id != re->vrf_id) {
+                       if ((nexthop->vrf_id != re->vrf_id)
+                            && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
                                struct vrf *vrf =
                                        vrf_lookup_by_id(nexthop->vrf_id);
 
@@ -1569,7 +1571,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
                        break;
                }
 
-               if (nexthop->vrf_id != re->vrf_id) {
+               if ((nexthop->vrf_id != re->vrf_id)
+                    && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
                        struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
 
                        if (vrf)
@@ -1651,7 +1654,7 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
                json = json_object_new_object();
 
        /* Show all routes. */
-       for (rn = route_top(table); rn; rn = route_next(rn)) {
+       for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
                dest = rib_dest_from_rnode(rn);
 
                RNODE_FOREACH_RE (rn, re) {
index 434a1507ae713004ed8ae053a5d490df2da4e422..4c90757d70489e02ac6c42d0cb60fc8685c8b5f1 100644 (file)
@@ -69,7 +69,7 @@ extern struct zebra_privs_t zserv_privs;
  * Client thread events.
  *
  * These are used almost exclusively by client threads to drive their own event
- * loops. The only exception is in zebra_client_create(), which pushes an
+ * loops. The only exception is in zserv_client_create(), which pushes an
  * initial ZSERV_CLIENT_READ event to start the API handler loop.
  */
 enum zserv_client_event {
@@ -640,7 +640,7 @@ static int zserv_handle_client_close(struct thread *thread)
  * sock
  *    client's socket file descriptor
  */
-static void zserv_client_create(int sock)
+static struct zserv *zserv_client_create(int sock)
 {
        struct zserv *client;
        int i;
@@ -696,6 +696,8 @@ static void zserv_client_create(int sock)
 
        /* start pthread */
        frr_pthread_run(client->pthread, NULL);
+
+       return client;
 }
 
 /*
@@ -1025,20 +1027,10 @@ void zserv_read_file(char *input)
        struct zserv *client = NULL;
        struct thread t;
 
-       zebra_client_create(-1);
-
-       frr_pthread_stop(client->pthread, NULL);
-       frr_pthread_destroy(client->pthread);
-       client->pthread = NULL;
-
-       t.arg = client;
-
        fd = open(input, O_RDONLY | O_NONBLOCK);
        t.u.fd = fd;
 
-       zserv_read(&t);
-
-       close(fd);
+       zserv_client_create(fd);
 }
 #endif