diff options
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" ] @@ -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, ¬e, 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); |
