summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/base-branch-label.yml20
-rw-r--r--bgpd/bgp_packet.c1
-rw-r--r--bgpd/bgp_rpki.c204
-rw-r--r--debian/changelog6
-rw-r--r--doc/user/overview.rst2
-rw-r--r--doc/user/rpki.rst6
-rw-r--r--docker/alpine/Dockerfile7
-rw-r--r--docker/centos-7/Dockerfile8
-rw-r--r--docker/centos-8/Dockerfile6
-rw-r--r--docker/ubi-8/Dockerfile6
-rw-r--r--redhat/frr.spec.in88
-rw-r--r--tests/topotests/bgp_gr_notification/__init__.py0
-rw-r--r--tests/topotests/bgp_gr_notification/r1/bgpd.conf10
-rw-r--r--tests/topotests/bgp_gr_notification/r1/zebra.conf9
-rw-r--r--tests/topotests/bgp_gr_notification/r2/bgpd.conf11
-rw-r--r--tests/topotests/bgp_gr_notification/r2/zebra.conf9
-rw-r--r--tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py224
-rw-r--r--tests/topotests/cspf_topo1/reference/sharp-ted.json2
-rw-r--r--tests/topotests/pbr_topo1/test_pbr_topo1.py12
19 files changed, 563 insertions, 68 deletions
diff --git a/.github/workflows/base-branch-label.yml b/.github/workflows/base-branch-label.yml
new file mode 100644
index 0000000000..9572ee7ee2
--- /dev/null
+++ b/.github/workflows/base-branch-label.yml
@@ -0,0 +1,20 @@
+name: Add base branch label
+
+on:
+ pull_request:
+ types:
+ - opened
+ - reopened
+
+jobs:
+ label:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: write
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions-ecosystem/action-add-labels@v1
+ with:
+ labels: |
+ ${{ github.event.pull_request.base.ref }}
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index c8996ba634..5560469838 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -733,7 +733,6 @@ static void bgp_write_notify(struct peer *peer)
/* Type should be notify. */
atomic_fetch_add_explicit(&peer->notify_out, 1, memory_order_relaxed);
- peer->notify_out++;
/* Double start timer. */
peer->v_start *= 2;
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 97e94a97ce..c28b81a413 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -1194,14 +1194,6 @@ DEFUN (show_rpki_prefix_table,
RPKI_OUTPUT_STRING
"Show validated prefixes which were received from RPKI Cache\n")
{
- struct listnode *cache_node;
- struct cache *cache;
-
- for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
- vty_out(vty, "host: %s port: %s\n",
- cache->tr_config.tcp_config->host,
- cache->tr_config.tcp_config->port);
- }
if (is_synchronized())
print_prefix_table(vty);
else
@@ -1278,62 +1270,137 @@ DEFPY (show_rpki_prefix,
return CMD_SUCCESS;
}
-DEFUN (show_rpki_cache_server,
+DEFPY (show_rpki_cache_server,
show_rpki_cache_server_cmd,
- "show rpki cache-server",
+ "show rpki cache-server [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
- "SHOW configured cache server\n")
+ "Show configured cache server\n"
+ JSON_STR)
{
+ struct json_object *json = NULL;
+ struct json_object *json_server = NULL;
+ struct json_object *json_servers = NULL;
struct listnode *cache_node;
struct cache *cache;
+ if (uj) {
+ json = json_object_new_object();
+ json_servers = json_object_new_array();
+ json_object_object_add(json, "servers", json_servers);
+ }
+
for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
if (cache->type == TCP) {
- vty_out(vty, "host: %s port: %s\n",
- cache->tr_config.tcp_config->host,
- cache->tr_config.tcp_config->port);
+ if (!json) {
+ vty_out(vty, "host: %s port: %s\n",
+ cache->tr_config.tcp_config->host,
+ cache->tr_config.tcp_config->port);
+ } else {
+ json_server = json_object_new_object();
+ json_object_string_add(json_server, "mode",
+ "tcp");
+ json_object_string_add(
+ json_server, "host",
+ cache->tr_config.tcp_config->host);
+ json_object_string_add(
+ json_server, "port",
+ cache->tr_config.tcp_config->port);
+ json_object_array_add(json_servers,
+ json_server);
+ }
#if defined(FOUND_SSH)
} else if (cache->type == SSH) {
- vty_out(vty,
- "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s\n",
- cache->tr_config.ssh_config->host,
- cache->tr_config.ssh_config->port,
- cache->tr_config.ssh_config->username,
- cache->tr_config.ssh_config
- ->server_hostkey_path,
- cache->tr_config.ssh_config
- ->client_privkey_path);
+ if (!json) {
+ vty_out(vty,
+ "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s\n",
+ cache->tr_config.ssh_config->host,
+ cache->tr_config.ssh_config->port,
+ cache->tr_config.ssh_config->username,
+ cache->tr_config.ssh_config
+ ->server_hostkey_path,
+ cache->tr_config.ssh_config
+ ->client_privkey_path);
+ } else {
+ json_server = json_object_new_object();
+ json_object_string_add(json_server, "mode",
+ "ssh");
+ json_object_string_add(
+ json_server, "host",
+ cache->tr_config.ssh_config->host);
+ json_object_int_add(
+ json_server, "port",
+ cache->tr_config.ssh_config->port);
+ json_object_string_add(
+ json_server, "username",
+ cache->tr_config.ssh_config->username);
+ json_object_string_add(
+ json_server, "serverHostkeyPath",
+ cache->tr_config.ssh_config
+ ->server_hostkey_path);
+ json_object_string_add(
+ json_server, "clientPrivkeyPath",
+ cache->tr_config.ssh_config
+ ->client_privkey_path);
+ json_object_array_add(json_servers,
+ json_server);
+ }
#endif
}
}
+ if (json)
+ vty_json(vty, json);
+
return CMD_SUCCESS;
}
-DEFUN (show_rpki_cache_connection,
+DEFPY (show_rpki_cache_connection,
show_rpki_cache_connection_cmd,
- "show rpki cache-connection",
+ "show rpki cache-connection [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
- "Show to which RPKI Cache Servers we have a connection\n")
+ "Show to which RPKI Cache Servers we have a connection\n"
+ JSON_STR)
{
+ struct json_object *json = NULL;
+ struct json_object *json_conn = NULL;
+ struct json_object *json_conns = NULL;
+ struct listnode *cache_node;
+ struct cache *cache;
+ struct rtr_mgr_group *group;
+
+ if (uj)
+ json = json_object_new_object();
+
if (!is_synchronized()) {
- vty_out(vty, "No connection to RPKI cache server.\n");
+ if (!json)
+ vty_out(vty, "No connection to RPKI cache server.\n");
+ else
+ vty_json(vty, json);
return CMD_SUCCESS;
}
- struct listnode *cache_node;
- struct cache *cache;
- struct rtr_mgr_group *group = get_connected_group();
-
+ group = get_connected_group();
if (!group) {
- vty_out(vty, "Cannot find a connected group.\n");
+ if (!json)
+ vty_out(vty, "Cannot find a connected group.\n");
+ else
+ vty_json(vty, json);
+
return CMD_SUCCESS;
}
- vty_out(vty, "Connected to group %d\n", group->preference);
+
+ if (!json) {
+ vty_out(vty, "Connected to group %d\n", group->preference);
+ } else {
+ json_conns = json_object_new_array();
+ json_object_int_add(json, "connectedGroup", group->preference);
+ json_object_object_add(json, "connections", json_conns);
+ }
+
for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
struct tr_tcp_config *tcp_config;
#if defined(FOUND_SSH)
@@ -1342,22 +1409,66 @@ DEFUN (show_rpki_cache_connection,
switch (cache->type) {
case TCP:
tcp_config = cache->tr_config.tcp_config;
- vty_out(vty, "rpki tcp cache %s %s pref %hhu%s\n",
- tcp_config->host, tcp_config->port,
- cache->preference,
- cache->rtr_socket->state == RTR_ESTABLISHED
- ? " (connected)"
- : "");
+
+ if (!json) {
+ vty_out(vty,
+ "rpki tcp cache %s %s pref %hhu%s\n",
+ tcp_config->host, tcp_config->port,
+ cache->preference,
+ cache->rtr_socket->state ==
+ RTR_ESTABLISHED
+ ? " (connected)"
+ : "");
+ } else {
+ json_conn = json_object_new_object();
+ json_object_string_add(json_conn, "mode",
+ "tcp");
+ json_object_string_add(json_conn, "host",
+ tcp_config->host);
+ json_object_string_add(json_conn, "port",
+ tcp_config->port);
+ json_object_int_add(json_conn, "preference",
+ cache->preference);
+ json_object_string_add(
+ json_conn, "state",
+ cache->rtr_socket->state ==
+ RTR_ESTABLISHED
+ ? "connected"
+ : "disconnected");
+ json_object_array_add(json_conns, json_conn);
+ }
break;
#if defined(FOUND_SSH)
case SSH:
ssh_config = cache->tr_config.ssh_config;
- vty_out(vty, "rpki ssh cache %s %u pref %hhu%s\n",
- ssh_config->host, ssh_config->port,
- cache->preference,
- cache->rtr_socket->state == RTR_ESTABLISHED
- ? " (connected)"
- : "");
+
+ if (!json) {
+ vty_out(vty,
+ "rpki ssh cache %s %u pref %hhu%s\n",
+ ssh_config->host, ssh_config->port,
+ cache->preference,
+ cache->rtr_socket->state ==
+ RTR_ESTABLISHED
+ ? " (connected)"
+ : "");
+ } else {
+ json_conn = json_object_new_object();
+ json_object_string_add(json_conn, "mode",
+ "ssh");
+ json_object_string_add(json_conn, "host",
+ ssh_config->host);
+ json_object_int_add(json_conn, "port",
+ ssh_config->port);
+ json_object_int_add(json_conn, "preference",
+ cache->preference);
+ json_object_string_add(
+ json_conn, "state",
+ cache->rtr_socket->state ==
+ RTR_ESTABLISHED
+ ? "connected"
+ : "disconnected");
+ json_object_array_add(json_conns, json_conn);
+ }
break;
#endif
default:
@@ -1365,6 +1476,9 @@ DEFUN (show_rpki_cache_connection,
}
}
+ if (json)
+ vty_json(vty, json);
+
return CMD_SUCCESS;
}
diff --git a/debian/changelog b/debian/changelog
index f3e42199de..0661ffbb97 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -4,6 +4,12 @@ frr (8.3~dev-1) UNRELEASED; urgency=medium
-- Donatas Abraitis <donatas.abraitis@gmail.com> Tue, 01 Feb 2022 11:00:00 +0200
+frr (8.2-0) UNRELEASED; urgency=medium
+
+ * New upstream release FRR 8.2
+
+ -- Jafar Al-Gharaibeh <jafar@atcorp.com> Tue, 01 Mar 2022 10:00:00 +0500
+
frr (8.1-0) unstable; urgency=medium
* New upstream release FRR 8.1
diff --git a/doc/user/overview.rst b/doc/user/overview.rst
index 516650641a..9bcd2af346 100644
--- a/doc/user/overview.rst
+++ b/doc/user/overview.rst
@@ -519,7 +519,7 @@ Bug Reports
For information on reporting bugs, please see :ref:`bug-reports`.
-.. _frr: |PACKAGE_URL|
+.. _frr: https://frrouting.org
.. _github: https://github.com/frrouting/frr/
.. _github issues: https://github.com/frrouting/frr/issues
.. _slack: https://frrouting.org/community
diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst
index c2f8ad1268..ece788d9e3 100644
--- a/doc/user/rpki.rst
+++ b/doc/user/rpki.rst
@@ -216,10 +216,14 @@ Displaying RPKI
received from the cache servers and stored in the router. Based on this data,
the router validates BGP Updates.
-.. clicmd:: show rpki cache-connection
+.. clicmd:: show rpki cache-server [json]
Display all configured cache servers, whether active or not.
+.. clicmd:: show rpki cache-connection [json]
+
+ Display all cache connections, and show which is connected or not.
+
.. clicmd:: show bgp [afi] [safi] <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> rpki <valid|invalid|notfound>
Display for the specified prefix or address the bgp paths that match the given rpki state.
diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile
index 79ae315679..fa4b9859b9 100644
--- a/docker/alpine/Dockerfile
+++ b/docker/alpine/Dockerfile
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Create a basic stage set up to build APKs
-FROM alpine:3.13 as alpine-builder
+FROM alpine:3.15 as alpine-builder
RUN apk add \
--update-cache \
abuild \
@@ -22,7 +22,7 @@ RUN cd /libyang \
&& abuild -r -P /pkgs/apk
# This stage builds a dist tarball from the source
-FROM alpine:3.13 as source-builder
+FROM alpine:3.15 as source-builder
RUN mkdir -p /src/alpine
COPY alpine/APKBUILD.in /src/alpine
@@ -33,6 +33,7 @@ RUN source /src/alpine/APKBUILD.in \
$makedepends \
gzip \
py-pip \
+ rtrlib \
&& pip install pytest
RUN mkdir -p /pkgs/apk
@@ -66,7 +67,7 @@ RUN cd /dist \
&& abuild -r -P /pkgs/apk
# This stage installs frr from the apk
-FROM alpine:3.13
+FROM alpine:3.15
RUN mkdir -p /pkgs/apk
COPY --from=frr-apk-builder /pkgs/apk/ /pkgs/apk/
RUN apk add \
diff --git a/docker/centos-7/Dockerfile b/docker/centos-7/Dockerfile
index 73097df8fa..2d1ee9efa4 100644
--- a/docker/centos-7/Dockerfile
+++ b/docker/centos-7/Dockerfile
@@ -4,11 +4,11 @@ RUN yum install -y epel-release
RUN yum install -y rpm-build autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig \
json-c-devel pam-devel bison flex pytest c-ares-devel \
- python3-devel python3-sphinx libcap-devel \
+ python3-devel python3-sphinx libcap-devel systemd-devel \
https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-7-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el7.x86_64.rpm \
https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-7-x86_64-Packages/libyang2-devel-2.0.0.10.g2eb910e4-1.el7.x86_64.rpm \
- https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm \
- https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-devel-0.7.0-1.el7.centos.x86_64.rpm
+ https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-0.8.0-1.el7.x86_64.rpm \
+ https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-devel-0.8.0-1.el7.x86_64.rpm
COPY . /src
ARG PKGVER
@@ -33,7 +33,7 @@ RUN echo '%_smp_mflags %( echo "-j$(/usr/bin/getconf _NPROCESSORS_ONLN)"; )' >>
FROM centos:centos7
RUN mkdir -p /pkgs/rpm \
&& yum install -y https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-7-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el7.x86_64.rpm \
- https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm
+ https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-0.8.0-1.el7.x86_64.rpm
COPY --from=centos-7-builder /rpmbuild/RPMS/ /pkgs/rpm/
diff --git a/docker/centos-8/Dockerfile b/docker/centos-8/Dockerfile
index df095edcde..df772b8318 100644
--- a/docker/centos-8/Dockerfile
+++ b/docker/centos-8/Dockerfile
@@ -11,8 +11,8 @@ RUN dnf install --enablerepo=powertools -y rpm-build git autoconf pcre-devel \
c-ares-devel python3-devel python3-sphinx libcap-devel platform-python-devel \
https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \
https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-devel-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \
- https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm \
- https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-devel-0.7.0-1.el7.centos.x86_64.rpm
+ https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-0.8.0-1.el7.x86_64.rpm \
+ https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-devel-0.8.0-1.el7.x86_64.rpm
COPY . /src
@@ -42,7 +42,7 @@ RUN sed -i -e "s|mirrorlist=|#mirrorlist=|g" /etc/yum.repos.d/CentOS-* \
RUN mkdir -p /pkgs/rpm \
&& yum install -y https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \
- https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm
+ https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-0.8.0-1.el7.x86_64.rpm
COPY --from=centos-8-builder /rpmbuild/RPMS/ /pkgs/rpm/
diff --git a/docker/ubi-8/Dockerfile b/docker/ubi-8/Dockerfile
index 7b2db66ede..1d1e8bdc6e 100644
--- a/docker/ubi-8/Dockerfile
+++ b/docker/ubi-8/Dockerfile
@@ -16,8 +16,8 @@ RUN dnf install -qy https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.
libcap-devel platform-python-devel \
https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \
https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-devel-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \
- https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm \
- https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-devel-0.7.0-1.el7.centos.x86_64.rpm
+ https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-0.8.0-1.el7.x86_64.rpm \
+ https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-devel-0.8.0-1.el7.x86_64.rpm
COPY . /src
@@ -60,7 +60,7 @@ RUN rpm --import https://www.centos.org/keys/RPM-GPG-KEY-CentOS-Official \
RUN dnf install -qy https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm \
&& mkdir -p /pkgs/rpm \
&& dnf install --enablerepo=* -qy https://ci1.netdef.org/artifact/LIBYANG-LIBYANGV2/shared/build-2/CentOS-8-x86_64-Packages/libyang2-2.0.0.10.g2eb910e4-1.el8.x86_64.rpm \
- https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-110/CentOS-7-x86_64-Packages/librtr-0.7.0-1.el7.centos.x86_64.rpm
+ https://ci1.netdef.org/artifact/RPKI-RTRLIB/shared/build-00146/CentOS-7-x86_64-Packages/librtr-0.8.0-1.el7.x86_64.rpm
COPY --from=ubi-8-builder /rpmbuild/RPMS/ /pkgs/rpm/
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 0753940595..c479a7d4cf 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -774,9 +774,91 @@ sed -i 's/ -M rpki//' %{_sysconfdir}/frr/daemons
%changelog
-* Tue Nov 4 2021 Martin Winter <mwinter@opensourcerouting.org> - %{version}
-
-* Tue Feb 1 2022 Donatas Abraitis <donatas.abraitis@gmail.com> - 8.2
+* Tue Mar 1 2022 Martin Winter <mwinter@opensourcerouting.org> - %{version}
+
+* Tue Mar 1 2022 Jafar Al-Gharaibeh <jafar@atcorp.com> - 8.2
+- The FRRouting community would like to announce FRR Release 8.2.
+- This release consists of just over 800 commits from 62 authors.
+- Selected features and bug fixes are listed below.
+- babeld:
+- Fix the checks for truncated packets
+- bfdd:
+- Correct one spelling error of comment
+- Fix detection timeout update
+- Fix possibly wrong counter of control packets
+- bgpd:
+- Add "json" option to a few more show commands
+- Add 'show bgp <afi> <safi> json detail' header data
+- Add a 6 hour warning to missing policy
+- Add an ability to match ipv6 next-hop by prefix-list
+- Add autocomplete for access-list under bmp node
+- Add autocomplete for as-path filters
+- Add autocomplete for set/match community/large/ext lists
+- Add long-lived graceful restart capability
+- Add peer-groups to neighbor autocomplete
+- Adjust symbolic names for cease notifications according to rfc4486
+- Deprecate dpa, advertiser and rcid_path path attributes
+- Extended bgp administrative shutdown communication
+- Fix crash when using "show bgp vrf all"
+- Fix inconsistency of match ip/ipv6 next-hop commands
+- Fix missing name of default vrf
+- Handle TCP connection errors with connection callbacks for RPKI
+- Implement llgr helper mode
+- Implement rfc9072
+- Support redirect import more than one route-target ipv6
+- docker:
+- Update alpine build enable set own version
+- isisd:
+- Add link state traffic engineering support
+- Fix router capability tlv parsing issues
+- Fix running-config for fast-reroute
+- Make isis work with default vrf name different than 'default'
+- ospf6d
+- Add missing vrf parameter to "clear ipv6 ospf6 interface"
+- Add prompt for commands with non-exist vrf
+- Add support for nssa type-7 address ranges
+- Add the ability of specifying router-id/area-id in no debug ospf6
+- Do not originate type-4 lsa when nssa
+- Do not send type-5 into stub area
+- Fix ecmp inter-area route nexthop update
+- Fix memory leak for `show ipv6 ospf6 zebra json`
+- ospfd
+- Fix wrong comparison of routemap name
+- Fix crash on "ospf send-extra-data zebra"
+- Fix incorrect detection of topology changes in helper mode
+- Fix loss of mixed form in "range" command
+- Fix no-form of "graceful-restart" command
+- Fix summary-address deletion
+- Fix wrong parsing of te subtlv
+- pbrd
+- Add vlan actions to vty
+- Pbr route maps get addr family of nhgs
+- Protect from a possible null dereference
+- pimd
+- Do not allow 224.0.0.0/24 range in igmp join
+- Fix igmp user config
+- Fix msdp mesh grp with wildcard member addr
+- Fix stale forwarding entries left around after join goes away
+- Fix FRR drops IGMP packets for TOS value other than 0XC0
+- redhat
+- Check if frr.conf already exists
+- Logrotate file has typo for staticd
+- ripd
+- Fix packet send for non primary addresses
+- vtysh
+- Add missing rpki node when showing config
+- Improve startup time by ca. ×6
+- remove `address-family evpn`
+- watchfrr
+- Allow an integrated config to work within a namespace
+- zebra
+- Add optional nhg id output to `show ip ro`
+- Add resolver flag for nexthop in json
+- Add support for json output in srv6 locator detail command
+- Don't lose next hop weights while exporting via fpm
+- Fix buffer overflow
+- Fix netns deletion
+- Fix route-map application when when using vrfs
* Tue Nov 2 2021 Jafar Al-Gharaibeh <jafar@atcorp.com> - 8.1
- FRR 8.1 brings a long list of enhancements and fixes with 1200 commits from
diff --git a/tests/topotests/bgp_gr_notification/__init__.py b/tests/topotests/bgp_gr_notification/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_gr_notification/__init__.py
diff --git a/tests/topotests/bgp_gr_notification/r1/bgpd.conf b/tests/topotests/bgp_gr_notification/r1/bgpd.conf
new file mode 100644
index 0000000000..6119f67436
--- /dev/null
+++ b/tests/topotests/bgp_gr_notification/r1/bgpd.conf
@@ -0,0 +1,10 @@
+router bgp 65001
+ no bgp ebgp-requires-policy
+ bgp graceful-restart
+ neighbor 192.168.255.2 remote-as external
+ neighbor 192.168.255.2 timers 1 3
+ neighbor 192.168.255.2 timers connect 1
+ address-family ipv4
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_gr_notification/r1/zebra.conf b/tests/topotests/bgp_gr_notification/r1/zebra.conf
new file mode 100644
index 0000000000..091794f475
--- /dev/null
+++ b/tests/topotests/bgp_gr_notification/r1/zebra.conf
@@ -0,0 +1,9 @@
+!
+interface lo
+ ip address 172.16.255.1/32
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_gr_notification/r2/bgpd.conf b/tests/topotests/bgp_gr_notification/r2/bgpd.conf
new file mode 100644
index 0000000000..05e17f0564
--- /dev/null
+++ b/tests/topotests/bgp_gr_notification/r2/bgpd.conf
@@ -0,0 +1,11 @@
+router bgp 65002
+ no bgp ebgp-requires-policy
+ no bgp hard-administrative-reset
+ bgp graceful-restart
+ neighbor 192.168.255.1 remote-as external
+ neighbor 192.168.255.1 timers 1 3
+ neighbor 192.168.255.1 timers connect 1
+ address-family ipv4
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_gr_notification/r2/zebra.conf b/tests/topotests/bgp_gr_notification/r2/zebra.conf
new file mode 100644
index 0000000000..1fcccbe161
--- /dev/null
+++ b/tests/topotests/bgp_gr_notification/r2/zebra.conf
@@ -0,0 +1,9 @@
+!
+interface lo
+ ip address 172.16.255.2/32
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py b/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py
new file mode 100644
index 0000000000..3519e5cc7b
--- /dev/null
+++ b/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py
@@ -0,0 +1,224 @@
+#!/usr/bin/env python
+
+#
+# bgp_gr_notification.py
+#
+# Copyright (c) 2022 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+TC1: Disable the link between R1-R2 and wait for HoldTimerExpire notification:
+ 1) Check if R2 sent HoldTimerExpired notification
+ 2) Check if the routes are retained at R2
+TC2: Trigger `clear bgp` (Administrative Reset):
+ `bgp hard-administrative-reset` disabled:
+ a) Check if Administrative Reset notification was sent from R2
+ b) Routes should be retained on R1
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 3):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_hold_timer_expired_gr():
+ # TC1
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
+ expected = {
+ "192.168.255.1": {
+ "bgpState": "Established",
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _disable_link_r1_r2():
+ r1.cmd_raises("ip link set down dev r1-eth0")
+
+ def _enable_link_r1_r2():
+ r1.cmd_raises("ip link set up dev r1-eth0")
+
+ def _bgp_check_hold_timer_expire_reason():
+ output = json.loads(r2.vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
+ expected = {
+ "192.168.255.1": {
+ "lastNotificationReason": "Hold Timer Expired",
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_hold_timer_expire_stale():
+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast 172.16.255.1/32 json"))
+ expected = {
+ "paths": [
+ {
+ "stale": True,
+ "valid": True,
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ step("Initial BGP converge")
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP convergence on R2"
+
+ step("Disable the link between R1-R2")
+ _disable_link_r1_r2()
+
+ step("Check if R2 sent HoldTimerExpire notification to R1")
+ test_func = functools.partial(_bgp_check_hold_timer_expire_reason)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see Hold Timer Expired notification from R2 on R1"
+
+ step("Check if the routes are retained at R2")
+ test_func = functools.partial(_bgp_check_hold_timer_expire_stale)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see retained stale routes on R2"
+
+ step("Enable the link between R1-R2")
+ _enable_link_r1_r2()
+
+
+def test_bgp_administrative_reset_gr():
+ # TC2
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
+ expected = {
+ "192.168.255.1": {
+ "bgpState": "Established",
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_hard_reset():
+ output = json.loads(r1.vtysh_cmd("show ip bgp neighbor 192.168.255.2 json"))
+ expected = {
+ "192.168.255.2": {
+ "lastNotificationReason": "Cease/Administrative Reset",
+ "lastNotificationHardReset": False,
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_gr_notification_stale():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast 172.16.255.2/32 json"))
+ expected = {
+ "paths": [
+ {
+ "stale": True,
+ "valid": True,
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_clear_r1_and_shutdown():
+ r2.vtysh_cmd(
+ """
+ clear ip bgp 192.168.255.1
+ configure terminal
+ router bgp
+ neighbor 192.168.255.1 shutdown
+ """
+ )
+
+ step("Initial BGP converge")
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP convergence on R2"
+
+ step("Reset and shutdown R1")
+ _bgp_clear_r1_and_shutdown()
+
+ step("Check if Hard Reset notification wasn't sent from R2")
+ test_func = functools.partial(_bgp_check_hard_reset)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to send Administrative Reset notification from R2"
+
+ step("Check if stale routes are retained on R1")
+ test_func = functools.partial(_bgp_check_gr_notification_stale)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see retained stale routes on R1"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/cspf_topo1/reference/sharp-ted.json b/tests/topotests/cspf_topo1/reference/sharp-ted.json
index db50260ac7..d3d1f9e406 100644
--- a/tests/topotests/cspf_topo1/reference/sharp-ted.json
+++ b/tests/topotests/cspf_topo1/reference/sharp-ted.json
@@ -269,7 +269,6 @@
},
"segment-routing":[
{
- "adj-sid":5001,
"flags":"0xb0",
"weight":0
}
@@ -666,7 +665,6 @@
},
"segment-routing":[
{
- "adj-sid":5000,
"flags":"0x30",
"weight":0
}
diff --git a/tests/topotests/pbr_topo1/test_pbr_topo1.py b/tests/topotests/pbr_topo1/test_pbr_topo1.py
index 586d9217d2..8506a15135 100644
--- a/tests/topotests/pbr_topo1/test_pbr_topo1.py
+++ b/tests/topotests/pbr_topo1/test_pbr_topo1.py
@@ -234,15 +234,23 @@ def test_rule_linux_installation():
logger.info("Checking for installed PBR rules in OS")
+ def _get_router_rules(router, expected):
+ actual = topotest.ip_rules(router)
+
+ logger.info(actual)
+ return topotest.json_cmp(actual, expected)
+
router_list = tgen.routers().values()
for router in router_list:
rules_file = "{}/{}/linux-rules.json".format(CWD, router.name)
- actual = topotest.ip_rules(router)
expected = json.loads(open(rules_file).read())
+ test_func = partial(_get_router_rules, router, expected)
+
+ _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
assertmsg = "Router {} OS rules mismatch".format(router.name)
- assert topotest.json_cmp(actual, expected) is None, assertmsg
+ assert result is None, assertmsg
if __name__ == "__main__":