summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am20
-rw-r--r--bgpd/bgp_mplsvpn.c68
-rw-r--r--bgpd/bgp_mplsvpn.h10
-rw-r--r--bgpd/bgp_rpki.c181
-rw-r--r--bgpd/bgp_table.c62
-rw-r--r--bgpd/bgp_table.h4
-rw-r--r--bgpd/bgp_vty.c8
-rwxr-xr-xconfigure.ac16
-rw-r--r--doc/Makefile.am1
-rw-r--r--doc/developer/maintainer-release-build.rst89
-rw-r--r--doc/developer/workflow.rst31
-rw-r--r--doc/user/installation.rst9
-rw-r--r--doc/user/rpki.rst3
-rw-r--r--docker/alpine/Dockerfile-coverage12
-rw-r--r--lib/if.c12
-rw-r--r--lib/nexthop_group.h5
-rw-r--r--lib/srcdest_table.c33
-rw-r--r--lib/srcdest_table.h13
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile.am5
-rw-r--r--tests/bgpd/test_bgp_table.c192
-rw-r--r--tests/bgpd/test_bgp_table.py7
-rw-r--r--tests/lib/test_srcdest_table.c17
-rw-r--r--zebra/kernel_netlink.c58
-rw-r--r--zebra/kernel_netlink.h4
-rw-r--r--zebra/redistribute.c6
-rw-r--r--zebra/redistribute.h6
-rw-r--r--zebra/rib.h2
-rw-r--r--zebra/rt.h7
-rw-r--r--zebra/rt_netlink.c26
-rw-r--r--zebra/rt_socket.c4
-rw-r--r--zebra/zapi_msg.c40
-rw-r--r--zebra/zapi_msg.h6
-rw-r--r--zebra/zebra_mpls.c12
-rw-r--r--zebra/zebra_rib.c18
-rw-r--r--zebra/zebra_routemap.c6
-rw-r--r--zebra/zebra_routemap.h2
-rw-r--r--zebra/zebra_static.c12
-rw-r--r--zebra/zebra_static.h9
-rw-r--r--zebra/zserv.c4
40 files changed, 883 insertions, 138 deletions
diff --git a/Makefile.am b/Makefile.am
index 5dc80b4983..ed22c60e7c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -115,3 +115,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
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 847129fbe5..f72104dd33 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -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);
+ }
+}
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index 384108dc0c..b0add40da9 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -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 */
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 317d451b6d..774c484784 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -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);
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index 613b924d0d..94e2d83cfe 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -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);
+ }
+ }
+ }
+}
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index 388c247227..60c2cbd4a4 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -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 */
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 641628d4b7..e9d9a846af 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -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.
*/
}
diff --git a/configure.ac b/configure.ac
index 3ec29cc38f..8846fcdf71 100755
--- a/configure.ac
+++ b/configure.ac
@@ -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 ------------------------------------
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 1f27e4a8e7..62cb3c2edb 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -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
index 0000000000..907bd14ee6
--- /dev/null
+++ b/doc/developer/maintainer-release-build.rst
@@ -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)
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index b29769da49..cd03d2733d 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -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
========================
diff --git a/doc/user/installation.rst b/doc/user/installation.rst
index 26d30f1e10..158e2c8595 100644
--- a/doc/user/installation.rst
+++ b/doc/user/installation.rst
@@ -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/`
diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst
index 93a8e4396a..c35928db07 100644
--- a/doc/user/rpki.rst
+++ b/doc/user/rpki.rst
@@ -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:
diff --git a/docker/alpine/Dockerfile-coverage b/docker/alpine/Dockerfile-coverage
new file mode 100644
index 0000000000..5fdb1179b0
--- /dev/null
+++ b/docker/alpine/Dockerfile-coverage
@@ -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" ]
diff --git a/lib/if.c b/lib/if.c
index 2541e6e45a..2320093a15 100644
--- 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;
diff --git a/lib/nexthop_group.h b/lib/nexthop_group.h
index a44f4e3542..473ecb34fc 100644
--- a/lib/nexthop_group.h
+++ b/lib/nexthop_group.h
@@ -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;
diff --git a/lib/srcdest_table.c b/lib/srcdest_table.c
index a70574cff2..32f8e8ca5b 100644
--- a/lib/srcdest_table.c
+++ b/lib/srcdest_table.c
@@ -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);
diff --git a/lib/srcdest_table.h b/lib/srcdest_table.h
index 669068a79b..5f97f02bac 100644
--- a/lib/srcdest_table.h
+++ b/lib/srcdest_table.h
@@ -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);
diff --git a/tests/.gitignore b/tests/.gitignore
index 5b90b7046c..c8368b39b6 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -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
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 32d2db768a..a7dec67348 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 0000000000..01ce7480d7
--- /dev/null
+++ b/tests/bgpd/test_bgp_table.c
@@ -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
index 0000000000..4423530fe0
--- /dev/null
+++ b/tests/bgpd/test_bgp_table.py
@@ -0,0 +1,7 @@
+import frrtest
+
+class TestTable(frrtest.TestMultiOut):
+ program = './test_bgp_table'
+
+for i in range(6):
+ TestTable.onesimple('Checks successfull')
diff --git a/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c
index 04e85435d1..53180564bd 100644
--- a/tests/lib/test_srcdest_table.c
+++ b/tests/lib/test_srcdest_table.c
@@ -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)) {
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index d9c6631845..8703b01319 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -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();
}
diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h
index 3b4048ff69..80bb876e0b 100644
--- a/zebra/kernel_netlink.h
+++ b/zebra/kernel_netlink.h
@@ -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,
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 1fee675cbf..69c0ebb7ec 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -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;
diff --git a/zebra/redistribute.h b/zebra/redistribute.h
index 9b4820acd4..a0fbd13cf9 100644
--- a/zebra/redistribute.h
+++ b/zebra/redistribute.h
@@ -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 *);
diff --git a/zebra/rib.h b/zebra/rib.h
index 209f085ed1..6509cdaba7 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -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);
diff --git a/zebra/rt.h b/zebra/rt.h
index ad1fe9a1f5..57e62e4f6e 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -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);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 9033491549..485abc3f12 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -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)
{
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 441f518e91..cba0376300 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -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)
{
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 08666bf37d..c16fa70857 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -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);
diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h
index f27897580a..8289e33c6a 100644
--- a/zebra/zapi_msg.h
+++ b/zebra/zapi_msg.h
@@ -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,
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index fe0837a63a..cfe208d35b 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -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;
}
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 8935956b25..9bf6bfa22f 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -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;
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index ce51f54a65..bf6718164f 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -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);
diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h
index 20d425a2bc..688c8b7203 100644
--- a/zebra/zebra_routemap.h
+++ b/zebra/zebra_routemap.h
@@ -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,
diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c
index 67b2954f35..76346f6b66 100644
--- a/zebra/zebra_static.c
+++ b/zebra/zebra_static.c
@@ -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;
diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h
index 7dc47d6190..0be434fff2 100644
--- a/zebra/zebra_static.h
+++ b/zebra/zebra_static.h
@@ -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,
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 434a1507ae..b08da9cebd 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -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 {
@@ -1025,7 +1025,7 @@ void zserv_read_file(char *input)
struct zserv *client = NULL;
struct thread t;
- zebra_client_create(-1);
+ zserv_client_create(-1);
frr_pthread_stop(client->pthread, NULL);
frr_pthread_destroy(client->pthread);